Exemplo n.º 1
0
def check_split_induct (p, restrs, hyps, split, tags = None):
	"""perform both the induction check and a function-call based check
	on successes which can avoid some problematic inductions."""
	((l_split, (_, l_step), _), (r_split, (_, r_step), _), _, n, _) = split
	if tags == None:
		tags = p.pairing.tags

	err_hyp = check.split_r_err_pc_hyp (p, split, restrs, tags = tags)
	hyps = [err_hyp] + hyps + check.split_loop_hyps (tags, split,
		restrs, exit = False)

	rep = mk_graph_slice (p)

	if not check.check_split_induct_step_group (rep, restrs, hyps, split,
			tags = tags):
		return False

	l_succs = get_n_offset_successes (rep, l_split, l_step, restrs)
	r_succs = get_n_offset_successes (rep, r_split, r_step, restrs)

	if not l_succs:
		return True

	hyp = syntax.foldr1 (syntax.mk_and, l_succs)
	if r_succs:
		hyp = syntax.mk_implies (foldr1 (syntax.mk_and, r_succs), hyp)

	return rep.test_hyp_whyps (hyp, hyps)
Exemplo n.º 2
0
def setup_split_search (rep, head, restrs, hyps,
		i_opts, j_opts, unfold_limit = None, tags = None):
	p = rep.p

	if not tags:
		tags = p.pairing.tags
	if unfold_limit == None:
		unfold_limit = max ([start + (2 * step) + 1
			for (start, step) in i_opts + j_opts])

	trace ('Split search at %d, unfold limit %d.' % (head, unfold_limit))

	l_tag, r_tag = tags
	loop_elts = [(n, start, step) for n in p.splittable_points (head)
		for (start, step) in i_opts]
	init_to_split = init_loops_to_split (p, restrs)
	r_to_split = [n for n in init_to_split if p.node_tags[n][0] == r_tag] 
	cand_r_loop_elts = [(n2, start, step) for n in r_to_split
		for n2 in p.splittable_points (n)
		for (start, step) in j_opts]

	err_restrs = restr_others (p, tuple ([(sp, vc_upto (unfold_limit))
		for sp in r_to_split]) + restrs, 1)
	nrerr_pc = mk_not (rep.get_pc (('Err', err_restrs), tag = r_tag))

	def get_pc (n, k):
		head = p.loop_id (n)
		assert head in init_to_split
		if n != head:
			k += 1
		restrs2 = restrs + ((head, vc_num (k)), )
		return rep.get_pc ((n, restrs2))

	for n in r_to_split:
		get_pc (n, unfold_limit)
	get_pc (head, unfold_limit)

	premise = foldr1 (mk_and, [nrerr_pc] + map (rep.interpret_hyp, hyps))
	premise = logic.weaken_assert (premise)

	knowledge = SearchKnowledge (rep,
		'search at %d (unfold limit %d)' % (head, unfold_limit),
		restrs, hyps, tags, (loop_elts, cand_r_loop_elts))
	knowledge.premise = premise
	last_knowledge[0] = knowledge

	# make sure the representation is in sync
	rep.test_hyp_whyps (true_term, hyps)

	# make sure all mem eqs are being tracked
	mem_vs = [v for v in knowledge.v_ids if v[0].typ == builtinTs['Mem']]
	for (i, v) in enumerate (mem_vs):
		for v2 in mem_vs[:i]:
			for pred in expand_var_eqs (knowledge, (v, v2)):
				smt_expr (pred, {}, rep.solv)
	for v in knowledge.v_ids:
		for pred in expand_var_eqs (knowledge, (v, 'Const')):
			smt_expr (pred, {}, rep.solv)

	return knowledge
