예제 #1
0
def v_id_eq_hyps (v_ids):
	groups = logic.dict_list ([(k, v) for (v, k) in v_ids.iteritems ()])
	hyps = []
	for vs in groups.itervalues ():
		for v in vs[1:]:
			hyps.append (mk_eq (v, vs[0]))
	return hyps
예제 #2
0
def candidate_additional_eqs(p, split):
    eq_vals = set()

    def visitor(expr):
        if expr.is_op('Equals') and expr.vals[0].typ.kind == 'Word':
            [x, y] = expr.vals
            eq_vals.update([(x, y), (y, x)])

    for n in p.loop_body(split):
        p.nodes[n].visit(lambda x: (), visitor)
    for (x, y) in list(eq_vals):
        if is_zero(x) and y.is_op('Plus'):
            [x, y] = y.vals
            eq_vals.add((x, syntax.mk_uminus(y)))
            eq_vals.add((y, syntax.mk_uminus(x)))
        elif is_zero(x) and y.is_op('Minus'):
            [x, y] = y.vals
            eq_vals.add((x, y))
            eq_vals.add((y, x))

    loop = syntax.mk_var('%i', syntax.word32T)
    minus_loop_step = syntax.mk_uminus(loop)

    vas = search.get_loop_var_analysis_at(p, split)
    ls_vas = dict([(var, [data]) for (var, data) in vas
                   if data[0] == 'LoopLinearSeries'])
    cmp_series = [(x, y, rew, offs) for (x, y) in eq_vals
                  for (_, rew, offs) in ls_vas.get(x, [])]
    odd_eqs = []
    for (x, y, rew, offs) in cmp_series:
        x_init_cmp1 = syntax.mk_less_eq(x, rew(x, minus_loop_step))
        x_init_cmp2 = syntax.mk_less_eq(rew(x, minus_loop_step), x)
        fin_cmp1 = syntax.mk_less(x, y)
        fin_cmp2 = syntax.mk_less(y, x)
        odd_eqs.append(syntax.mk_eq(x_init_cmp1, fin_cmp1))
        odd_eqs.append(syntax.mk_eq(x_init_cmp2, fin_cmp1))
        odd_eqs.append(syntax.mk_eq(x_init_cmp1, fin_cmp2))
        odd_eqs.append(syntax.mk_eq(x_init_cmp2, fin_cmp2))

    ass_eqs = []
    var_deps = p.compute_var_dependencies()
    for hook in target_objects.hooks('extra_wcet_assertions'):
        for assn in hook(var_deps[split]):
            ass_eqs.append(assn)

    return odd_eqs + ass_eqs
예제 #3
0
	def add_local_def (self, n, vname, name, val, env):
		if self.local_defs_unsat:
			smt_name = self.solv.add_var (name, val.typ)
			eq = mk_eq (mk_smt_expr (smt_name, val.typ), val)
			self.solv.assert_fact (eq, env, unsat_tag
				= ('Def', n, vname))
		else:
			smt_name = self.solv.add_def (name, val, env)
		return smt_name
