Skip to content

Commit d1424df

Browse files
committed
ARM: convert annotations to handle result types
1 parent e84cf58 commit d1424df

File tree

8 files changed

+585
-138
lines changed

8 files changed

+585
-138
lines changed

chb/app/InstrXData.py

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------------------------------------------------
55
# The MIT License (MIT)
66
#
7-
# Copyright (c) 2021-2024 Aarno Labs LLC
7+
# Copyright (c) 2021-2025 Aarno Labs LLC
88
#
99
# Permission is hereby granted, free of charge, to any person obtaining a copy
1010
# of this software and associated documentation files (the "Software"), to deal
@@ -73,8 +73,10 @@ def __init__(
7373
self.expanded = False
7474
self._ssavals: List[XVariable] = []
7575
self._vars: List[XVariable] = []
76+
self._vars_r: List[Optional[XVariable]] = []
7677
self._types: List["BCTyp"] = []
7778
self._xprs: List[XXpr] = []
79+
self._xprs_r: List[Optional[XXpr]] = []
7880
self._intervals: List[XInterval] = []
7981
self._strs: List[str] = []
8082
self._ints: List[int] = []
@@ -121,6 +123,12 @@ def vars(self) -> List[XVariable]:
121123
self._expand()
122124
return self._vars
123125

126+
@property
127+
def vars_r(self) -> List[Optional[XVariable]]:
128+
if not self.expanded:
129+
self._expand()
130+
return self._vars_r
131+
124132
@property
125133
def types(self) -> List["BCTyp"]:
126134
if not self.expanded:
@@ -161,12 +169,29 @@ def get_var(self, index: int) -> XVariable:
161169
+ str(len(self.vars))
162170
+ ")")
163171

172+
def get_var_x(self, index: int) -> Optional[XVariable]:
173+
if index < len(self.vars_r):
174+
return self.vars_r[index]
175+
else:
176+
raise UF.CHBError(
177+
"xdata: var-index out-of-bound: "
178+
+ str(index)
179+
+ " (length is "
180+
+ str(len(self.vars))
181+
+ ")")
182+
164183
@property
165184
def xprs(self) -> List[XXpr]:
166185
if not self.expanded:
167186
self._expand()
168187
return self._xprs
169188

189+
@property
190+
def xprs_r(self) -> List[Optional[XXpr]]:
191+
if not self.expanded:
192+
self._expand()
193+
return self._xprs_r
194+
170195
@property
171196
def intervals(self) -> List[XInterval]:
172197
if not self.expanded:
@@ -223,6 +248,18 @@ def reachingdeflocs_for_s(self, var: str) -> Sequence[XSymbol]:
223248
return rdef.deflocations
224249
return []
225250

