Example #1
0
def init_case_splits (p, hyps, tags = None):
	if 'init_case_splits' in p.cached_analysis:
		return p.cached_analysis['init_case_splits']
	if tags == None:
		tags = p.pairing.tags
	poss = logic.possible_graph_divs (p)
	if len (set ([p.node_tags[n][0] for n in poss])) < 2:
		return None
	rep = rep_graph.mk_graph_slice (p)
	assert all ([p.nodes[n].kind == 'Cond' for n in poss])
	pc_map = logic.dict_list ([(rep.get_pc ((c, ())), c)
		for n in poss for c in p.nodes[n].get_conts ()
		if c not in p.loop_data])
	no_loop_restrs = tuple ([(n, vc_num (0)) for n in p.loop_heads ()])
	err_pc_hyps = [rep_graph.pc_false_hyp ((('Err', no_loop_restrs), tag))
		for tag in p.pairing.tags]
	knowledge = EqSearchKnowledge (rep, hyps + err_pc_hyps, list (pc_map))
	last_knowledge[0] = knowledge
	pc_ids = knowledge.classify_vs ()
	id_n_map = logic.dict_list ([(i, n) for (pc, i) in pc_ids.iteritems ()
		for n in pc_map[pc]])
	tag_div_ns = [[[n for n in ns if p.node_tags[n][0] == t] for t in tags]
		for (i, ns) in id_n_map.iteritems ()]
	split_pairs = [(l_ns[0], r_ns[0]) for (l_ns, r_ns) in tag_div_ns
		if l_ns and r_ns]
	p.cached_analysis['init_case_splits'] = split_pairs
	return split_pairs
Example #2
0
def proof_subproblems (p, kind, args, restrs, hyps, path):
	tags = p.pairing.tags
	if kind == 'Leaf':
		return []
	elif kind == 'Restr':
		restr = get_proof_restr (args[0], args[1])
		hyps = hyps + [restr_trivial_hyp (p, args[0], args[1], restrs)]
		return [((restr,) + restrs, hyps,
			'%s (%d limited)' % (path, args[0]))]
	elif kind == 'Split':
		split = args
		return [(restrs, hyps + split_no_loop_hyps (tags, split, restrs),
			'%d init case in %s' % (split[0][0], path)),
		(restrs, hyps + split_loop_hyps (tags, split, restrs, exit = True),
			'%d loop case in %s' % (split[0][0], path))]
	elif kind == 'CaseSplit':
		(point, tag) = args
		visit = ((point, restrs), tag)
		true_hyps = hyps + [pc_true_hyp (visit)]
		false_hyps = hyps + [pc_false_hyp (visit)]
		return [(restrs, true_hyps, 
			'true case (%d visited) in %s' % (point, path)),
		(restrs, false_hyps,
			'false case (%d not visited) in %s' % (point, path))]
	else:
		assert not 'proof node kind understood', proof.kind
Example #3
0
def noHaltHyps(split,p):
    ret = []
    all_halts = callNodes(p,fs=['halt'])
    for x in all_halts:
       ret += [rep_graph.pc_false_hyp((n_vc, p.node_tags[x][0]))
         for n_vc in default_n_vc_cases (p, x)]
    return ret
Example #4
0
def proof_subproblems(p, kind, args, restrs, hyps, path):
    tags = p.pairing.tags
    if kind == 'Leaf':
        return []
    elif kind == 'Restr':
        restr = get_proof_restr(args[0], args[1])
        hyps = hyps + [restr_trivial_hyp(p, args[0], args[1], restrs)]
        return [((restr, ) + restrs, hyps, '%s (%d limited)' % (path, args[0]))
                ]
    elif kind == 'SingleRevInduct':
        hyp = single_induct_resulting_hyp(p, restrs, args)
        return [(restrs, hyps + [hyp], path)]
    elif kind == 'Split':
        split = args
        return [
            (restrs, hyps + split_no_loop_hyps(tags, split, restrs),
             '%d init case in %s' % (split[0][0], path)),
            (restrs, hyps + split_loop_hyps(tags, split, restrs, exit=True),
             '%d loop case in %s' % (split[0][0], path))
        ]
    elif kind == 'CaseSplit':
        (point, tag) = args
        visit = ((point, restrs), tag)
        true_hyps = hyps + [pc_true_hyp(visit)]
        false_hyps = hyps + [pc_false_hyp(visit)]
        return [(restrs, true_hyps,
                 'true case (%d visited) in %s' % (point, path)),
                (restrs, false_hyps,
                 'false case (%d not visited) in %s' % (point, path))]
    else:
        assert not 'proof node kind understood', proof.kind