Exemplo n.º 3
0
	def get_func_assert (self, n_vc, n_vc2):
		(pair, l_n_vc, r_n_vc) = self.get_func_pairing (n_vc, n_vc2)
		(ltag, rtag) = pair.tags
		(inp_eqs, out_eqs) = pair.eqs
		(lin, lout, lsucc) = self.funcs[l_n_vc]
		(rin, rout, rsucc) = self.funcs[r_n_vc]
		lpc = self.get_pc (l_n_vc)
		rpc = self.get_pc (r_n_vc)
		envs = {ltag + '_IN': lin, rtag + '_IN': rin,
			ltag + '_OUT': lout, rtag + '_OUT': rout}
		inp_eqs = inst_eqs (inp_eqs, envs, self.solv)
		out_eqs = inst_eqs (out_eqs, envs, self.solv)
		succ_imp = mk_implies (rsucc, lsucc)

		return mk_implies (foldr1 (mk_and, inp_eqs + [rpc]),
			foldr1 (mk_and, out_eqs + [succ_imp]))
Exemplo n.º 4
0
	def hyps_add_model (self, hyps, assert_progress = True):
		if hyps:
			test_expr = foldr1 (mk_and, hyps)
		else:
			# we want to learn something, either a new model, or
			# that all hyps are true. if there are no hyps,
			# learning they're all true is learning nothing.
			# instead force a model
			test_expr = false_term
		test_expr = mk_implies (self.premise, test_expr)
		m = {}
		(r, _) = self.rep.solv.parallel_check_hyps ([(1, test_expr)],
			{}, model = m)
		if r == 'unsat':
			if not hyps:
				trace ('WARNING: SearchKnowledge: premise unsat.')
				trace ("  ... learning procedure isn't going to work.")
				return
			if assert_progress:
				assert not (set (hyps) <= self.facts), hyps
			for hyp in hyps:
				self.facts.add (hyp)
		else:
			assert r == 'sat', r
			self.add_model (m)
			if assert_progress:
				assert self.model_trace[-2:-1] != [m]
Exemplo n.º 5
0
	def __init__ (self, rep, hyps, vs):
		self.rep = rep
		self.hyps = hyps
		self.v_ids = dict ([(v, 1) for v in vs])
		self.model_trace = []
		self.facts = set ()
		self.premise = foldr1 (mk_and, map (rep.interpret_hyp, hyps))
Exemplo n.º 6
0
def check_pairs (pairs, loops = True, report_mode = False,
		only_build_problem = False):
	num_pairs = len (pairs)
	printout ('Checking %d function pair problems' % len (pairs))
	results = [(pair, toplevel_check (pair, check_loops = loops,
			report = report_mode, count = (i, num_pairs),
			only_build_problem = only_build_problem))
		for (i, pair) in enumerate (pairs)]
	result_dict = logic.dict_list ([(result_codes[r][1], pair)
		for (pair, r) in results])
	if not only_build_problem:
		printout ('Results: %s'
			% [(pair.name, r) for (pair, r) in results])
	printout ('Result summary:')
	success = result_dict.get ('Success', [])
	if only_build_problem:
		printout ('  - %d problems build' % len (success))
	else:
		printout ('  - %d proofs checked' % len (success))
	skipped = result_dict.get ('Skipped', [])
	printout ('  - %d proofs skipped' % len (skipped))
	fails = [pair.name for pair in result_dict.get ('Failed', [])]
	print_coverage_report (set (skipped), set (success + fails))
	printout ('  - failures: %s' % fails)
	return syntax.foldr1 (comb_results, ['True']
		+ [r for (_, r) in results])
Exemplo n.º 7
0
def check_pairs (pairs, loops = True, report_mode = False):
	num_pairs = len (pairs)
	results = [toplevel_check_wname (pair, check_loops = loops,
			report_mode = report_mode, count = (i, num_pairs))
		for (i, pair) in enumerate (pairs)]
	printout ('Result summary: %s' % results)
	count = len ([1 for (_, r) in results if r == 'True'])
	printout ('  - %d proofs checked' % count)
	count = len ([1 for (_, r) in results
		if r in ['ProofAbort', 'None']])
	printout ('  - %d proofs skipped' % count)
	fails = [(nm, r) for (nm, r) in results
		if r not in ['True', 'ProofAbort', 'None']]
	printout ('  - failures: %s' % fails)
	return syntax.foldr1 (comb_results, ['True']
		+ [r for (nm, r) in results])
