def inline_no_pre_pairing(p): # FIXME: handle code sharing with check.inline_completely_unmatched while True: ns = [ n for n in p.nodes if p.nodes[n].kind == 'Call' if p.nodes[n].fname not in pre_pairings if not is_instruction(p.nodes[n].fname) ] for n in ns: trace('Inlining %s at %d.' % (p.nodes[n].fname, n)) problem.inline_at_point(p, n) if not ns: return
def inline_completely_unmatched (p, ref_tags = None, skip_underspec = False): if ref_tags == None: ref_tags = p.pairing.tags while True: ns = [(n, skip_underspec and not functions[p.nodes[n].fname].entry) for n in p.nodes if p.nodes[n].kind == 'Call' if not [pair for pair in pairings.get (p.nodes[n].fname, []) if pair.tags == ref_tags]] [trace ('Skipped inlining underspecified %s.' % p.nodes[n].fname) for (n, skip) in ns if skip] ns = [n for (n, skip) in ns if not skip] for n in ns: inline_at_point (p, n, do_analysis = False) if not ns: p.do_analysis () return
def inline_completely_unmatched(p, ref_tags=None, skip_underspec=False): if ref_tags == None: ref_tags = p.pairing.tags while True: ns = [(n, skip_underspec and not functions[p.nodes[n].fname].entry) for n in p.nodes if p.nodes[n].kind == 'Call' if not [ pair for pair in pairings.get(p.nodes[n].fname, []) if pair.tags == ref_tags ]] [ trace('Skipped inlining underspecified %s.' % p.nodes[n].fname) for (n, skip) in ns if skip ] ns = [n for (n, skip) in ns if not skip] for n in ns: trace('Function %s at %d - %s - completely unmatched.' % (p.nodes[n].fname, n, p.node_tags[n][0])) inline_at_point(p, n, do_analysis=False) if not ns: p.do_analysis() return
def consider_inline1(p, n, matched_funs, inline_tag, force_inline, skip_underspec): node = p.nodes[n] assert node.kind == 'Call' if p.node_tags[n][0] != inline_tag: return False f_nm = node.fname if skip_underspec and not functions[f_nm].entry: trace('Skipping inlining underspecified %s' % f_nm) return False if f_nm not in matched_funs or (force_inline and force_inline(f_nm)): return lambda: inline_at_point(p, n) else: return False
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"
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"