Example #5
0
def noHaltHyps(split, p):
    ret = []
    all_halts = callNodes(p, fs=['halt'])
    for x in all_halts:
        ret += [
            rep_graph.pc_false_hyp((n_vc, p.node_tags[x][0]))
            for n_vc in default_n_vc_cases(p, x)
        ]
    return ret
Example #6
0
def mk_not_callable_hyps (p):
	hyps = []
	for n in p.nodes:
		if p.nodes[n].kind != 'Call':
			continue
		if get_asm_callable (p.nodes[n].fname):
			continue
		tag = p.node_tags[n][0]
		hyp = rep_graph.pc_false_hyp ((default_n_vc (p, n), tag))
		hyps.append (hyp)
	return hyps
Example #7
0
def mk_not_callable_hyps(p):
    hyps = []
    for n in p.nodes:
        if p.nodes[n].kind != 'Call':
            continue
        if get_asm_callable(p.nodes[n].fname):
            continue
        tag = p.node_tags[n][0]
        hyp = rep_graph.pc_false_hyp((default_n_vc(p, n), tag))
        hyps.append(hyp)
    return hyps
Example #8
0
def find_case_split (p, head, restrs, hyps, tags = None):
	# are there multiple paths to the loop head 'head' and can we
	# restrict to one of them?
	preds = set ()
	frontier = list (set ([n2 for n in p.loop_body (head)
		for n2 in p.preds[n] if p.loop_id (n2) != head]))
	while frontier:
		n2 = frontier.pop ()
		if n2 in preds:
			continue
		preds.add (n2)
		frontier.extend (p.preds[n2])
	divs = [n2 for n2 in preds if len (set ([n3
		for n3 in p.nodes[n2].get_conts ()
			if n3 in preds or n3 == head])) > 1
		if n2 not in p.loop_data]

	trace ('find_case_split: possible divs %s.' % divs)

	rep = mk_graph_slice (p)
	err_restrs = restr_others (p, restrs, 2)
	if tags:
		l_tag, r_tag = tags
	else:
		l_tag, r_tag = p.pairing.tags
	hvis_restrs = tuple ([(head, rep_graph.vc_num (0))]) + restrs
	
	lhyps = hyps + [rep_graph.pc_false_hyp ((('Err', err_restrs), r_tag)),
		rep_graph.pc_true_hyp (((head, hvis_restrs),
			p.node_tags[head][0]))]

	# for this to be a usable case split, both paths must be possible
	for div in divs:
		dhyps = lhyps + [rep_graph.pc_true_hyp (((div, restrs),
			p.node_tags[div][0]))]
		assert p.nodes[div].kind == 'Cond'
		(_, env) = rep.get_node_pc_env ((div, restrs))
		c = to_smt_expr (p.nodes[div].cond, env, rep.solv)
		if (rep.test_hyp_whyps (c, dhyps)
				or rep.test_hyp_whyps (mk_not (c), dhyps)):
			continue
		trace ("attempting case split at %d" % div)
		sides = [n for n in p.nodes[div].get_conts ()
			if n not in p.loop_data
			if p.preds[n] == [div]]
		if not sides:
			trace ("skipping case split, no notable succ")
		n = sides[0]
		return ('CaseSplit', (n, p.node_tags[n][0]))
	trace ('find_case_split: no case splits possible')
	return (None, ())
