Skip to content

Commit a5efe97

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

File tree

6 files changed

+337
-40
lines changed

6 files changed

+337
-40
lines changed

chb/app/InstrXData.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,20 @@ def is_ok(self) -> bool:
260260
else:
261261
return True
262262

263+
@property
264+
def error_values(self) -> Tuple[List[int], List[int]]:
265+
266+
key = self.tags[0]
267+
if key.startswith("ar:"):
268+
vars_e: List[int] = [
269+
i for i in range(0, len(self.vars_r)) if self.vars_r[i] is None]
270+
xprs_e: List[int] = [
271+
i for i in range(0, len(self.xprs_r)) if self.xprs_r[i] is None]
272+
return (vars_e, xprs_e)
273+
else:
274+
return ([], [])
275+
276+
263277
def _expand(self) -> None:
264278
"""Expand the arguments based on the argument string in the keys.
265279
@@ -373,6 +387,11 @@ def is_bx_call(self) -> bool:
373387
return "bx-call" in self.tags
374388

375389
def call_target_argument_count(self) -> Optional[int]:
390+
if any(s.startswith("argcount:") for s in self.tags):
391+
tag = next(s for s in self.tags if s.startswith("argcount:"))
392+
argcount = int(tag[9:])
393+
return argcount
394+
376395
if len(self.tags) >= 3:
377396
if self.tags[1] == "call":
378397
try:
@@ -385,7 +404,6 @@ def call_target_argument_count(self) -> Optional[int]:
385404

386405
return None
387406

388-
389407
def has_inlined_call_target(self) -> bool:
390408
return len(self.tags) >= 3 and self.tags[2] == "inlined"
391409

chb/arm/ARMCallOpcode.py

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------------------------------------------------
55
# The MIT License (MIT)
66
#
7-
# Copyright (c) 2022-2024 Aarno Labs LLC
7+
# Copyright (c) 2022-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
@@ -54,12 +54,62 @@
5454

5555
if TYPE_CHECKING:
5656
from chb.api.CallTarget import CallTarget, AppTarget, StaticStubTarget
57+
from chb.api.InterfaceDictionary import InterfaceDictionary
5758
from chb.arm.ARMDictionary import ARMDictionary
5859
from chb.bctypes.BCTyp import BCTypFun
5960
from chb.invariants.VarInvariantFact import ReachingDefFact
6061
from chb.invariants.VAssemblyVariable import VRegisterVariable
6162
from chb.invariants.VConstantValueVariable import VFunctionReturnValue
62-
from chb.invariants.XXpr import XprConstant, XprVariable
63+
from chb.invariants.XVariable import XVariable
64+
from chb.invariants.XXpr import XXpr, XprConstant, XprVariable
65+
66+
67+
class ARMCallOpcodeXData:
68+
69+
def __init__(
70+
self,
71+
xdata: InstrXData,
72+
ixd: "InterfaceDictionary") -> None:
73+
self._xdata = xdata
74+
self._ixd = ixd
75+
76+
@property
77+
def is_ok(self) -> bool:
78+
return self._xdata.is_ok
79+
80+
@property
81+
def argument_count(self) -> int:
82+
argcount = self._xdata.call_target_argument_count()
83+
if argcount is None:
84+
chklogger.logger.error(
85+
"No argument count found for call")
86+
return 0
87+
return argcount
88+
89+
@property
90+
def arguments(self) -> List["XXpr"]:
91+
argcount = self.argument_count
92+
arguments: List["XXpr"] = []
93+
for i in range(argcount):
94+
x = self._xdata.xprs_r[i]
95+
if x is None:
96+
x = self._xdata.xprs_r[i + argcount]
97+
if x is None:
98+
raise UF.CHBError(
99+
"Unexpected None-value call argument at index "
100+
+ str(i))
101+
arguments.append(x)
102+
return arguments
103+
104+
@property
105+
def calltarget(self) -> "CallTarget":
106+
return self._xdata.call_target(self._ixd)
107+
108+
@property
109+
def annotation(self) -> str:
110+
tgt = str(self.calltarget)
111+
args = ", ".join(str(x) for x in self.arguments)
112+
return "call " + str(tgt) + "(" + args + ")"
63113

64114

65115
class ARMCallOpcode(ARMOpcode):
@@ -134,13 +184,8 @@ def is_call_instruction(self, xdata: InstrXData) -> bool:
134184
return xdata.has_call_target()
135185

136186
def annotation(self, xdata: InstrXData) -> str:
137-
if self.is_call(xdata) and xdata.has_call_target():
138-
tgt = xdata.call_target(self.ixd)
139-
args = ", ".join(str(x) for x in self.arguments(xdata))
140-
return "call " + str(tgt) + "(" + args + ")"
141-
142-
ctgt = str(xdata.xprs[0])
143-
return "call " + ctgt
187+
xd = ARMCallOpcodeXData(xdata, self.ixd)
188+
return xd.annotation
144189

145190
def call_target(self, xdata: InstrXData) -> "CallTarget":
146191
if self.is_call(xdata):

chb/arm/opcodes/ARMBranchLink.py

Lines changed: 1 addition & 1 deletion
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

chb/arm/opcodes/ARMCompare.py

Lines changed: 56 additions & 16 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
@@ -43,7 +43,56 @@
4343
from chb.util.IndexedTable import IndexedTableValue
4444

4545
if TYPE_CHECKING:
46-
import chb.arm.ARMDictionary
46+
from chb.arm.ARMDictionary import ARMDictionary
47+
from chb.invariants.XXpr import XXpr
48+
49+
50+
class ARMCompareXData:
51+
52+
def __init__(self, xdata: InstrXData) -> None:
53+
self._xdata = xdata
54+
55+
@property
56+
def is_ok(self) -> bool:
57+
return self._xdata.is_ok
58+
59+
def xpr(self, index: int, msg: str) -> "XXpr":
60+
x = self._xdata.xprs_r[index]
61+
if x is None:
62+
raise UF.CHBError("ARMCompareXData:" + msg)
63+
return x
64+
65+
@property
66+
def xrn(self) -> "XXpr":
67+
return self.xpr(0, "xrn")
68+
69+
@property
70+
def xrm(self) -> "XXpr":
71+
return self.xpr(1, "xrm")
72+
73+
@property
74+
def result(self) -> "XXpr":
75+
return self.xpr(2, "result")
76+
77+
@property
78+
def tcond(self) -> "XXpr":
79+
return self.xpr(3, "tcond")
80+
81+
@property
82+
def fcond(self) -> "XXpr":
83+
return self.xpr(4, "fcond")
84+
85+
@property
86+
def annotation(self) -> str:
87+
ann = "compare " + str(self.xrn) + " and " + str(self.xrm)
88+
ann += " (" + str(self.result) + ")"
89+
if self._xdata.has_unknown_instruction_condition():
90+
return "if ? then " + ann
91+
elif self._xdata.has_instruction_condition():
92+
c = str(self.tcond)
93+
return "if " + c + " then " + ann
94+
else:
95+
return ann
4796

4897

4998
@armregistry.register_tag("CMP", ARMOpcode)
@@ -72,10 +121,7 @@ class ARMCompare(ARMOpcode):
72121
rdefs[2..]: xrn - xrm (simplified)
73122
"""
74123