Exemplo n.º 8
0
def mk_align_valid_ineq (typ, p):
	if typ[0] == 'Type':
		(_, typ) = typ
		align = typ.align ()
		size = mk_word32 (typ.size ())
	else:
		assert typ[0] == 'Array', typ
		(kind, typ, num) = typ
		align = typ.align ()
		size = mk_times (mk_word32 (typ.size ()), num)
	assert align in [1, 4, 8]
	w0 = mk_word32 (0)
	if align > 1:
		align_req = [mk_eq (mk_bwand (p, mk_word32 (align - 1)), w0)]
	else:
		align_req = []
	return foldr1 (mk_and, align_req + [mk_not (mk_eq (p, w0)),
		mk_implies (mk_less (w0, size),
			mk_less_eq (p, mk_uminus (size)))])
Exemplo n.º 9
0
def get_styp_condition_inner2 (inner_typ, outer_typ):
	if inner_typ[0] == 'Array' and outer_typ[0] == 'Array':
		(_, ityp, inum, _) = inner_typ
		(_, otyp, onum, outer_bound) = outer_typ
		# array fits in another array if the starting element is
		# a sub-element, and if the size of the left array plus
		# the offset fits in the right array
		cond = get_styp_condition_inner1 (('Type', ityp), outer_typ)
		isize = array_typ_size (inner_typ)
		osize = array_typ_size (outer_typ)
		if outer_bound == 'Strong' and cond:
			return lambda offs: mk_and (cond (offs),
				mk_less_eq (mk_plus (isize, offs), osize))
		else:
			return cond
	elif inner_typ == outer_typ:
		return lambda offs: mk_eq (offs, mk_word32 (0))
	elif outer_typ[0] == 'Type' and outer_typ[1].kind == 'Struct':
		conds = [(get_styp_condition_inner1 (inner_typ,
				('Type', sf_typ)), mk_word32 (offs2))
			for (_, offs2, sf_typ)
			in structs[outer_typ[1].name].fields.itervalues()]
		conds = [cond for cond in conds if cond[0]]
		if conds:
			return lambda offs: foldr1 (mk_or,
				[c (mk_minus (offs, offs2))
					for (c, offs2) in conds])
		else:
			return None
	elif outer_typ[0] == 'Array':
		(_, el_typ, n, bound) = outer_typ
		cond = get_styp_condition_inner1 (inner_typ, ('Type', el_typ))
		el_size = mk_word32 (el_typ.size ())
		size = mk_times (n, el_size)
		if bound == 'Strong' and cond:
			return lambda offs: mk_and (mk_less (offs, size),
				cond (mk_modulus (offs, el_size)))
		elif cond:
			return lambda offs: cond (mk_modulus (offs, el_size))
		else:
			return None
	else:
		return None
Exemplo n.º 10
0
def add_model (knowledge, preds):
	(rep, (_, _, _, premise), _, facts) = knowledge
	if preds:
		pred_expr = foldr1 (mk_and, preds)
	else:
		# we want to learn something, either a new model, or that
		# all of our predicates are true. if there are no predicates,
		# ''all our predicates are true'' is trivially true. instead
		# we must want a model (counterexample of false)
		pred_expr = false_term
	m = {}
	r = rep.solv.check_hyp (mk_implies (premise, pred_expr), {}, model = m)
	if r == 'unsat':
		if not preds:
			trace ('WARNING: unsat with no extra assertions.')
			trace ("  ... learning procedure isn't going to work.")
		for pred in preds:
			facts.add (pred)
	else:
		assert r == 'sat'
		update_knowledge_for_model (knowledge, m)
