Esempio n. 1
0
def linear_eq_induct_base_checks (p, restrs, hyps, tag, split, eqs):
    tests = []
    details = (split, (0, 1), eqs)
    for i in [0, 1]:
        reach = split_visit_one_visit (tag, details, restrs, vc_num (i))
        nhyps = [pc_true_hyp (reach)]
        tests.extend ([(hyps + nhyps, hyp,
            'Base check (%s, %d) at induct step for %d' % (desc,
                i, split)) for (hyp, desc) in
            linear_eq_hyps_at_visit (tag, split, eqs,
                restrs, vc_num (i))])
    return tests
Esempio n. 2
0
def single_loop_induct_base_checks(p, restrs, hyps, tag, split, n, eqs):
    tests = []
    details = (split, (0, 1), eqs)
    for i in range(n + 1):
        reach = split_visit_one_visit(tag, details, restrs, vc_num(i))
        nhyps = [pc_true_hyp(reach)]
        tests.extend([
            (hyps + nhyps, hyp,
             'Base check (%s, %d) at induct step for %d' % (desc, i, split))
            for (hyp, desc
                 ) in loop_eq_hyps_at_visit(tag, split, eqs, restrs, vc_num(i))
        ])
    return tests
Esempio n. 3
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
Esempio n. 4
0
	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))
Esempio n. 5
0
def split_hyps_at_visit (tags, split, restrs, visit):
	(l_details, r_details, eqs, _, _) = split
	(l_split, (l_seq_start, l_step), l_eqs) = l_details
	(r_split, (r_seq_start, r_step), r_eqs) = r_details

	(l_visit, r_visit) = split_visit_visits (tags, split, restrs, visit)
	(l_start, r_start) = split_visit_visits (tags, split, restrs, vc_num (0))
	(l_tag, r_tag) = tags

	def mksub (v):
		return lambda exp: logic.var_subst (exp, {('%i', word32T) : v},
			must_subst = False)
	def inst (exp):
		return logic.inst_eq_at_visit (exp, visit)
	zsub = mksub (mk_word32 (0))
	if visit.kind == 'Number':
		lsub = mksub (mk_word32 (visit.n))
	else:
		lsub = mksub (mk_plus (mk_var ('%n', word32T),
			mk_word32 (visit.n)))

	hyps = [(Hyp ('PCImp', l_visit, r_visit), 'pc imp'),
		(Hyp ('PCImp', l_visit, l_start), '%s pc imp' % l_tag),
		(Hyp ('PCImp', r_visit, r_start), '%s pc imp' % r_tag)]
	hyps += [(eq_hyp ((zsub (l_exp), l_start), (lsub (l_exp), l_visit),
				(l_split, r_split)), '%s const' % l_tag)
			for l_exp in l_eqs if inst (l_exp)]
	hyps += [(eq_hyp ((zsub (r_exp), r_start), (lsub (r_exp), r_visit),
				(l_split, r_split)), '%s const' % r_tag)
			for r_exp in r_eqs if inst (r_exp)]
	hyps += [(eq_hyp ((lsub (l_exp), l_visit), (lsub (r_exp), r_visit),
				(l_split, r_split)), 'eq')
			for (l_exp, r_exp) in eqs
			if inst (l_exp) and inst (r_exp)]
	return hyps
Esempio n. 6
0
def split_hyps_at_visit(tags, split, restrs, visit):
    (l_details, r_details, eqs, _, _) = split
    (l_split, (l_seq_start, l_step), l_eqs) = l_details
    (r_split, (r_seq_start, r_step), r_eqs) = r_details

    (l_visit, r_visit) = split_visit_visits(tags, split, restrs, visit)
    (l_start, r_start) = split_visit_visits(tags, split, restrs, vc_num(0))
    (l_tag, r_tag) = tags

    def mksub(v):
        return lambda exp: logic.var_subst(exp, {('%i', word32T): v},
                                           must_subst=False)

    def inst(exp):
        return logic.inst_eq_at_visit(exp, visit)

    zsub = mksub(mk_word32(0))
    if visit.kind == 'Number':
        lsub = mksub(mk_word32(visit.n))
    else:
        lsub = mksub(mk_plus(mk_var('%n', word32T), mk_word32(visit.n)))

    hyps = [(Hyp('PCImp', l_visit, r_visit), 'pc imp'),
            (Hyp('PCImp', l_visit, l_start), '%s pc imp' % l_tag),
            (Hyp('PCImp', r_visit, r_start), '%s pc imp' % r_tag)]
    hyps += [(eq_hyp((zsub(l_exp), l_start), (lsub(l_exp), l_visit),
                     (l_split, r_split)), '%s const' % l_tag)
             for l_exp in l_eqs if inst(l_exp)]
    hyps += [(eq_hyp((zsub(r_exp), r_start), (lsub(r_exp), r_visit),
                     (l_split, r_split)), '%s const' % r_tag)
             for r_exp in r_eqs if inst(r_exp)]
    hyps += [(eq_hyp((lsub(l_exp), l_visit), (lsub(r_exp), r_visit),
                     (l_split, r_split)), 'eq') for (l_exp, r_exp) in eqs
             if inst(l_exp) and inst(r_exp)]
    return hyps
