1 # ScratchABlock - Program analysis and decompilation framework
3 # Copyright (c) 2015-2018 Paul Sokolovsky
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """Expression transformations using Prolog-style inferences"""
21 from xform_expr_basic
import expr_neg
27 def __init__(self
, name
):
31 return "V(%r)" % self
.name
37 class Failed(Exception):
41 def _uni(ex
, pat
, ctx
):
42 # print("_uni: %r vs %r" % (ex, pat))
44 if isinstance(pat
, V
):
45 if pat
.name
in ctx
and ctx
[pat
.name
] != ex
:
49 elif type(ex
) is type(pat
):
50 if isinstance(ex
, EXPR
):
51 if len(ex
.args
) == len(pat
.args
):
52 _uni(ex
.op
, pat
.op
, ctx
)
53 for i
in range(len(ex
.args
)):
54 _uni(ex
.args
[i
], pat
.args
[i
], ctx
)
57 elif isinstance(ex
, MEM
):
58 if ex
.type == pat
.type:
59 _uni(ex
.expr
, pat
.expr
, ctx
)
62 elif isinstance(ex
, REG
):
63 _uni(ex
.name
, pat
.name
, ctx
)
64 elif isinstance(ex
, ADDR
):
65 _uni(ex
.addr
, pat
.addr
, ctx
)
66 elif isinstance(ex
, VALUE
):
67 _uni(ex
.val
, pat
.val
, ctx
)
71 raise Failed(str((ex
, pat
)))
85 EXPR("-", V("x"), V("x")),
90 EXPR("^", V("x"), V("x")),
95 EXPR("+", V("x"), VALUE(0)),
100 EXPR("^", V("x"), VALUE(0)),
105 EXPR("&", VALUE(V("x1")), VALUE(V("x2"))),
106 lambda W
: VALUE(W
["x1"] & W
["x2"])
110 EXPR("-", VALUE(V("x1")), VALUE(V("x2"))),
111 lambda W
: VALUE(W
["x1"] - W
["x2"])
115 EXPR(V("rel_op"), EXPR("+", V("x1"), V("x2")), VALUE(0)),
116 lambda W
: W
["rel_op"] in ("==", "!=", "<", "<=", ">=", ">"),
117 lambda W
: EXPR(W
["rel_op"], W
["x1"], expr_neg(W
["x2"]))
121 EXPR("!", EXPR(V("rel_op"), V("x1"), V("x2"))),
122 lambda W
: W
["rel_op"] in ("==", "!=", "<", "<=", ">=", ">"),
123 lambda W
: EXPR(COND
.NEG
[W
["rel_op"]], W
["x1"], W
["x2"])
127 EXPR("!=", EXPR(V("rel_op"), V("x1"), V("x2")), VALUE(0)),
128 lambda W
: W
["rel_op"] in ("==", "!=", "<", "<=", ">=", ">"),
129 lambda W
: EXPR(W
["rel_op"], W
["x1"], W
["x2"])
133 EXPR("==", EXPR(V("rel_op"), V("x1"), V("x2")), VALUE(0)),
134 lambda W
: W
["rel_op"] in ("==", "!=", "<", "<=", ">=", ">"),
135 lambda W
: EXPR(COND
.NEG
[W
["rel_op"]], W
["x1"], W
["x2"])
148 #print("Trying", repr(pat))
155 #print("Test passed")
162 if __name__
== "__main__":
163 ex
= EXPR("-", REG("a1"), REG("a1"))
164 ex
= EXPR("^", REG("a1"), REG("a1"))
165 ex
= EXPR("^", REG("a1"), VALUE(1))
166 ex
= EXPR("==", EXPR("+", REG("a1"), EXPR("NEG", REG("a2"))), VALUE(0))
167 ex
= EXPR("!=", EXPR("+", REG("a1"), EXPR("NEG", REG("a2"))), VALUE(0))
168 ex
= EXPR("<", EXPR("+", REG("a1"), EXPR("NEG", REG("a2"))), VALUE(0))