251+
@property
252+
def is_ok(self) -> bool:
253+
"""Returns false if the data key is ar: and one or more of the
254+
variables and/or expressions are error values (None). Returns true
255+
otherwise."""
256+
257+
key = self.tags[0]
258+
if key.startswith("ar:"):
259+
return all(self.vars_r) and all(self.xprs_r)
260+
else:
261+
return True
262+
226263
def _expand(self) -> None:
227264
"""Expand the arguments based on the argument string in the keys.
228265
@@ -240,49 +277,72 @@ def _expand(self) -> None:
240277
key = self.tags[0]
241278
if key.startswith("a:"):
242279
keyletters = key[2:]
243-
for (i, c) in enumerate(keyletters):
244-
arg = self.args[i]
245-
xd = self.xprdictionary
246-
bd = self.bdictionary
247-
bcd = self.bcdictionary
248-
if c == "v":
280+
use_result = False
281+
elif key.startswith("ar:"):
282+
keyletters = key[3:]
283+
use_result = True
284+
else:
285+
chklogger.logger.error(
286+
"InstrXData tag: %s not recognized", key)
287+
return
288+
289+
for (i, c) in enumerate(keyletters):
290+
arg = self.args[i]
291+
xd = self.xprdictionary
292+
bd = self.bdictionary
293+
bcd = self.bcdictionary
294+
if c == "v":
295+
if use_result:
296+
if arg == -2:
297+
self._vars_r.append(None)
298+
else:
299+
self._vars_r.append(xd.variable(arg))
300+
else:
249301
self._vars.append(xd.variable(arg))
250-
elif c == "x":
251-
self._xprs.append(xd.xpr(arg))
252-
elif c == "a":
253-
self._xprs.append(xd.xpr(arg))
254-
elif c == "s":
255-
self._strs.append(bd.string(arg))
256-
elif c == "i":
257-
self._intervals.append(xd.interval(arg))
258-
elif c == "l":
259-
self._ints.append(arg)
260-
elif c == "t":
261-
self._types.append(bcd.typ(arg))
262-
elif c == "r":
263-
varinvd = self.varinvdictionary
264-
rdef = varinvd.var_invariant_fact(arg) if arg >= 0 else None
265-
rdef = cast(Optional[ReachingDefFact], rdef)
266-
self._reachingdefs.append(rdef)
267-
elif c == "d":
268-
varinvd = self.varinvdictionary
269-
use = varinvd.var_invariant_fact(arg) if arg >= 0 else None
270-
use = cast(Optional[DefUse], use)
271-
self._defuses.append(use)
272-
elif c == "h":
273-
varinvd = self.varinvdictionary
274-
usehigh = varinvd.var_invariant_fact(arg) if arg > 0 else None
275-
usehigh = cast(Optional[DefUseHigh], usehigh)
276-
self._defuseshigh.append(usehigh)
277-
elif c == "f":
278-
varinvd = self.varinvdictionary
279-
flagrdef = varinvd.var_invariant_fact(arg) if arg >= 0 else None
280-
flagrdef = cast(Optional[FlagReachingDefFact], flagrdef)
281-
self._flagreachingdefs.append(flagrdef)
282-
elif c == "c":
283-
self._ssavals.append(xd.variable(arg))
302+
303+
elif c == "x":
304+
if use_result:
305+
if arg == -2:
306+
self._xprs_r.append(None)
307+
else:
308+
self._xprs_r.append(xd.xpr(arg))
284309
else:
285-
raise UF.CHBError("Key letter not recognized: " + c)
310+
self._xprs.append(xd.xpr(arg))
311+
312+
elif c == "a":
313+
self._xprs.append(xd.xpr(arg))
314+
elif c == "s":
315+
self._strs.append(bd.string(arg))
316+
elif c == "i":
317+
self._intervals.append(xd.interval(arg))
318+
elif c == "l":
319+
self._ints.append(arg)
320+
elif c == "t":
321+
self._types.append(bcd.typ(arg))
322+
elif c == "r":
323+
varinvd = self.varinvdictionary
324+
rdef = varinvd.var_invariant_fact(arg) if arg >= 0 else None
325+
rdef = cast(Optional[ReachingDefFact], rdef)
326+
self._reachingdefs.append(rdef)
327+
elif c == "d":
328+
varinvd = self.varinvdictionary
329+
use = varinvd.var_invariant_fact(arg) if arg >= 0 else None
330+
use = cast(Optional[DefUse], use)
331+
self._defuses.append(use)
332+
elif c == "h":
333+
varinvd = self.varinvdictionary
334+
usehigh = varinvd.var_invariant_fact(arg) if arg > 0 else None
335+
usehigh = cast(Optional[DefUseHigh], usehigh)
336+
self._defuseshigh.append(usehigh)
337+
elif c == "f":
338+
varinvd = self.varinvdictionary
339+
flagrdef = varinvd.var_invariant_fact(arg) if arg >= 0 else None
340+
flagrdef = cast(Optional[FlagReachingDefFact], flagrdef)
341+
self._flagreachingdefs.append(flagrdef)
342+
elif c == "c":
343+
self._ssavals.append(xd.variable(arg))
344+
else:
345+
raise UF.CHBError("Key letter not recognized: " + c)
286346

287347
@property
288348
def is_function_argument(self) -> bool:

chb/arm/ARMInstruction.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ def to_string(
417417
pesp = str(self.stackpointer_offset) + " " if sp else ""
418418
popcode = (
419419
self.opcodetext.ljust(opcodewidth) if opcodetxt else "")
420+
print("DEBUG: " + pesp + pbytes + popcode + self.annotation)
420421
return pesp + pbytes + popcode + self.annotation
421422
except Exception as e:
422423
print(

chb/arm/opcodes/ARMAdd.py

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------------------------------------------------
55
# The MIT License (MIT)
66
#
7-
# Copyright (c) 2021-2024 Aarno Labs LLC
7+
# Copyright (c) 2021-2025 Aarno Labs LLC
88
#
99
# Permission is hereby granted, free of charge, to any person obtaining a copy
1010
# of this software and associated documentation files (the "Software"), to deal
@@ -44,8 +44,108 @@
4444

4545

4646
if TYPE_CHECKING:
47-
import chb.arm.ARMDictionary
48-
from chb.invariants.XXpr import XprCompound, XprConstant
47+
from chb.arm.ARMDictionary import ARMDictionary
48+
from chb.invariants.VarInvariantFact import ReachingDefFact
49+
from chb.invariants.XVariable import XVariable
50+
from chb.invariants.XXpr import XprCompound, XprConstant, XXpr
51+
52+
53+
class ARMAddXData:
54+
"""Add <rd> <rn> <rm> ==> result
55+
56+
xdata format: a:vxxxxxxrrdh
57+
-------------------------
58+
vars[0]: vrd (Rd)
59+
xprs[0]: xrn (Rn)
60+
xprs[1]: xrm (Rm)
61+
xprs[2]: result: xrn + xrm
62+
xprs[3]: rresult: xrn + xrm (rewritten)
63+
xprs[4]: xxrn (xrn rewritten)
64+
xprs[5]: xxrm (xrm rewritten)
65+
xprs[6]: tcond (optional)
66+
xprs[7]: fcond (optional)
67+
rdefs[0]: xrn
68+
rdefs[1]: xrm
69+
rdefs[2:..]: reaching definitions for simplified result expression
70+
uses[0]: vrd
71+
useshigh[0]: vrd
72+
"""
73+
74+
def __init__(self, xdata: InstrXData) -> None:
75+
self._xdata = xdata
76+
77+
@property
78+
def is_ok(self) -> bool:
79+
return self._xdata.is_ok
80+
81+
@property
82+
def vrd(self) -> "XVariable":
83+
v = self._xdata.vars_r[0]
84+
if v is None:
85+
raise UF.CHBError("ARMAddXData:vrd")
86+
return v
87+
88+
def xpr(self, index: int, msg: str) -> "XXpr":
89+
x = self._xdata.xprs_r[index]
90+
if x is None:
91+
raise UF.CHBError("ARMAddXData:" + msg)
92+
return x
93+
94+
@property
95+
def xrn(self) -> "XXpr":
96+
return self.xpr(0, "xrn")
97+
98+
@property
99+
def xrm(self) -> "XXpr":
100+
return self.xpr(1, "xrm")
101+
102+
@property
103+
def result(self) -> "XXpr":
104+
return self.xpr(2, "result")
105+
106+
@property
107+
def rresult(self) -> "XXpr":
108+
return self.xpr(3, "rresult")
109+
110+
@property
111+
def result_simplified(self) -> str:
112+
return simplify_result(
113+
self._xdata.args[3], self._xdata.args[4], self.result, self.rresult)
114+
115+
@property
116+
def xxrn(self) -> "XXpr":
117+
return self.xpr(4, "xxrn")
118+
119+
@property
120+
def xxrm(self) -> "XXpr":
121+
return self.xpr(5, "xxrm")
122+
123+
@property
124+
def tcond(self) -> "XXpr":
125+
return self.xpr(6, "tcond")
126+
127+
@property
128+
def fcond(self) -> "XXpr":
129+
return self.xpr(7, "fcond")
130+
131+
@property
132+
def rn_rdef(self) -> Optional["ReachingDefFact"]:
133+
return self._xdata.reachingdefs[0]
134+
135+
@property
136+
def rm_rdef(self) -> Optional["ReachingDefFact"]:
137+
return self._xdata.reachingdefs[1]
138+
139+
@property
140+
def annotation(self) -> str:
141+
assignment = str(self.vrd) + " := " + self.result_simplified
142+
if self._xdata.has_unknown_instruction_condition():
143+
return "if ? then " + assignment
144+
elif self._xdata.has_instruction_condition():
145+
c = str(self.tcond)
146+
return "if " + c + " then " + assignment
147+
else:
148+
return assignment
49149

50150

51151
@armregistry.register_tag("ADD", ARMOpcode)
@@ -69,26 +169,9 @@ class ARMAdd(ARMOpcode):
69169
args[3]: index of op3 in armdictionary
70170
args[4]: is-wide (thumb)
71171
72-
xdata format: a:vxxxxrrdh
73-
-------------------------
74-
vars[0]: lhs (Rd)
75-
xprs[0]: rhs1 (Rn)
76-
xprs[1]: rhs2 (Rm)
77-
xprs[2]: rhs1 + rhs2
78-
xprs[3]: rhs1 + rhs2 (simplified)
79-
xprs[4]: rhs1 (simplified)
80-
xprs[5]: rhs2 (simplified)
81-
rdefs[0]: rhs1
82-
rdefs[1]: rhs2
83-
rdefs[2:..]: reaching definitions for simplified result expression
84-
uses[0]: lhs
85-
useshigh[0]: lhs
86172
"""
87173

