def ident_conds(fname, idents): rolling = syntax.true_term conds = [] for ident in idents.get(fname, [syntax.true_term]): conds.append((ident, syntax.mk_and(rolling, ident))) rolling = syntax.mk_and(rolling, syntax.mk_not(ident)) return conds
def ident_conds (fname, idents): rolling = syntax.true_term conds = [] for ident in idents.get (fname, [syntax.true_term]): conds.append ((ident, syntax.mk_and (rolling, ident))) rolling = syntax.mk_and (rolling, syntax.mk_not (ident)) return conds
def ident_callables (fname, callees, idents): from solver import to_smt_expr, smt_expr from syntax import mk_not, mk_and, true_term auto_callables = dict ([((ident, f, true_term), True) for ident in idents.get (fname, [true_term]) for f in callees if f not in idents]) if not [f for f in callees if f in idents]: return auto_callables fun = functions[fname] p = fun.as_problem (problem.Problem, name = 'Target') check_ns = [(n, ident, cond) for n in p.nodes if p.nodes[n].kind == 'Call' if p.nodes[n].fname in idents for (ident, cond) in ident_conds (p.nodes[n].fname, idents)] p.do_analysis () assert check_ns rep = rep_graph.mk_graph_slice (p, fast = True) err_hyp = rep_graph.pc_false_hyp ((default_n_vc (p, 'Err'), 'Target')) callables = auto_callables nhyps = mk_not_callable_hyps (p) for (ident, cond) in ident_conds (fname, idents): renames = p.entry_exit_renames (tags = ['Target']) cond = syntax.rename_expr (cond, renames['Target_IN']) entry = p.get_entry ('Target') e_vis = ((entry, ()), 'Target') hyps = [err_hyp, rep_graph.eq_hyp ((cond, e_vis), (true_term, e_vis))] for (n, ident2, cond2) in check_ns: k = (ident, p.nodes[n].fname, ident2) (inp_env, _, _) = rep.get_func (default_n_vc (p, n)) pc = rep.get_pc (default_n_vc (p, n)) cond2 = to_smt_expr (cond2, inp_env, rep.solv) if rep.test_hyp_whyps (mk_not (mk_and (pc, cond2)), hyps + nhyps): callables[k] = False else: callables[k] = True return callables
def ident_callables(fname, callees, idents): from solver import to_smt_expr, smt_expr from syntax import mk_not, mk_and, true_term auto_callables = dict([((ident, f, true_term), True) for ident in idents.get(fname, [true_term]) for f in callees if f not in idents]) if not [f for f in callees if f in idents]: return auto_callables fun = functions[fname] p = fun.as_problem(problem.Problem, name='Target') check_ns = [(n, ident, cond) for n in p.nodes if p.nodes[n].kind == 'Call' if p.nodes[n].fname in idents for (ident, cond) in ident_conds(p.nodes[n].fname, idents)] p.do_analysis() assert check_ns rep = rep_graph.mk_graph_slice(p, fast=True) err_hyp = rep_graph.pc_false_hyp((default_n_vc(p, 'Err'), 'Target')) callables = auto_callables nhyps = mk_not_callable_hyps(p) for (ident, cond) in ident_conds(fname, idents): renames = p.entry_exit_renames(tags=['Target']) cond = syntax.rename_expr(cond, renames['Target_IN']) entry = p.get_entry('Target') e_vis = ((entry, ()), 'Target') hyps = [err_hyp, rep_graph.eq_hyp((cond, e_vis), (true_term, e_vis))] for (n, ident2, cond2) in check_ns: k = (ident, p.nodes[n].fname, ident2) (inp_env, _, _) = rep.get_func(default_n_vc(p, n)) pc = rep.get_pc(default_n_vc(p, n)) cond2 = to_smt_expr(cond2, inp_env, rep.solv) if rep.test_hyp_whyps(mk_not(mk_and(pc, cond2)), hyps + nhyps): callables[k] = False else: callables[k] = True return callables
def loop_no_match_unroll (rep, restrs, hyps, split, other_tag, unroll): p = rep.p assert p.node_tags[split][0] != other_tag restr = ((split, vc_num (unroll)), ) restrs2 = restr_others (p, restr + restrs, 2) loop_cond = rep.get_pc ((split, restr + restrs)) ret_cond = rep.get_pc (('Ret', restrs2), tag = other_tag) # loop should be reachable if rep.test_hyp_whyps (mk_not (loop_cond), hyps): trace ('Loop weak at %d (unroll count %d).' % (split, unroll)) return True # reaching the loop should imply reaching a loop on the other side hyp = mk_not (mk_and (loop_cond, ret_cond)) if not rep.test_hyp_whyps (hyp, hyps): trace ('Loop independent at %d (unroll count %d).' % (split, unroll)) return True return False
def emit_node (self, n): (pc, env) = self.get_node_pc_env (n, request = False) tag = self.p.node_tags[n[0]][0] app_eqs = self.apply_known_eqs_tm (n, tag) # node = logic.simplify_node_elementary (self.p.nodes[n[0]]) # whether to ignore unreachable Cond arcs seems to be a huge # dilemma. if we ignore them, some reachable sites become # unreachable and we can't interpret all hyps # if we don't ignore them, the variable set disagrees with # var_deps and so the abstracted loop pc/env may not be # sufficient and we get EnvMiss again. I don't really know # what to do about this corner case. node = self.p.nodes[n[0]] env = dict (env) if node.kind == 'Call': self.try_inline (n[0], pc, env) if pc == false_term: return [(c, false_term, {}) for c in node.get_conts()] elif node.kind == 'Cond' and node.left == node.right: return [(node.left, pc, env)] elif node.kind == 'Cond' and node.cond == true_term: return [(node.left, pc, env), (node.right, false_term, env)] elif node.kind == 'Basic': upds = [] for (lv, v) in node.upds: if v.kind == 'Var': upds.append ((lv, env[(v.name, v.typ)])) else: name = self.local_name (lv[0], n) v = app_eqs (v) vname = self.add_local_def (n, ('Var', lv), name, v, env) upds.append ((lv, vname)) for (lv, v) in upds: env[lv] = v return [(node.cont, pc, env)] elif node.kind == 'Cond': name = self.cond_name (n) cond = self.p.fresh_var (name, boolT) env[(cond.name, boolT)] = self.add_local_def (n, 'Cond', name, app_eqs (node.cond), env) lpc = mk_and (cond, pc) rpc = mk_and (mk_not (cond), pc) return [(node.left, lpc, env), (node.right, rpc, env)] elif node.kind == 'Call': nm = self.success_name (node.fname, n) success = self.solv.add_var (nm, boolT) success = mk_smt_expr (success, boolT) fun = functions[node.fname] ins = dict ([((x, typ), smt_expr (app_eqs (arg), env, self.solv)) for ((x, typ), arg) in azip (fun.inputs, node.args)]) mem_name = None for (x, typ) in reversed (fun.inputs): if typ == builtinTs['Mem']: mem_name = (node.fname, ins[(x, typ)]) outs = {} for ((x, typ), (y, typ2)) in azip (node.rets, fun.outputs): assert typ2 == typ if self.fast_const_ret (n[0], x, typ): outs[(y, typ2)] = env [(x, typ)] continue name = self.local_name (x, n) env[(x, typ)] = self.solv.add_var_restr (name, typ, mem_name = mem_name) outs[(y, typ2)] = env[(x, typ)] for ((x, typ), (y, _)) in azip (node.rets, fun.outputs): z = self.var_rep_request ((x, typ), 'Call', n, env) if z != None: env[(x, typ)] = z outs[(y, typ)] = z self.add_func (node.fname, ins, outs, success, n) return [(node.cont, pc, env)] else: assert not 'node kind understood'