Esempio n. 7
0
	def get_var (k):
		head = rep.p.loop_id (i)
		if i != head:
			k += 1
		restrs2 = restrs + ((head, vc_num (k)), )
		(pc, env) = rep.get_node_pc_env ((i, restrs2))
		return (to_smt_expr (pc, env, rep.solv),
			to_smt_expr (v_i, env, rep.solv))
Esempio n. 8
0
def default_n_vc_cases(p, n):
    head = p.loop_id(n)
    general = [(n2, rep_graph.vc_options([0], [1])) for n2 in p.loop_heads()
               if n2 != head]

    if head:
        return [(n, tuple(general + [(head, rep_graph.vc_num(1))])),
                (n, tuple(general + [(head, rep_graph.vc_offs(1))]))]
    specific = [(head, rep_graph.vc_offs(1)) for _ in [1] if head]
    return [(n, tuple(general + specific))]
Esempio n. 9
0
def default_n_vc_cases(p, n):
    head = p.loop_id(n)
    general = [(n2, rep_graph.vc_options([0], [1])) for n2 in p.loop_heads() if n2 != head]

    if head:
        return [
            (n, tuple(general + [(head, rep_graph.vc_num(1))])),
            (n, tuple(general + [(head, rep_graph.vc_offs(1))])),
        ]
    specific = [(head, rep_graph.vc_offs(1)) for _ in [1] if head]
    return [(n, tuple(general + specific))]
Esempio n. 10
0
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)
        # this trivial 'hyp' ensures the rep is built to include
        # the matching rhs visits when checking lhs consts
        rpc_triv_hyp = rep_graph.pc_triv_hyp(r_visit)
        vis_hyps = split_hyps_at_visit(tags, split, restrs, vc_num(i))

        for (hyp, desc) in vis_hyps:
            checks.append((hyps + [lpc_hyp, rpc_triv_hyp], hyp,
                           'Induct check at visit %d: %s' % (i, desc)))
    return checks
Esempio n. 11
0
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)
		# this trivial 'hyp' ensures the rep is built to include
		# the matching rhs visits when checking lhs consts
		rpc_triv_hyp = rep_graph.pc_triv_hyp (r_visit)
		vis_hyps = split_hyps_at_visit (tags, split, restrs, vc_num (i))

		for (hyp, desc) in vis_hyps:
			checks.append ((hyps + [lpc_hyp, rpc_triv_hyp], hyp,
				'Induct check at visit %d: %s' % (i, desc)))
	return checks
Esempio n. 12
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, ())
Esempio n. 13
0
def split_visit_one_visit (tag, details, restrs, visit):
	if details == None:
		return None
	(split, (seq_start, step), eqs) = details

	# the split point sequence at low numbers ('Number') is offset
	# by the point the sequence starts. At symbolic offsets we ignore
	# that, instead having the loop counter for the two sequences
	# be the same number of iterations after the sequence start.
	if visit.kind == 'Offset':
		visit = vc_offs (visit.n * step)
	else:
		visit = vc_num (seq_start + (visit.n * step))

	visit = ((split, ((split, visit), ) + restrs), tag)
	return visit
Esempio n. 14
0
def split_visit_one_visit(tag, details, restrs, visit):
    if details == None:
        return None
    (split, (seq_start, step), eqs) = details

    # the split point sequence at low numbers ('Number') is offset
    # by the point the sequence starts. At symbolic offsets we ignore
    # that, instead having the loop counter for the two sequences
    # be the same number of iterations after the sequence start.
    if visit.kind == 'Offset':
        visit = vc_offs(visit.n * step)
    else:
        visit = vc_num(seq_start + (visit.n * step))

    visit = ((split, ((split, visit), ) + restrs), tag)
    return visit