예제 #4
0
def candidate_additional_eqs(p, split):
    eq_vals = set()

    def visitor(expr):
        if expr.is_op("Equals") and expr.vals[0].typ.kind == "Word":
            [x, y] = expr.vals
            eq_vals.update([(x, y), (y, x)])

    for n in p.loop_body(split):
        p.nodes[n].visit(lambda x: (), visitor)
    for (x, y) in list(eq_vals):
        if is_zero(x) and y.is_op("Plus"):
            [x, y] = y.vals
            eq_vals.add((x, syntax.mk_uminus(y)))
            eq_vals.add((y, syntax.mk_uminus(x)))
        elif is_zero(x) and y.is_op("Minus"):
            [x, y] = y.vals
            eq_vals.add((x, y))
            eq_vals.add((y, x))

    loop = syntax.mk_var("%i", syntax.word32T)
    minus_loop_step = syntax.mk_uminus(loop)

    vas = search.get_loop_var_analysis_at(p, split)
    ls_vas = dict([(var, [data]) for (var, data) in vas if data[0] == "LoopLinearSeries"])
    cmp_series = [(x, y, rew, offs) for (x, y) in eq_vals for (_, rew, offs) in ls_vas.get(x, [])]
    odd_eqs = []
    for (x, y, rew, offs) in cmp_series:
        x_init_cmp1 = syntax.mk_less_eq(x, rew(x, minus_loop_step))
        x_init_cmp2 = syntax.mk_less_eq(rew(x, minus_loop_step), x)
        fin_cmp1 = syntax.mk_less(x, y)
        fin_cmp2 = syntax.mk_less(y, x)
        odd_eqs.append(syntax.mk_eq(x_init_cmp1, fin_cmp1))
        odd_eqs.append(syntax.mk_eq(x_init_cmp2, fin_cmp1))
        odd_eqs.append(syntax.mk_eq(x_init_cmp1, fin_cmp2))
        odd_eqs.append(syntax.mk_eq(x_init_cmp2, fin_cmp2))

    ass_eqs = []
    var_deps = p.compute_var_dependencies()
    for hook in target_objects.hooks("extra_wcet_assertions"):
        for assn in hook(var_deps[split]):
            ass_eqs.append(assn)

    return odd_eqs + ass_eqs
예제 #5
0
def convert_recursion_idents (idents):
	asm_idents = {}
	for f in idents:
		if f not in pre_pairings:
			continue
		f2 = pre_pairings[f]['ASM']
		assert f2 != f
		asm_idents[f2] = []
		for ident in idents[f]:
			if ident.is_op ('True'):
				asm_idents[f2].append (ident)
			elif ident.is_op ('Equals'):
				[x, y] = ident.vals
				# this is a bit hacky
				[i] = [i for (i, (nm, typ))
					in enumerate (functions[f].inputs)
					if x.is_var ((nm, typ))]
				cc = get_asm_calling_convention (f2)
				x = cc['args'][i]
				asm_idents[f2].append (syntax.mk_eq (x, y))
			else:
				assert not 'ident kind convertible'
	return asm_idents
예제 #6
0
def convert_recursion_idents(idents):
    asm_idents = {}
    for f in idents:
        if f not in pre_pairings:
            continue
        f2 = pre_pairings[f]['ASM']
        assert f2 != f
        asm_idents[f2] = []
        for ident in idents[f]:
            if ident.is_op('True'):
                asm_idents[f2].append(ident)
            elif ident.is_op('Equals'):
                [x, y] = ident.vals
                # this is a bit hacky
                [i] = [
                    i for (i, (nm, typ)) in enumerate(functions[f].inputs)
                    if x.is_var((nm, typ))
                ]
                cc = get_asm_calling_convention(f2)
                x = cc['args'][i]
                asm_idents[f2].append(syntax.mk_eq(x, y))
            else:
                assert not 'ident kind convertible'
    return asm_idents