75-
def __init__(
76-
self,
77-
d: "chb.arm.ARMDictionary.ARMDictionary",
78-
ixval: IndexedTableValue) -> None:
124+
def __init__(self, d: "ARMDictionary", ixval: IndexedTableValue) -> None:
79125
ARMOpcode.__init__(self, d, ixval)
80126
self.check_key(2, 3, "Compare")
81127

@@ -93,17 +139,11 @@ def opargs(self) -> List[ARMOperand]:
93139
return [self.armd.arm_operand(i) for i in self.args[:-1]]
94140

95141
def annotation(self, xdata: InstrXData) -> str:
96-
rhs1 = str(xdata.xprs[0])
97-
rhs2 = str(xdata.xprs[1])
98-
result = str(xdata.xprs[2])
99-
ann = "compare " + str(rhs1) + " and " + str(rhs2) + " (" + result + ")"
100-
if xdata.has_unknown_instruction_condition():
101-
return "if ? then " + ann
102-
elif xdata.has_instruction_condition():
103-
c = str(xdata.xprs[1])
104-
return "if " + c + " then " + ann
142+
xd = ARMCompareXData(xdata)
143+
if xd.is_ok:
144+
return xd.annotation
105145
else:
106-
return ann
146+
return "Error value"
107147

108148
def ast_prov(
109149
self,

0 commit comments

Comments
 (0)