Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • yassine.ettayeb/anastat-frama-c-24-25
  • nicolas.descamps/anastat
  • stanislas.plowiecki/anastat-frama-c-24-25
  • thomas.norodom/norodom-ana-stat-frama-c-24-25
  • quentin.vicens/ana-stat-frama-c-24-25
  • rayan.lachguel/anastat-frama-c-24-25
  • virgile.prevosto/anastat-frama-c-24-25
  • merlin.baviere/ana-stat-frama-c-24-25-merlin-baviere
8 results
Select Git revision
  • main
1 result
Show changes
Showing
with 262 additions and 41 deletions
File added
File added
File moved
......@@ -82,26 +82,76 @@ def eval_bexp(env: abstract_env, e: BoolExpr) -> abstract_value[bool] | None:
class Constant_propagation(Transfer[state]):
variables: frozenset[str]
def __init__(self,instr):
self.variables = variables_of_instr(instr)
def bottom(self) -> state:
...
return None
def init_state(self) -> state:
...
s = {}
for var in self.variables:
s[var] = abstract_value(None)
return s
def join(self,s1:state,s2:state) -> state:
...
def included(self,s1: state,s2: state) -> bool:
...
if s1 is None: return s2
elif s2 is None: return s1
else:
s=s1.copy()
for var in s2:
if not(var in s1):
s[var]=s2[var]
elif s1[var] == abstract_value(None):
s[var]=s2[var]
elif s2[var] == abstract_value(None):
pass
else:
s[var]=abstract_value(None)
return s1
def included(self, s1: state,s2: state) -> bool:
included = True
if s1 is None:
return True
if s2 is None:
return False
else:
for var in s1:
included = included and ((s1[var]==s2[var]) | (s1[var] == abstract_value(None)))
return included
def tr_skip(self,s: state) -> state:
...
def tr_set(self,s: state,v: str,e: ArithExpr) -> state:
...
return s.copy()
def tr_set(self, s: state, v: str, e: ArithExpr) -> state:
s1 = s.copy()
s1[v]=eval_aexp(s, e)
return s1
def tr_test(self,s: state,c: BoolExpr) -> state:
...
if eval_bexp(s, c) is False:
return None
else:
if s:
return s.copy()
else:
return s
def tr_err(self,s: state,e: Expr) -> state:
...
if isinstance(e,ArithExpr):
if eval_aexp(s ,e) is not None:
return None
else:
return s.copy()
else:
if isinstance(e,BoolExpr):
if eval_bexp(s ,e) is not None:
return None
else:
return s.copy()
else: assert False
......@@ -40,7 +40,30 @@ class Transfer[S](Protocol):
def fixpoint_iteration[T](transfer: Transfer[T], cfg: Cfg) -> dict[Node,T]:
"""computes the fixpoint for the given transfer functions over the given CfG
output maps each node to the computed state
"""
raise NotImplementedError
result = {}
for n in cfg.g.nodes:
result[n]=transfer.bottom()
result[cfg.init_node] = transfer.init_state()
worklist = [(cfg.init_node,n,l) for (n,l) in cfg.init_node.succs]
while worklist:
src,dst,label = worklist.pop(0)
previous_state = result[dst]
source_state = result[src]
match label:
case LSkip():
new_state = transfer.join(previous_state, transfer.tr_skip(source_state))
case LTest(c):
new_state = transfer.join(previous_state, transfer.tr_test(source_state, c))
case LErr(e):
new_state = transfer.join(previous_state, transfer.tr_err(source_state, e))
case LSet(v, exp):
new_state = transfer.join(previous_state, transfer.tr_set(source_state, v, exp))
case _:
raise ValueError(f"Type de label inconnu : {label}")
if transfer.included(new_state,previous_state): pass
else: worklist += [(dst,n,l) for (n,l) in dst.succs]
result[dst]=new_state
return result
......@@ -12,39 +12,56 @@ def eval_aexp(env: dict[str,int], exp: ArithExpr) -> int | None:
"""evaluates an arithmetic expression"""
match exp:
case AECst(value):
raise NotImplementedError
return value
case AEVar(var):
raise NotImplementedError
if(var in env): return env[var]
else: return 0
case AEUop(uop,expr):
raise NotImplementedError
match uop:
case Uop.OPP:
return -1*eval_aexp(env, expr)
case _:
assert False
case AEBop(bop,left_expr,right_expr):
raise NotImplementedError
match bop:
case Bop.ADD:
return eval_aexp(env, left_expr)+eval_aexp(env, right_expr)
case Bop.MUL:
return eval_aexp(env, left_expr)*eval_aexp(env, right_expr)
case Bop.DIV:
if (eval_aexp(env, right_expr)!=0): return eval_aexp(env, left_expr)/eval_aexp(env, right_expr)
else: return None
case _:
assert False
case _: assert False
def eval_bexp(env: dict[str,int], exp:BoolExpr) -> bool | None:
"""evaluates a boolean expression"""
match exp:
case BEPlain(aexpr):
raise NotImplementedError
return eval_aexp(env, aexpr)!=0
case BEEq(left_expr,right_expr):
raise NotImplementedError
return eval_aexp(env, left_expr) == eval_aexp(env, right_expr)
case BELeq(left_expr,right_expr):
raise NotImplementedError
return eval_aexp(env, left_expr) <= eval_aexp(env, right_expr)
case BENeg(expr):
raise NotImplementedError
return not(eval_bexp(env, expr))
case _: assert False
def eval_instr(env: dict[str,int], instr: Instr) -> dict[str,int] | None:
"""evaluates an instruction"""
match instr:
case ISkip():
raise NotImplementedError
return env
case ISet(var,expr):
raise NotImplementedError
newenv = env.copy()
newenv[var]=eval_aexp(env, expr); return newenv
case ISeq(first,second):
raise NotImplementedError
return eval_instr(eval_instr(env, first), second)
case ICond(cond,true_branch,false_branch):
raise NotImplementedError
if eval_bexp(env, cond): return eval_instr(env, true_branch)
else: return eval_instr(env, false_branch)
case ILoop(cond,body):
raise NotImplementedError
if eval_bexp(env, cond): return eval_instr(eval_instr(env, body), ILoop(cond,body))
else: return env
case _: assert False
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
......@@ -167,32 +167,93 @@ def sign_div(s1: sign, s2: sign) -> sign | Top | None:
case (sign.NEG | sign.SNEG), sign.SNEG: return sign.POS
def eval_aexp(env: abstract_env, e: ArithExpr) -> sign | Top | None:
"""evaluate an arithmetic expression in an abstract environment
returns None in case of error
"""
"""Evaluate an arithmetic expression in an abstract environment."""
match e:
case AECst(value):
raise NotImplementedError
if value > 0:
return sign.POS
elif value < 0:
return sign.NEG
else:
return sign.NZ
case AEVar(var):
raise NotImplementedError
case AEUop(uop,expr):
raise NotImplementedError
case AEBop(bop,left_expr,right_expr):
raise NotImplementedError
case _: pass
if var in env:
return env[var]
else:
return None
case AEUop(uop, expr):
val = eval_aexp(env, expr)
if val is None:
return None
if isinstance(val, Top):
return Top()
if uop == Uop.OPP:
return sign_opp(val)
case AEBop(bop, left_expr, right_expr):
left_val = eval_aexp(env, left_expr)
right_val = eval_aexp(env, right_expr)
if left_val is None or right_val is None:
return None
if isinstance(left_val, Top) or isinstance(right_val, Top):
return Top()
if bop == Bop.ADD:
return sign_add(left_val, right_val)
elif bop == Bop.MUL:
return sign_mul(left_val, right_val)
elif bop == Bop.DIV:
return sign_div(left_val, right_val)
else:
return None
case _:
return None
def eval_bexp(env: abstract_env, e: BoolExpr) -> bool | BTop | None:
"""abstract evaluation of a boolean expression"""
"""Abstract evaluation of a boolean expression."""
match e:
case BEPlain(aexpr):
raise NotImplementedError
case BEEq(left_expr,right_expr):
raise NotImplementedError
case BELeq(left_expr,right_expr):
raise NotImplementedError
case BEPlain(aexpr):
val = eval_aexp(env, aexpr)
if val is None:
return None
if isinstance(val, Top):
return BTop(False)
return BTop(True)
case BEEq(left_expr, right_expr):
left_val = eval_aexp(env, left_expr)
right_val = eval_aexp(env, right_expr)
if left_val is None or right_val is None:
return None
if isinstance(left_val, Top) or isinstance(right_val, Top):
return BTop(False)
if left_val == right_val:
return True
return False
case BELeq(left_expr, right_expr):
left_val = eval_aexp(env, left_expr)
right_val = eval_aexp(env, right_expr)
if left_val is None or right_val is None:
return None
if isinstance(left_val, Top) or isinstance(right_val, Top):
return BTop(False)
return sign_leq(left_val, right_val)
case BENeg(expr):
raise NotImplementedError
case _: pass
val = eval_bexp(env, expr)
if val is None:
return None
if isinstance(val, Top):
return BTop(False)
return not val
case _:
return None
def reduce_eq_sign(s: state, x: str, expr: ArithExpr) -> state:
"""reduce the value associated to x in s under the hypothesis that x == expr"""
......@@ -314,18 +375,38 @@ class Sign_interp(Transfer[state]):
def tr_skip(self,s: state) -> state:
return s
def tr_set(self,s: state,v: str,e: ArithExpr) -> state:
raise NotImplementedError
def tr_set(self, s: state, v: str, e: ArithExpr) -> state:
"""Handle the assignment v = e"""
if s is None: return None
value = eval_aexp(s, e)
if value is None: return None
if isinstance(value, Top): return s
s2 = s.copy()
s2[v]=value
return s2
def tr_test(self,s: state,c: BoolExpr) -> state:
raise NotImplementedError
def tr_test(self, s: state, c: BoolExpr) -> state:
"""Handle the boolean test"""
if s is None: return None
result = eval_bexp(s, c)
if result is None: return None
if isinstance(result, bool):
if result:
return s
else:
return None
else:
return s
def tr_err(self,s: state,e: Expr) -> state:
if s is None: return s
if isinstance(e,ArithExpr):
raise NotImplementedError
return None
if isinstance(e,BoolExpr):
raise NotImplementedError
return None
def analyze(i: Instr) -> None:
cfg = Cfg(i)
......
File moved