Exemplo n.º 11
0
def find_unknown_recursion (p, group, idents, tag, assns, extra_unfolds):
	from syntax import mk_not, mk_and, foldr1
	rep = rep_graph.mk_graph_slice (p, fast = True)
	for n in p.nodes:
		if p.nodes[n].kind != 'Call':
			continue
		if p.node_tags[n][0] != tag:
			continue
		fname = p.nodes[n].fname
		if fname in extra_unfolds:
			return n
		if fname not in group:
			continue
		(inp_env, _, _) = rep.get_func (default_n_vc (p, n))
		pc = rep.get_pc (default_n_vc (p, n))
		new = foldr1 (mk_and, [pc] + [syntax.mk_not (
				solver.to_smt_expr (ident, inp_env, rep.solv))
			for ident in idents.get (fname, [])])
		if rep.test_hyp_whyps (mk_not (new), assns):
			continue
		return n
	return None
Exemplo n.º 12
0
def get_styp_condition_inner2 (inner_typ, outer_typ, strict = True):
	if inner_typ[0] == 'Array' and outer_typ[0] == 'Array':
		(_, ityp, inum) = inner_typ
		(_, otyp, onum) = outer_typ
		# array fits in another array if the starting element is
		# a sub-element, and for the strictness constraint if it's
		# no smaller
		cond = get_styp_condition_inner1 (('Type', ityp), outer_typ)
		if strict and cond:
			return lambda offs: mk_and (cond (offs),
				mk_less_eq (inum, onum))
		return cond
	elif inner_typ == outer_typ:
		return lambda offs: mk_eq (offs, mk_word32 (0))
	elif outer_typ[0] == 'Type' and outer_typ[1].kind == 'Struct':
		conds = [(get_styp_condition_inner1 (inner_typ,
				('Type', sf_typ)), mk_word32 (offs2))
			for (_, offs2, sf_typ)
			in structs[outer_typ[1].name].fields.itervalues()]
		conds = [cond for cond in conds if cond[0]]
		if conds:
			return lambda offs: foldr1 (mk_or,
				[c (mk_minus (offs, offs2))
					for (c, offs2) in conds])
		else:
			return None
	elif outer_typ[0] == 'Array':
		(_, el_typ, n) = outer_typ
		cond = get_styp_condition_inner1 (inner_typ, ('Type', el_typ))
		el_size = mk_word32 (el_typ.size ())
		size = mk_times (n, el_size)
		if cond:
			return lambda offs: mk_and (mk_less (offs, size),
				cond (mk_modulus (offs, el_size)))
		else:
			return None
	else:
		return None
Exemplo n.º 13
0
def find_unknown_recursion(p, group, idents, tag, assns, extra_unfolds):
    from syntax import mk_not, mk_and, foldr1
    rep = rep_graph.mk_graph_slice(p, fast=True)
    for n in p.nodes:
        if p.nodes[n].kind != 'Call':
            continue
        if p.node_tags[n][0] != tag:
            continue
        fname = p.nodes[n].fname
        if fname in extra_unfolds:
            return n
        if fname not in group:
            continue
        (inp_env, _, _) = rep.get_func(default_n_vc(p, n))
        pc = rep.get_pc(default_n_vc(p, n))
        new = foldr1(mk_and, [pc] + [
            syntax.mk_not(solver.to_smt_expr(ident, inp_env, rep.solv))
            for ident in idents.get(fname, [])
        ])
        if rep.test_hyp_whyps(mk_not(new), assns):
            continue
        return n
    return None
Exemplo n.º 14
0
	return mk_plus (p, mk_minus (sz, mk_word32 (1)))

def pvalid_assertion1 ((typ, k, p, pv), (typ2, k2, p2, pv2)):
	"""first pointer validity assertion: incompatibility.
	pvalid1 & pvalid2 --> non-overlapping OR somehow-contained.
	typ/typ2 is ('Type', syntax.Type) or ('Array', Type, Expr) for
	dynamically sized arrays.
	"""
	offs1 = mk_minus (p, p2)
	cond1 = get_styp_condition (offs1, typ, typ2, strict = False)
	offs2 = mk_minus (p2, p)
	cond2 = get_styp_condition (offs2, typ2, typ, strict = False)
	
	out1 = mk_less (end_addr (p, typ), p2)
	out2 = mk_less (end_addr (p2, typ2), p)
	return mk_implies (mk_and (pv, pv2), foldr1 (mk_or,
		[cond1, cond2, out1, out2]))