Esempio n. 15
0
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
Esempio n. 16
0
def loop_eq_hyps_at_visit(tag, split, eqs, restrs, visit_num, use_if_at=False):
    details = (split, (0, 1), eqs)
    visit = split_visit_one_visit(tag, details, restrs, visit_num)
    start = split_visit_one_visit(tag, details, restrs, vc_num(0))

    def mksub(v):
        return lambda exp: logic.var_subst(exp, {('%i', word32T): v},
                                           must_subst=False)

    zsub = mksub(mk_word32(0))
    if visit_num.kind == 'Number':
        isub = mksub(mk_word32(visit_num.n))
    else:
        isub = mksub(mk_plus(mk_var('%n', word32T), mk_word32(visit_num.n)))

    hyps = [(Hyp('PCImp', visit, start), '%s pc imp' % tag)]
    hyps += [(eq_hyp((zsub(exp), start), (isub(exp), visit), (split, 0),
                     use_if_at=use_if_at), '%s const' % tag) for exp in eqs
             if logic.inst_eq_at_visit(exp, visit_num)]

    return hyps
Esempio n. 17
0
def linear_eq_hyps_at_visit (tag, split, eqs, restrs, visit_num):
    details = (split, (0, 1), eqs)
    visit = split_visit_one_visit (tag, details, restrs, visit_num)
    start = split_visit_one_visit (tag, details, restrs, vc_num (0))
    from syntax import mk_word32, mk_plus, mk_var, word32T

    def mksub (v):
            return lambda exp: logic.var_subst (exp, {('%i', word32T) : v},
                    must_subst = False)
    zsub = mksub (mk_word32 (0))
    if visit_num.kind == 'Number':
            isub = mksub (mk_word32 (visit_num.n))
    else:
            isub = mksub (mk_plus (mk_var ('%n', word32T),
                    mk_word32 (visit_num.n)))

    hyps = [(Hyp ('PCImp', visit, start), '%s pc imp' % tag)]
    hyps += [(eq_hyp ((zsub (exp), start), (isub (exp), visit),
                            (split, 0)), '%s const' % tag)
                    for exp in eqs if logic.inst_eq_at_visit (exp, visit_num)]

    return hyps
Esempio n. 18
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
Esempio n. 19
0
def single_induct_resulting_hyp(p, restrs, rev_induct_args):
    (point, _, (pred, _)) = rev_induct_args
    (tag, _) = p.node_tags[point]
    vis = ((point, restrs + tuple([(point, vc_num(0))])), tag)
    return rep_graph.true_if_at_hyp(pred, vis)
Esempio n. 20
0
		p.node_tags[n][0]))

def proof_restr_checks (n, (kind, (x, y)), p, restrs, hyps):
	restr = get_proof_restr (n, (kind, (x, y)))
	ncerr_hyp = non_r_err_pc_hyp (p.pairing.tags,
		restr_others (p, (restr, ) + restrs, 2))
	hyps = [ncerr_hyp] + hyps
	def visit (vc):
		return ((n, ((n, vc), ) + restrs), p.node_tags[n][0])

	# this cannot be more uniform because the representation of visit
	# at offset 0 is all a bit odd, with n being the only node so visited:
	if kind == 'Offset':
		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]
Esempio n. 21
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)]
Esempio n. 22
0
	def vis (n, i):
		if n != p.loop_id (n):
			i = i + 1
		return (n, tuple ([(p.loop_id (n), vc_num (i))]) + restrs)
Esempio n. 23
0
def proof_restr_checks(n, (kind, (x, y)), p, restrs, hyps):
    restr = get_proof_restr(n, (kind, (x, y)))
    ncerr_hyp = non_r_err_pc_hyp(p.pairing.tags,
                                 restr_others(p, (restr, ) + restrs, 2))
    hyps = [ncerr_hyp] + hyps

    def visit(vc):
        return ((n, ((n, vc), ) + restrs), p.node_tags[n][0])

    # this cannot be more uniform because the representation of visit
    # at offset 0 is all a bit odd, with n being the only node so visited:
    if kind == 'Offset':
        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]
Esempio n. 24
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)]