88-
def __init__(
89-
self,
90-
d: "chb.arm.ARMDictionary.ARMDictionary",
91-
ixval: IndexedTableValue) -> None:
174+
def __init__(self, d: "ARMDictionary", ixval: IndexedTableValue) -> None:
92175
ARMOpcode.__init__(self, d, ixval)
93176
self.check_key(2, 5, "Add")
94177

@@ -111,18 +194,11 @@ def mnemonic_extension(self) -> str:
111194
return wb + cc + wide
112195

113196
def annotation(self, xdata: InstrXData) -> str:
114-
lhs = str(xdata.vars[0])
115-
result = xdata.xprs[2]
116-
rresult = xdata.xprs[3]
117-
xresult = simplify_result(xdata.args[3], xdata.args[4], result, rresult)
118-
assignment = lhs + " := " + xresult
119-
if xdata.has_unknown_instruction_condition():
120-
return "if ? then " + assignment
121-
elif xdata.has_instruction_condition():
122-
c = str(xdata.xprs[1])
123-
return "if " + c + " then " + assignment
197+
xd = ARMAddXData(xdata)
198+
if xd.is_ok:
199+
return xd.annotation
124200
else:
125-
return assignment
201+
return "Error Value"
126202

127203
# --------------------------------------------------------------------------
128204
# AddWithCarry()

0 commit comments

Comments
 (0)