Example #9
0
def split_loop_hyps (tags, split, restrs, exit):
	((r_split, _, _), _, _, n, _) = split
	(l_visit, _) = split_visit_visits (tags, split, restrs, vc_offs (n - 1))
	(l_cont, _) = split_visit_visits (tags, split, restrs, vc_offs (n))
	(l_tag, r_tag) = tags

	l_enter = pc_true_hyp (l_visit)
	l_exit = pc_false_hyp (l_cont)
	if exit:
		hyps = [l_enter, l_exit]
	else:
		hyps = [l_enter]
	return hyps + [hyp for offs in map (vc_offs, range (n))
		for (hyp, _) in split_hyps_at_visit (tags, split, restrs, offs)]
Example #10
0
def split_loop_hyps(tags, split, restrs, exit):
    ((r_split, _, _), _, _, n, _) = split
    (l_visit, _) = split_visit_visits(tags, split, restrs, vc_offs(n - 1))
    (l_cont, _) = split_visit_visits(tags, split, restrs, vc_offs(n))
    (l_tag, r_tag) = tags

    l_enter = pc_true_hyp(l_visit)
    l_exit = pc_false_hyp(l_cont)
    if exit:
        hyps = [l_enter, l_exit]
    else:
        hyps = [l_enter]
    return hyps + [
        hyp for offs in map(vc_offs, range(n))
        for (hyp, _) in split_hyps_at_visit(tags, split, restrs, offs)
    ]
Example #11
0
def build_compound_problem (fnames):
	"""mirrors build_problem from check for multiple functions"""
	printout ('Building compound problem for %s' % fnames)
	last_compound_problem_req[0] = list (fnames)
	p = problem.Problem (None, name = ', '.join(fnames))
	fun_tag_pairs = []

	all_tags = {}
	for (i, fn) in enumerate (fnames):
		i = len (fnames) - i
		[pair] = pairings[fn]
		next_tags = {}
		scripts = get_problem_inline_scripts (pair)
		for (pair_tag, fname) in pair.funs.items ():
			tag = '%s_%d_%s' % (fname, i, pair_tag)
			tag = syntax.fresh_name (tag, all_tags)
			next_tags[pair_tag] = tag
			p.add_entry_function (functions[fname], tag)
			p.hook_tag_hints[tag] = pair_tag
			p.replay_inline_script (tag, scripts[pair_tag])
		fun_tag_pairs.append ((next_tags, pair))

	p.pad_merge_points ()
	p.do_analysis ()

	free_hyps = []
	for (tags, pair) in fun_tag_pairs:
		(inp_eqs, _) = pair.eqs
		free_hyps += check.inst_eqs (p, (), inp_eqs, tags)
		err_vis_opts = rep_graph.vc_options ([0, 1, 2], [1])
		err_vis_vc = tuple ([(n, err_vis_opts) for n in p.loop_heads ()
			if p.node_tags[n][0] == tags['C']])
		err_vis = (('Err', err_vis_vc), tags['C'])
		free_hyps.append (rep_graph.pc_false_hyp (err_vis))

	addr_map = {}
	for n in p.nodes:
		if not p.node_tags[n][0].endswith ('_ASM'):
			continue
		if type (p.node_tags[n][1]) == tuple:
			(fname, data) = p.node_tags[n][1]
			if (logic.is_int (data) and is_addr (data)
					and not fname.startswith ("instruction'")):
				assert data not in addr_map, data
				addr_map[data] = n

	return (p, free_hyps, addr_map, fun_tag_pairs)