예제 #7
0
def add_recursion_ident(f, group, idents, extra_unfolds):
    from syntax import mk_eq, mk_implies, mk_var
    p = problem.Problem(None, name='Recursion Test')
    chain = []
    tag = 'fun0'
    p.add_entry_function(functions[f], tag)
    p.do_analysis()
    assns = []
    recursion_last_assns[0] = assns

    while True:
        res = find_unknown_recursion(p, group, idents, tag, assns,
                                     extra_unfolds)
        if res == None:
            break
        if p.nodes[res].fname not in group:
            problem.inline_at_point(p, res)
            continue
        fname = p.nodes[res].fname
        chain.append(fname)
        tag = 'fun%d' % len(chain)
        (args, _, entry) = p.add_entry_function(functions[fname], tag)
        p.do_analysis()
        assns += function_link_assns(p, res, tag)
    if chain == []:
        return None
    recursion_trace.append('  created fun chain %s' % chain)
    word_args = [(i, mk_var(s, typ)) for (i, (s, typ)) in enumerate(args)
                 if typ.kind == 'Word']
    rep = rep_graph.mk_graph_slice(p, fast=True)
    (_, env) = rep.get_node_pc_env((entry, ()))

    m = {}
    res = rep.test_hyp_whyps(syntax.false_term, assns, model=m)
    assert m

    if find_unknown_recursion(p, group, idents, tag, [], []) == None:
        idents.setdefault(fname, [])
        idents[fname].append(syntax.true_term)
        recursion_trace.append('      found final ident for %s' % fname)
        return syntax.true_term
    assert word_args
    recursion_trace.append('      scanning for ident for %s' % fname)
    for (i, arg) in word_args:
        (nm, typ) = functions[fname].inputs[i]
        arg_smt = solver.to_smt_expr(arg, env, rep.solv)
        val = search.eval_model_expr(m, rep.solv, arg_smt)
        if not rep.test_hyp_whyps(mk_eq(arg_smt, val), assns):
            recursion_trace.append('      discarded %s = 0x%x, not stable' %
                                   (nm, val.val))
            continue
        entry_vis = ((entry, ()), tag)
        ass = rep_graph.eq_hyp((arg, entry_vis), (val, entry_vis))
        res = find_unknown_recursion(p, group, idents, tag, assns + [ass], [])
        if res:
            fname2 = p.nodes[res].fname
            recursion_trace.append(
                '      discarded %s, allows recursion to %s' % (nm, fname2))
            continue
        eq = syntax.mk_eq(mk_var(nm, typ), val)
        idents.setdefault(fname, [])
        idents[fname].append(eq)
        recursion_trace.append('    found ident for %s: %s' % (fname, eq))
        return eq
    assert not "identifying assertion found"
예제 #8
0
def add_recursion_ident (f, group, idents, extra_unfolds):
	from syntax import mk_eq, mk_implies, mk_var
	p = problem.Problem (None, name = 'Recursion Test')
	chain = []
	tag = 'fun0'
	p.add_entry_function (functions[f], tag)
	p.do_analysis ()
	assns = []
	recursion_last_assns[0] = assns

	while True:
		res = find_unknown_recursion (p, group, idents, tag, assns,
			extra_unfolds)
		if res == None:
			break
		if p.nodes[res].fname not in group:
			problem.inline_at_point (p, res)
			continue
		fname = p.nodes[res].fname
		chain.append (fname)
		tag = 'fun%d' % len (chain)
		(args, _, entry) = p.add_entry_function (functions[fname], tag)
		p.do_analysis ()
		assns += function_link_assns (p, res, tag)
	if chain == []:
		return None
	recursion_trace.append ('  created fun chain %s' % chain)
	word_args = [(i, mk_var (s, typ))
		for (i, (s, typ)) in enumerate (args)
		if typ.kind == 'Word']
	rep = rep_graph.mk_graph_slice (p, fast = True)
	(_, env) = rep.get_node_pc_env ((entry, ()))

	m = {}
	res = rep.test_hyp_whyps (syntax.false_term, assns, model = m)
	assert m

	if find_unknown_recursion (p, group, idents, tag, [], []) == None:
		idents.setdefault (fname, [])
		idents[fname].append (syntax.true_term)
		recursion_trace.append ('      found final ident for %s' % fname)
		return syntax.true_term
	assert word_args
	recursion_trace.append ('      scanning for ident for %s' % fname)
	for (i, arg) in word_args:
		(nm, typ) = functions[fname].inputs[i]
		arg_smt = solver.to_smt_expr (arg, env, rep.solv)
		val = search.eval_model_expr (m, rep.solv, arg_smt)
		if not rep.test_hyp_whyps (mk_eq (arg_smt, val), assns):
			recursion_trace.append ('      discarded %s = 0x%x, not stable' % (nm, val.val))
			continue
		entry_vis = ((entry, ()), tag)
		ass = rep_graph.eq_hyp ((arg, entry_vis), (val, entry_vis))
		res = find_unknown_recursion (p, group, idents, tag,
				assns + [ass], [])
		if res:
			fname2 = p.nodes[res].fname
			recursion_trace.append ('      discarded %s, allows recursion to %s' % (nm, fname2))
			continue
		eq = syntax.mk_eq (mk_var (nm, typ), val)
		idents.setdefault (fname, [])
		idents[fname].append (eq)
		recursion_trace.append ('    found ident for %s: %s' % (fname, eq))
		return eq
	assert not "identifying assertion found"