def pvalid_assertion2 ((typ, k, p, pv), (typ2, k2, p2, pv2)):
	"""second pointer validity assertion: implication.
	pvalid1 & strictly-contained --> pvalid2
	"""
	offs1 = mk_minus (p, p2)
	cond1 = get_styp_condition (offs1, typ, typ2)
	imp1 = mk_implies (mk_and (cond1, pv2), pv)
	offs2 = mk_minus (p2, p)
	cond2 = get_styp_condition (offs2, typ2, typ)
	imp2 = mk_implies (mk_and (cond2, pv), pv2)
	return mk_and (imp1, imp2)

def sym_distinct_assertion ((typ, p, pv), (start, end)):
	out1 = mk_less (mk_plus (p, mk_word32 (typ.size () - 1)), mk_word32 (start))
Exemplo n.º 15
0
def compile_accs(replaces, expr):
    r = compile_const_global_acc(expr)
    if r:
        return compile_accs(replaces, r)

    if expr.kind == 'Field':
        expr = compile_field_acc(expr.field[0], expr.struct, replaces)
        return compile_accs(replaces, expr)
    elif expr.is_op('ArrayIndex'):
        [arr, n] = expr.vals
        expr2 = compile_array_acc(n, arr, replaces, False)
        if expr2:
            return compile_accs(replaces, expr2)
        arr = compile_accs(replaces, arr)
        n = compile_accs(replaces, n)
        expr2 = compile_array_acc(n, arr, replaces, False)
        if expr2:
            return compile_accs(replaces, expr2)
        else:
            return mk_arr_index(arr, n)
    elif (expr.is_op('MemUpdate') and expr.vals[2].is_op('MemAcc')
          and expr.vals[2].vals[0] == expr.vals[0]
          and expr.vals[2].vals[1] == expr.vals[1]):
        # null memory copy. probably created by ops below
        return compile_accs(replaces, expr.vals[0])
    elif (expr.is_op('MemUpdate') and expr.vals[2].kind == 'FieldUpd'):
        [m, p, f_upd] = expr.vals
        assert f_upd.typ.kind == 'Struct'
        (typ, offs, _) = structs[f_upd.typ.name].fields[f_upd.field[0]]
        assert f_upd.val.typ == typ
        return compile_accs(
            replaces,
            mk_memupd(mk_memupd(m, p, f_upd.struct),
                      mk_plus(p, mk_word32(offs)), f_upd.val))
    elif (expr.is_op('MemUpdate') and expr.vals[2].typ.kind == 'Struct'):
        [m, p, s_val] = expr.vals
        struct = structs[s_val.typ.name]
        for (nm, (typ, offs, _)) in struct.fields.iteritems():
            f = compile_field_acc(nm, s_val, replaces)
            assert f.typ == typ
            m = mk_memupd(m, mk_plus(p, mk_word32(offs)), f)
        return compile_accs(replaces, m)
    elif (expr.is_op('MemUpdate') and expr.vals[2].is_op('ArrayUpdate')):
        [m, p, arr_upd] = expr.vals
        [arr, i, v] = arr_upd.vals
        return compile_accs(
            replaces,
            mk_memupd(mk_memupd(m, p, arr), mk_arroffs(p, arr.typ, i), v))
    elif (expr.is_op('MemUpdate') and expr.vals[2].typ.kind == 'Array'):
        [m, p, arr] = expr.vals
        n = arr.typ.num
        typ = arr.typ.el_typ
        for i in range(n):
            offs = i * typ.size()
            assert offs == i or offs % 4 == 0
            e = compile_array_acc(i, arr, replaces)
            m = mk_memupd(m, mk_plus(p, mk_word32(offs)), e)
        return compile_accs(replaces, m)
    elif expr.is_op ('Equals') \
      and expr.vals[0].typ.kind in ['Struct', 'Array']:
        [x, y] = expr.vals
        assert x.typ == y.typ
        xs = compile_val_fields(x, replaces)
        ys = compile_val_fields(y, replaces)
        eq = foldr1(mk_and, map(mk_eq, xs, ys))
        return compile_accs(replaces, eq)
    elif expr.is_op('PAlignValid'):
        [typ, p] = expr.vals
        p = compile_accs(replaces, p)
        assert typ.kind == 'Type'
        return logic.mk_align_valid_ineq(('Type', typ.val), p)
    elif expr.kind == 'Op':
        vals = [compile_accs(replaces, v) for v in expr.vals]
        return syntax.adjust_op_vals(expr, vals)
    elif expr.kind == 'Symbol':
        return mk_word32(symbols[expr.name][0])
    else:
        if expr.kind not in {
                'Var': True,
                'ConstGlobal': True,
                'Num': True,
                'Invent': True,
                'Type': True
        }:
            print expr
            assert not 'field acc compiled'
        return expr