Example #12
0
def build_compound_problem(fnames):
    """mirrors build_problem from check for multiple functions"""
    printout('Building compound problem for %s' % fnames)
    last_compound_problem_req[0] = list(fnames)
    p = problem.Problem(None, name=', '.join(fnames))
    fun_tag_pairs = []

    all_tags = {}
    for (i, fn) in enumerate(fnames):
        i = len(fnames) - i
        [pair] = pairings[fn]
        next_tags = {}
        scripts = get_problem_inline_scripts(pair)
        for (pair_tag, fname) in pair.funs.items():
            tag = '%s_%d_%s' % (fname, i, pair_tag)
            tag = syntax.fresh_name(tag, all_tags)
            next_tags[pair_tag] = tag
            p.add_entry_function(functions[fname], tag)
            p.hook_tag_hints[tag] = pair_tag
            p.replay_inline_script(tag, scripts[pair_tag])
        fun_tag_pairs.append((next_tags, pair))

    p.pad_merge_points()
    p.do_analysis()

    free_hyps = []
    for (tags, pair) in fun_tag_pairs:
        (inp_eqs, _) = pair.eqs
        free_hyps += check.inst_eqs(p, (), inp_eqs, tags)
        err_vis_opts = rep_graph.vc_options([0, 1, 2], [1])
        err_vis_vc = tuple([(n, err_vis_opts) for n in p.loop_heads()
                            if p.node_tags[n][0] == tags['C']])
        err_vis = (('Err', err_vis_vc), tags['C'])
        free_hyps.append(rep_graph.pc_false_hyp(err_vis))

    addr_map = {}
    for n in p.nodes:
        if not p.node_tags[n][0].endswith('_ASM'):
            continue
        if type(p.node_tags[n][1]) == tuple:
            (fname, data) = p.node_tags[n][1]
            if (logic.is_int(data) and is_addr(data)
                    and not fname.startswith("instruction'")):
                assert data not in addr_map, data
                addr_map[data] = n

    return (p, free_hyps, addr_map, fun_tag_pairs)
Example #13
0
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
Example #14
0
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
Example #15
0
def leaf_condition_checks(p, restrs, hyps):
    '''checks of the final refinement conditions'''
    nrerr_pc_hyp = non_r_err_pc_hyp(p.pairing.tags, restrs)
    hyps = [nrerr_pc_hyp] + hyps
    [l_tag, r_tag] = p.pairing.tags

    nlerr_pc = pc_false_hyp((('Err', restrs), l_tag))
    # this 'hypothesis' ensures that the representation is built all
    # the way to Ret. in particular this ensures that function relations
    # are available to use in proving single-side equalities
    ret_eq = eq_hyp((true_term, (('Ret', restrs), l_tag)),
                    (true_term, (('Ret', restrs), r_tag)))

    ### TODO: previously we considered the case where 'Ret' was unreachable
    ### (as a result of unsatisfiable hyps) and proved a simpler property.
    ### we might want to restore this
    (_, out_eqs) = p.pairing.eqs
    checks = [(hyps + [nlerr_pc, ret_eq], hyp, 'Leaf eq check')
              for hyp in inst_eqs(p, restrs, out_eqs)]
    return [(hyps + [ret_eq], nlerr_pc, 'Leaf path-cond imp')] + checks
Example #16
0
def leaf_condition_checks (p, restrs, hyps):
	'''checks of the final refinement conditions'''
	nrerr_pc_hyp = non_r_err_pc_hyp (p.pairing.tags, restrs)
	hyps = [nrerr_pc_hyp] + hyps
	[l_tag, r_tag] = p.pairing.tags

	nlerr_pc = pc_false_hyp ((('Err', restrs), l_tag))
	# this 'hypothesis' ensures that the representation is built all
	# the way to Ret. in particular this ensures that function relations
	# are available to use in proving single-side equalities
	ret_eq = eq_hyp ((true_term, (('Ret', restrs), l_tag)),
		(true_term, (('Ret', restrs), r_tag)))

	### TODO: previously we considered the case where 'Ret' was unreachable
	### (as a result of unsatisfiable hyps) and proved a simpler property.
	### we might want to restore this
	(_, out_eqs) = p.pairing.eqs
	checks = [(hyps + [nlerr_pc, ret_eq], hyp, 'Leaf eq check') for hyp in
		inst_eqs (p, restrs, out_eqs)]
	return [(hyps + [ret_eq], nlerr_pc, 'Leaf path-cond imp')] + checks