예제 #9
0
def to_smt_expr_under_op (expr, env, solv):
	if expr.kind == 'Op':
		vals = [to_smt_expr (v, env, solv) for v in expr.vals]
		return syntax.Expr ('Op', expr.typ, name = expr.name,
			vals = vals)
	else:
		return to_smt_expr (expr, env, solv)

def inst_eq_with_envs ((x, env1), (y, env2), solv):
	x = to_smt_expr_under_op (x, env1, solv)
	y = to_smt_expr_under_op (y, env2, solv)
	if x.typ == syntax.builtinTs['RelWrapper']:
		return logic.apply_rel_wrapper (x, y)
	else:
		return mk_eq (x, y)

def inst_eqs (eqs, envs, solv):
	return [inst_eq_with_envs ((x, envs[x_addr]), (y, envs[y_addr]), solv)
		for ((x, x_addr), (y, y_addr)) in eqs]

def subst_induct (expr, induct_var):
	substs = {('%n', word32T): induct_var}
	return logic.var_subst (expr, substs, must_subst = False)

printed_hyps = {}
def print_hyps (hyps):
	hyps = tuple (hyps)
	if hyps in printed_hyps:
		trace ('hyps = %s' % printed_hyps[hyps])
	else:
예제 #10
0
		if i != head:
			k += 1
		restrs2 = restrs + ((head, vc_num (k)), )
		(pc, env) = rep.get_node_pc_env ((i, restrs2))
		return (to_smt_expr (pc, env, rep.solv),
			to_smt_expr (v_i, env, rep.solv))
	return [get_var (i_offs + (k * i_step))
		for k in [0, 1, 2]]

def expand_var_eqs (knowledge, (v_i, v_j)):
	(rep, (restrs, _, _, _), _, _) = knowledge

	if v_j == 'Const':
		pc_vs = get_var_pc_var_list (knowledge, v_i)
		(_, v0) = pc_vs[0]
		return [mk_implies (pc, mk_eq (v, v0))
			for (pc, v) in pc_vs[1:]]
	# sorting the vars guarantees we generate the same
	# mem eqs each time which is important for the solver
	(v_i, v_j) = sorted ([v_i, v_j])
	pc_vs = zip (get_var_pc_var_list (knowledge, v_i),
		get_var_pc_var_list (knowledge, v_j))
	return [pred for ((pc_i, v_i), (pc_j, v_j)) in pc_vs
		for pred in [mk_eq (pc_i, pc_j),
			mk_implies (pc_i, logic.mk_eq_with_cast (v_i, v_j))]]

