let rec compareExp (e1: exp) (e2: exp) : bool =
e1 == e2 ||
match e1.enode, e2.enode with
| Lval lv1, Lval lv2
| StartOf lv1, StartOf lv2
| AddrOf lv1, AddrOf lv2 -> compareLval lv1 lv2
| BinOp(bop1, l1, r1, _), BinOp(bop2, l2, r2, _) ->
bop1 = bop2 && compareExp l1 l2 && compareExp r1 r2
| _ -> begin
match isInteger (constFold true e1), isInteger (constFold true e2) with
Some i1, Some i2 -> i1 = i2
| _ -> false
end
and compareLval (lv1: lval) (lv2: lval) : bool =
let rec compareOffset (off1: offset) (off2: offset) : bool =
match off1, off2 with
| Field (fld1, off1'), Field (fld2, off2') ->
fld1 == fld2 && compareOffset off1' off2'
| Index (e1, off1'), Index (e2, off2') ->
compareExp e1 e2 && compareOffset off1' off2'
| NoOffset, NoOffset -> true
| _ -> false
in
lv1 == lv2 ||
match lv1, lv2 with
| (Var vi1, off1), (Var vi2, off2) ->
vi1 == vi2 && compareOffset off1 off2
| (Mem e1, off1), (Mem e2, off2) ->
compareExp e1 e2 && compareOffset off1 off2
| _ -> false