Example #17
0
def init_proof_case_split (p, restrs, hyps):
	ps = init_case_splits (p, hyps)
	if ps == None:
		return None
	p.cached_analysis.setdefault ('finished_init_case_splits', [])
	fin = p.cached_analysis['finished_init_case_splits']
	known_s = set.union (set (restrs), set (hyps))
	for rs in fin:
		if rs <= known_s:
			return None
	rep = rep_graph.mk_graph_slice (p)
	no_loop_restrs = tuple ([(n, vc_num (0)) for n in p.loop_heads ()])
	err_pc_hyps = [rep_graph.pc_false_hyp ((('Err', no_loop_restrs), tag))
		for tag in p.pairing.tags]
	for (n1, n2) in ps:
		pc = rep.get_pc ((n1, ()))
		if rep.test_hyp_whyps (pc, hyps + err_pc_hyps):
			continue
		if rep.test_hyp_whyps (mk_not (pc), hyps + err_pc_hyps):
			continue
		case_split_tr.append ((n1, restrs, hyps))
		return ('CaseSplit', ((n1, p.node_tags[n1][0]), [n1, n2]))
	fin.append (known_s)
	return None
Example #18
0
		min_vc = vc_offs (max (0, x - 1))
	elif x > 1:
		min_vc = vc_num (x - 1)
	else:
		min_vc = None
	if min_vc:
		init_check = [(hyps, pc_true_hyp (visit (min_vc)),
			'Check of restr min %d %s for %d' % (x, kind, n))]
	else:
		init_check = []

	# if we can reach node n with (y - 1) visits to n, then the next
	# node will have y visits to n, which we are disallowing
	# thus we show that this visit is impossible
	top_vc = VisitCount (kind, y - 1)
	top_check = (hyps, pc_false_hyp (visit (top_vc)),
		'Check of restr max %d %s for %d' % (y, kind, n))
	return init_check + [top_check]

def split_init_step_checks (p, restrs, hyps, split, tags = None):
	(_, _, _, n, _) = split
	if tags == None:
		tags = p.pairing.tags

	err_hyp = split_r_err_pc_hyp (p, split, restrs, tags = tags)
	hyps = [err_hyp] + hyps
	checks = []
	for i in range (n):
		(l_visit, r_visit) = split_visit_visits (tags, split,
			restrs, vc_num (i))
		lpc_hyp = pc_true_hyp (l_visit)
Example #19
0
def split_no_loop_hyps (tags, split, restrs):
	((_, (l_seq_start, l_step), _), _, _, n, _) = split

	(l_visit, _) = split_visit_visits (tags, split, restrs, vc_num (n)) 

	return [pc_false_hyp (l_visit)]
Example #20
0
def non_r_err_pc_hyp (tags, restrs):
	return pc_false_hyp ((('Err', restrs), tags[1]))
Example #21
0
def non_r_err_pc_hyp(tags, restrs):
    return pc_false_hyp((('Err', restrs), tags[1]))
Example #22
0
def split_no_loop_hyps(tags, split, restrs):
    ((_, (l_seq_start, l_step), _), _, _, n, _) = split

    (l_visit, _) = split_visit_visits(tags, split, restrs, vc_num(n))

    return [pc_false_hyp(l_visit)]
Example #23
0
        min_vc = vc_offs(max(0, x - 1))
    elif x > 1:
        min_vc = vc_num(x - 1)
    else:
        min_vc = None
    if min_vc:
        init_check = [(hyps, pc_true_hyp(visit(min_vc)),
                       'Check of restr min %d %s for %d' % (x, kind, n))]
    else:
        init_check = []

    # if we can reach node n with (y - 1) visits to n, then the next
    # node will have y visits to n, which we are disallowing
    # thus we show that this visit is impossible
    top_vc = VisitCount(kind, y - 1)
    top_check = (hyps, pc_false_hyp(visit(top_vc)),
                 'Check of restr max %d %s for %d' % (y, kind, n))
    return init_check + [top_check]


def split_init_step_checks(p, restrs, hyps, split, tags=None):
    (_, _, _, n, _) = split
    if tags == None:
        tags = p.pairing.tags

    err_hyp = split_r_err_pc_hyp(p, split, restrs, tags=tags)
    hyps = [err_hyp] + hyps
    checks = []
    for i in range(n):
        (l_visit, r_visit) = split_visit_visits(tags, split, restrs, vc_num(i))
        lpc_hyp = pc_true_hyp(l_visit)