word_ops = {'bvadd':lambda x, y: x + y, 'bvsub':lambda x, y: x - y,
	'bvmul':lambda x, y: x * y, 'bvurem':lambda x, y: x % y,
	'bvudiv':lambda x, y: x / y, 'bvand':lambda x, y: x & y,
	'bvor':lambda x, y: x | y, 'bvxor': lambda x, y: x ^ y,
	'bvnot': lambda x: ~ x, 'bvneg': lambda x: - x,
예제 #11
0
def get_necessary_split_opts (p, head, restrs, hyps, tags = None, iters = None):
	if not tags:
		tags = p.pairing.tags

	[l_tag, r_tag] = tags
	assert p.node_tags[head][0] == l_tag
	l_seq_vs = get_interesting_linear_series_exprs (p, head)
	if not l_seq_vs:
		return None
	r_seq_vs = {}
	for n in init_loops_to_split (p, restrs):
		if p.node_tags[n][0] == r_tag:
			vs = get_interesting_linear_series_exprs (p, n)
			r_seq_vs.update (vs)
	if not r_seq_vs:
		return None

	rep = rep_graph.mk_graph_slice (p, fast = True)
	def vis (n, i):
		if n != p.loop_id (n):
			i = i + 1
		return (n, tuple ([(p.loop_id (n), vc_num (i))]) + restrs)
	smt = lambda expr, n, i: rep.to_smt_expr (expr, vis (n, i))
	smt_pc = lambda n, i: rep.get_pc (vis (n, i))

	# remove duplicates by concretising
	l_seq_vs = dict ([(smt (expr, n, 2), (kind, n, expr))
		for n in l_seq_vs for (kind, expr) in l_seq_vs[n]]).values ()
	r_seq_vs = dict ([(smt (expr, n, 2), (kind, n, expr))
                for n in r_seq_vs for (kind, expr) in r_seq_vs[n]]).values ()

	if iters == None:
		if [n for n in p.loop_body (head) if p.nodes[n].kind == 'Call']:
			iters = 5
		else:
			iters = 8

	r_seq_end = 1 + 2 * iters
	l_seq_end = 1 + iters
	l_seq_ineq = 1 + max ([1 << n for n in range (iters)
		if 1 << n <= iters])

	hyps = hyps + [rep_graph.pc_triv_hyp ((vis (n, r_seq_end), r_tag))
		for n in set ([n for (_, n, _) in r_seq_vs])]
	hyps = hyps + [rep_graph.pc_triv_hyp ((vis (n, l_seq_end), l_tag))
		for n in set ([n for (_, n, _) in l_seq_vs])]
	ex_restrs = [(n, rep_graph.vc_upto (r_seq_end + 1))
		for n in set ([p.loop_id (n) for (_, n, _) in r_seq_vs])]
	hyps = hyps + [check.non_r_err_pc_hyp (tags,
			restr_others (p, restrs + tuple (ex_restrs), 2))]

	necessary_split_opts_trace[:] = []
	necessary_split_opts_long_trace[:] = []
	for (kind, n, expr) in sorted (l_seq_vs):
		rel_r_seq_vs = [v for v in r_seq_vs if v[0] == kind]
		if not rel_r_seq_vs:
			necessary_split_opts_trace.append ((n, 'NoneRelevant'))
			continue
		m = {}
		eq = mk_eq (smt (expr, n, 1), smt (expr, n, l_seq_ineq))
		ex_hyps = [rep_graph.pc_true_hyp ((vis (n, i), l_tag))
			for i in range (1, l_seq_end + 1)]
		res = rep.test_hyp_whyps (eq, hyps + ex_hyps, model = m)
		necessary_split_opts_long_trace.append ((n, eq, hyps + ex_hyps,
			res, m, smt, smt_pc, (kind, n, expr), r_seq_vs, iters))
		if not m:
			necessary_split_opts_trace.append ((n, None))
			continue
		seq_eq = get_linear_seq_eq (rep, m, smt, smt_pc,
			(kind, n, expr), r_seq_vs, iters)
		necessary_split_opts_trace.append ((n, ('Seq', seq_eq)))
		if not seq_eq:
			continue
		((n2, expr2), (l_start, l_step), (r_start, r_step)) = seq_eq
		eqs = [rep_graph.eq_hyp ((expr,
			(vis (n, l_start + (i * l_step)), l_tag)),
			(expr2, (vis (n2, r_start + (i * r_step)), r_tag)))
			for i in range (10)
			if l_start + (i * l_step) <= l_seq_end
			if r_start + (i * r_step) <= r_seq_end]
		eq = foldr1 (mk_and, map (rep.interpret_hyp, eqs))
		if rep.test_hyp_whyps (eq, hyps):
			mk_i = lambda i: (l_start + (i * l_step), l_step)
			mk_j = lambda j: (r_start + (j * r_step), r_step)
			return [([mk_i (0)], [mk_j (0)]),
				([mk_i (0), mk_i (1)], [mk_j (0), mk_j (1)])]
		n_vcs = entry_path_no_loops (rep, l_tag, m, head)
		path_hyps = [rep_graph.pc_true_hyp ((n_vc, l_tag)) for n_vc in n_vcs]
		if rep.test_hyp_whyps (eq, hyps + path_hyps):
			# immediate case split on difference between entry paths
			checks = [(hyps, eq_hyp, 'eq') for eq_hyp in eqs]
			return derive_case_split (rep, n_vcs, checks)
		necessary_split_opts_trace.append ((n, 'Seq check failed'))
	return None