Exemplo n.º 16
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
Exemplo n.º 17
0
	return mk_plus (p, mk_minus (sz, mk_word32 (1)))

def pvalid_assertion1 ((typ, k, p, pv), (typ2, k2, p2, pv2)):
	"""first pointer validity assertion: incompatibility.
	pvalid1 & pvalid2 --> non-overlapping OR somehow-contained.
	typ/typ2 is ('Type', syntax.Type) or ('Array', Type, Expr) for
	dynamically sized arrays.
	"""
	offs1 = mk_minus (p, p2)
	cond1 = get_styp_condition (offs1, typ, typ2)
	offs2 = mk_minus (p2, p)
	cond2 = get_styp_condition (offs2, typ2, typ)

	out1 = mk_less (end_addr (p, typ), p2)
	out2 = mk_less (end_addr (p2, typ2), p)
	return mk_implies (mk_and (pv, pv2), foldr1 (mk_or,
		[cond1, cond2, out1, out2]))

def pvalid_assertion2 ((typ, k, p, pv), (typ2, k2, p2, pv2)):
	"""second pointer validity assertion: implication.
	pvalid1 & strictly-contained --> pvalid2
	"""
	if typ[0] == 'Array' and typ2[0] == 'Array':
		# this is such a vague notion it's not worth it
		return true_term
	offs1 = mk_minus (p, p2)
	cond1 = get_styp_condition (offs1, typ, typ2)
	imp1 = mk_implies (mk_and (cond1, pv2), pv)
	offs2 = mk_minus (p2, p)
	cond2 = get_styp_condition (offs2, typ2, typ)
	imp2 = mk_implies (mk_and (cond2, pv), pv2)
	return mk_and (imp1, imp2)
Exemplo n.º 18
0
def tm_with_word32_list (xs):
	if xs:
		return foldr1 (mk_plus, map (mk_word32, xs))
	else:
		return mk_uminus (mk_word32 (0))
