Beispiel #1
0
	def apply_known_eqs_tm (self, n_vc, tag):
		eqs = self.fetch_known_eqs (n_vc, tag)
		if eqs == None:
			return lambda x: x
		eqs = dict ([(x, mk_smt_expr (sexpr, x.typ))
			for (x, sexpr) in eqs])
		return lambda tm: logic.recursive_term_subst (eqs, tm)
Beispiel #2
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
Beispiel #3
0
	def contract (self, name, n_vc, val, typ):
		if val in self.contractions:
			return self.contractions[val]

		name = self.local_name_before (name, n_vc)
		name = self.solv.add_def (name, mk_smt_expr (val, typ), {})
		
		self.contractions[val] = name
		return name
Beispiel #4
0
def simplify_expr_whyps(sexpr,
                        rep,
                        hyps,
                        cache=None,
                        extra_defs={},
                        bool_hyps=None):
    if cache == None:
        cache = {}
    if bool_hyps == None:
        bool_hyps = []
    if sexpr in extra_defs:
        sexpr = extra_defs[sexpr]
    if sexpr in rep.solv.defs:
        sexpr = rep.solv.defs[sexpr]
    if sexpr[0] == 'ite':
        (_, cond, x, y) = sexpr
        cond_exp = solver.mk_smt_expr(solver.flat_s_expression(cond),
                                      syntax.boolT)
        (mk_nimp, mk_not) = (syntax.mk_n_implies, syntax.mk_not)
        if rep.test_hyp_whyps(mk_nimp(bool_hyps, cond_exp), hyps, cache=cache):
            return x
        elif rep.test_hyp_whyps(mk_nimp(bool_hyps, mk_not(cond_exp)),
                                hyps,
                                cache=cache):
            return y
        x = simplify_expr_whyps(x,
                                rep,
                                hyps,
                                cache=cache,
                                extra_defs=extra_defs,
                                bool_hyps=bool_hyps + [cond_exp])
        y = simplify_expr_whyps(y,
                                rep,
                                hyps,
                                cache=cache,
                                extra_defs=extra_defs,
                                bool_hyps=bool_hyps +
                                [syntax.mk_not(cond_exp)])
        if x == y:
            return x
        return ('ite', cond, x, y)
    return sexpr
Beispiel #5
0
def simplify_expr_whyps (sexpr, rep, hyps, cache = None, extra_defs = {}):
	if cache == None:
		cache = {}
	if sexpr in extra_defs:
		sexpr = extra_defs[sexpr]
	if sexpr[0] == 'ite':
		(_, cond, x, y) = sexpr
		cond_exp = solver.mk_smt_expr (solver.flat_s_expression (cond),
			syntax.boolT)
		if rep.test_hyp_whyps (cond_exp, hyps, cache = cache):
			return x
		elif rep.test_hyp_whyps (syntax.mk_not (cond_exp), hyps,
				cache = cache):
			return y
		x = simplify_expr_whyps (x, rep, hyps, cache = cache,
			extra_defs = extra_defs)
		y = simplify_expr_whyps (y, rep, hyps, cache = cache,
			extra_defs = extra_defs)
		if x == y:
			return x
		return ('ite', cond, x, y)
	return sexpr
Beispiel #6
0
	def get_loop_pc_env (self, split, vcount):
		vcount2 = dict (vcount)
		vcount2[split] = vc_num (0)
		vcount2 = tuple (sorted (vcount2.items ()))
		prev_pc_env = self.get_node_pc_env ((split, vcount2))
		if prev_pc_env == None:
			return None
		(_, prev_env) = prev_pc_env
		def av (nm, typ, mem_name = None):
			nm2 = '%s_loop_at_%s' % (nm, split)
			return self.solv.add_var (nm2, typ,
				mem_name = mem_name)
		env = {}
		consts = set ()
		for (nm, typ) in prev_env:
			check_const = self.fast or (typ in
				[builtinTs['HTD'], builtinTs['Dom']])
			if check_const and self.is_synt_const (nm, typ, split):
				env[(nm, typ)] = prev_env[(nm, typ)]
				consts.add ((nm, typ))
			else:
				env[(nm, typ)] = av (nm + '_after', typ,
					('Loop', prev_env[(nm, typ)]))
		for (nm, typ) in prev_env:
			if (nm, typ) in consts:
				continue
			z = self.var_rep_request ((nm, typ), 'Loop',
				(split, vcount), env)
			if z:
				env[(nm, typ)] = z

		pc = mk_smt_expr (av ('pc_of', boolT), boolT)
		if self.fast:
			imp = syntax.mk_implies (pc, prev_pc_env[0])
			self.solv.assert_fact (imp, prev_env,
				unsat_tag = ('LoopPCImp', split))

		return (pc, env)
Beispiel #7
0
	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'
Beispiel #8
0
		if pc_envs == []:
			return None

		if n == 'Err':
			# we'll never care about variable values here
			# and there are sometimes a LOT of arcs to Err
			# so we save a lot of merge effort
			pc_envs = [(to_smt_expr (pc, env, self.solv), {})
				for (pc, env) in pc_envs]

		(pc, env, large) = merge_envs_pcs (pc_envs, self.solv)

		if large or len (smt_expr (pc, env, self.solv)) > 80:
			name = self.path_cond_name ((n, vcount), tag)
			name = self.solv.add_def (name, pc, env)
			pc = mk_smt_expr (name, boolT)
		
		for (nm, typ) in env:
			if len (env[(nm, typ)]) > 80:
				env[(nm, typ)] = self.contract (nm, (n, vcount),
					env[(nm, typ)], typ)

		return (pc, env)

	def contract (self, name, n_vc, val, typ):
		if val in self.contractions:
			return self.contractions[val]

		name = self.local_name_before (name, n_vc)
		name = self.solv.add_def (name, mk_smt_expr (val, typ), {})