Exemplo n.º 19
0
def find_split (rep, head, restrs, hyps, i_opts, j_opts, unfold_limit,
		tags = None):
	p = rep.p

	if tags:
		l_tag, r_tag = tags
	else:
		l_tag, r_tag = p.pairing.tags
	loop_elts = [(n, start, step) for n in p.loop_data[head][1]
		if p.loop_splittables[n]
		for (start, step) in i_opts]
	init_to_split = init_loops_to_split (p, restrs)
	r_to_split = [n for n in init_to_split if p.node_tags[n][0] == r_tag] 
	cand_r_loop_elts = [(n2, start, step) for n in r_to_split
		for n2 in p.loop_data[n][1]
		if p.loop_splittables[n2]
		for (start, step) in j_opts]

	err_restrs = restr_others (p, tuple ([(sp, vc_upto (unfold_limit))
		for sp in r_to_split]) + restrs, 1)
	nrerr_pc = mk_not (rep.get_pc (('Err', err_restrs), tag = r_tag))

	def get_pc (n, k):
		head = p.loop_id (n)
		assert head in init_to_split
		if n != head:
			k += 1
		restrs2 = restrs + ((head, vc_num (k)), )
		return rep.get_pc ((n, restrs2))

	for n in r_to_split:
		get_pc (n, unfold_limit)
	get_pc (head, unfold_limit)

	premise = foldr1 (mk_and, [nrerr_pc] + map (rep.interpret_hyp, hyps))
	premise = logic.weaken_assert (premise)

	knowledge = (rep, (restrs, loop_elts, cand_r_loop_elts, premise),
		init_knowledge_pairs (rep, loop_elts, cand_r_loop_elts), set ())
	last_knowledge[0] = knowledge

	# make sure the representation is in sync
	rep.test_hyp_whyps (true_term, hyps)

	# make sure all mem eqs are being tracked
	(_, _, (pairs, vs), _) = knowledge
	mem_vs = [v for v in vs if v[0].typ == builtinTs['Mem']]
	for (i, v) in enumerate (mem_vs):
		for v2 in mem_vs[:i]:
			for pred in expand_var_eqs (knowledge, (v, v2)):
				smt_expr (pred, {}, rep.solv)
	for v in vs:
		for pred in expand_var_eqs (knowledge, (v, 'Const')):
			smt_expr (pred, {}, rep.solv)

	# start the process with a model
	add_model (knowledge, [mk_not (get_pc (head, unfold_limit))])

	num_eqs = 3
	while True:
		trace ('Search at unfold limit %d' % unfold_limit)
		trace ('Computing live pairings')
		pair_eqs = [(pair, mk_pairing_v_eqs (knowledge, pair))
			for pair in sorted (pairs)
			if pairs[pair][0] != 'Failed']
		endorsed = [(pair, eqs) for (pair, eqs) in pair_eqs
			if eqs != None]
		trace (' ... %d live pairings, %d endorsed' %
			(len (pair_eqs), len (endorsed)))
		for (pair, eqs) in endorsed:
			split = v_eqs_to_split (p, pair, eqs, restrs, hyps,
				tags = tags)
			if split == None:
				pairs[pair] = ('Failed', 'SplitWeak', eqs)
				continue
			if check_split_induct (p, restrs, hyps, split,
					tags = tags):
				trace ('Tested v_eqs!')
				return ('Split', split)
			else:
				pairs[pair] = ('Failed', 'InductFailed', eqs)

		u_eqs = unknown_eqs (knowledge, num_eqs)
		if not u_eqs:
			trace (('Exhausted split candidates for loop at %d,'
				+ ' unfold limit %d') % (head, unfold_limit))
			fails = [it for it in pairs.items ()
				if it[1][0] == 'Failed']
			fails10 = fails[:10]
			trace ('  %d of %d failed pairings:' % (len (fails10),
				len (fails)))
			last_failed_pairings.append (fails)
			del last_failed_pairings[:-10]
			for f in fails:
				trace ('    %s' % (f,))
			ind_fails = [it for it in fails
				if str (it[1][1]) == 'InductFailed']
			if ind_fails:
				trace (  'Inductive failures!')
			for f in ind_fails:
				trace ('    %s' % (f,))
			return (None, ind_fails)
		
		add_model_wrapper (knowledge, u_eqs)
		num_eqs = 4 - num_eqs # oscillate between 3, 1
Exemplo n.º 20
0
def inst_eqs_pattern_exprs (pattern, params):
	(inp_eqs, out_eqs) = inst_eqs_pattern (pattern, params)
	return (foldr1 (mk_and, [mk_eq (a, c) for (a, c) in inp_eqs]),
		foldr1 (mk_and, [mk_eq (a, c) for (a, c) in out_eqs]))
Exemplo n.º 21
0
def compile_accs (replaces, expr):
	r = compile_const_global_acc (expr)
	if r:
		return compile_accs (replaces, r)

	if expr.kind == 'Field':
		expr = compile_field_acc (expr.field[0], expr.struct, replaces)
		return compile_accs (replaces, expr)
	elif expr.is_op ('ArrayIndex'):
		[arr, n] = expr.vals
		expr2 = compile_array_acc (n, arr, replaces, False)
		if expr2:
			return compile_accs (replaces, expr2)
		arr = compile_accs (replaces, arr)
		n = compile_accs (replaces, n)
		expr2 = compile_array_acc (n, arr, replaces, False)
		if expr2:
			return compile_accs (replaces, expr2)
		else:
			return mk_arr_index (arr, n)
	elif (expr.is_op ('MemUpdate')
			and expr.vals[2].is_op ('MemAcc')
			and expr.vals[2].vals[0] == expr.vals[0]
			and expr.vals[2].vals[1] == expr.vals[1]):
		# null memory copy. probably created by ops below
		return compile_accs (replaces, expr.vals[0])
	elif (expr.is_op ('MemUpdate')
			and expr.vals[2].kind == 'FieldUpd'):
		[m, p, f_upd] = expr.vals
		assert f_upd.typ.kind == 'Struct'
		(typ, offs, _) = structs[f_upd.typ.name].fields[f_upd.field[0]]
		assert f_upd.val.typ == typ
		return compile_accs (replaces,
			mk_memupd (mk_memupd (m, p, f_upd.struct),
				mk_plus (p, mk_word32 (offs)), f_upd.val))
	elif (expr.is_op ('MemUpdate')
			and expr.vals[2].typ.kind == 'Struct'):
		[m, p, s_val] = expr.vals
		struct = structs[s_val.typ.name]
		for (nm, (typ, offs, _)) in struct.fields.iteritems ():
			f = compile_field_acc (nm, s_val, replaces)
			assert f.typ == typ
			m = mk_memupd (m, mk_plus (p, mk_word32 (offs)), f)
		return compile_accs (replaces, m)
	elif (expr.is_op ('MemUpdate')
			and expr.vals[2].is_op ('ArrayUpdate')):
		[m, p, arr_upd] = expr.vals
		[arr, i, v] = arr_upd.vals
		return compile_accs (replaces,
			mk_memupd (mk_memupd (m, p, arr),
				mk_arroffs (p, arr.typ, i), v))
	elif (expr.is_op ('MemUpdate')
				and expr.vals[2].typ.kind == 'Array'):
		[m, p, arr] = expr.vals
		n = arr.typ.num
		typ = arr.typ.el_typ
		for i in range (n):
			offs = i * typ.size ()
			assert offs == i or offs % 4 == 0
			e = compile_array_acc (i, arr, replaces)
			m = mk_memupd (m, mk_plus (p, mk_word32 (offs)), e)
		return compile_accs (replaces, m)
	elif expr.is_op ('Equals') \
			and expr.vals[0].typ.kind in ['Struct', 'Array']:
		[x, y] = expr.vals
		assert x.typ == y.typ
		xs = compile_val_fields (x, replaces)
		ys = compile_val_fields (y, replaces)
		eq = foldr1 (mk_and, map (mk_eq, xs, ys))
		return compile_accs (replaces, eq)
	elif expr.is_op ('PAlignValid'):
		[typ, p] = expr.vals
		p = compile_accs (replaces, p)
		assert typ.kind == 'Type'
		return logic.mk_align_valid_ineq (('Type', typ.val), p)
	elif expr.kind == 'Op':
		vals = [compile_accs (replaces, v) for v in expr.vals]
		return Expr ('Op', expr.typ, expr.name, vals = vals)
	elif expr.kind == 'Symbol':
		return mk_word32 (symbols[expr.name][0])
	else:
		if expr.kind not in {'Var':True, 'ConstGlobal':True,
				'Num':True, 'Invent':True, 'Type':True}:
			print expr
			assert not 'field acc compiled'
		return expr