class Transient(pc_ast.Node):
- def __init__(self, value="UINT64_C(0)", bits="(uint8_t)ctx->XLEN"):
+ def __init__(self, value="UINT64_C(0)", bits="(uint8_t)OPPC_XLEN"):
self.__value = value
self.__bits = bits
return super().__init__()
def __str__(self):
- return f"oppc_transient(&(struct oppc_int){{}}, {self.__value}, {self.__bits})"
+ return f"oppc_transient(&(struct oppc_value){{}}, {self.__value}, {self.__bits})"
-class CCall(pc_ast.Dataclass):
+class Call(pc_ast.Dataclass):
name: str
code: tuple
stmt: bool
self.__code[self.__header].emit(stmt=f"oppc_{name}(void) {{")
with self.__code[self.__header]:
for decl in self.__decls:
- self.__code[self.__header].emit(stmt=f"struct oppc_int {decl};")
+ self.__code[self.__header].emit(stmt=f"struct oppc_value {decl};")
self.__code[self.__footer].emit(stmt=f"}}")
def __iter__(self):
def __getitem__(self, node):
return self.__code[node]
- def transient(self, node, value="UINT64_C(0)", bits="(uint8_t)ctx->XLEN"):
+ def transient(self, node,
+ value="UINT64_C(0)",
+ bits="(uint8_t)OPPC_XLEN"):
transient = Transient(value=value, bits=bits)
- with self.pseudocode(node=node):
- self.traverse(root=transient)
+ self.traverse(root=transient)
return transient
- def ccall(self, node, name, code, stmt=False):
+ def call(self, node, name, code, stmt=False):
def validate(item):
def validate(item):
(level, stmt) = item
return tuple(map(validate, item))
code = tuple(map(validate, code))
- ccall = CCall(name=name, code=code, stmt=stmt)
- with self.pseudocode(node=node):
- self.traverse(root=ccall)
- return ccall
+ call = Call(name=name, code=code, stmt=stmt)
+ self.traverse(root=call)
+ return call
+
+ def ternary(self, node):
+ self[node].clear()
+ test = self.call(name="oppc_bool", node=node, code=[
+ self[node.test],
+ ])
+ self[node].emit(stmt="(")
+ with self[node]:
+ for (level, stmt) in self[test]:
+ self[node].emit(stmt=stmt, level=level)
+ self[node].emit(stmt="?")
+ for (level, stmt) in self[node.body]:
+ self[node].emit(stmt=stmt, level=level)
+ self[node].emit(stmt=":")
+ for (level, stmt) in self[node.orelse]:
+ self[node].emit(stmt=stmt, level=level)
+ self[node].emit(stmt=")")
@contextlib.contextmanager
def pseudocode(self, node):
if isinstance(node.rvalue, (pc_ast.GPR, pc_ast.FPR)):
self.__regfetch[str(node.rvalue)].append(node.rvalue)
- rvalue = self[node.rvalue]
if isinstance(node.rvalue, pc_ast.IfExpr):
- rvalue = [(0, " ".join([
- str(self[node.rvalue.test]),
- "?",
- str(self[node.rvalue.body[0]]),
- ":",
- str(self[node.rvalue.orelse[0]]),
- ]))]
+ self.ternary(node=node.rvalue)
if isinstance(node.lvalue, pc_ast.SubscriptExpr):
- ccall = self.ccall(name="oppc_subscript_assign", node=node, stmt=True, code=[
+ call = self.call(name="oppc_subscript_assign", node=node, stmt=True, code=[
self[node.lvalue.subject],
self[node.lvalue.index],
- rvalue,
+ self[node.rvalue],
])
elif isinstance(node.lvalue, pc_ast.RangeSubscriptExpr):
- ccall = self.ccall(name="oppc_range_subscript_assign", node=node, stmt=True, code=[
+ call = self.call(name="oppc_range_subscript_assign", node=node, stmt=True, code=[
self[node.lvalue.subject],
self[node.lvalue.start],
self[node.lvalue.end],
- rvalue,
+ self[node.rvalue],
])
else:
- ccall = self.ccall(name="oppc_assign", stmt=True, node=node, code=[
+ call = self.call(name="oppc_assign", stmt=True, node=node, code=[
self[node.lvalue],
- rvalue,
+ self[node.rvalue],
])
- for (level, stmt) in self[ccall]:
- self[node].emit(stmt=stmt, level=level)
+ with self.pseudocode(node=node):
+ for (level, stmt) in self[call]:
+ self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.BinaryExpr)
def BinaryExpr(self, node):
pc_ast.Lt, pc_ast.Le,
pc_ast.Eq, pc_ast.NotEq,
pc_ast.Ge, pc_ast.Gt,
+ pc_ast.LtU, pc_ast.GtU,
)
+ if isinstance(node.left, pc_ast.IfExpr):
+ self.ternary(node=node.left)
+ if isinstance(node.right, pc_ast.IfExpr):
+ self.ternary(node=node.right)
+
if isinstance(node.op, comparison):
- ccall = self.ccall(name=str(self[node.op]), node=node, code=[
+ call = self.call(name=str(self[node.op]), node=node, code=[
self[node.left],
self[node.right],
])
else:
transient = self.transient(node=node)
- ccall = self.ccall(name=str(self[node.op]), node=node, code=[
+ call = self.call(name=str(self[node.op]), node=node, code=[
self[transient],
self[node.left],
self[node.right],
])
- for (level, stmt) in self[ccall]:
- self[node].emit(stmt=stmt, level=level)
+ with self.pseudocode(node=node):
+ for (level, stmt) in self[call]:
+ self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.UnaryExpr)
def UnaryExpr(self, node):
yield node
- ccall = self.ccall(name=str(self[node.op]), node=node, code=[
+ if isinstance(node.value, pc_ast.IfExpr):
+ self.ternary(node=node.value)
+ call = self.call(name=str(self[node.op]), node=node, code=[
self[node.value],
])
- for (level, stmt) in self[ccall]:
- self[node].emit(stmt=stmt, level=level)
+ with self.pseudocode(node=node):
+ for (level, stmt) in self[call]:
+ self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(
pc_ast.Not, pc_ast.Add, pc_ast.Sub,
pc_ast.Lt, pc_ast.Le,
pc_ast.Eq, pc_ast.NotEq,
pc_ast.Ge, pc_ast.Gt,
+ pc_ast.LtU, pc_ast.GtU,
pc_ast.LShift, pc_ast.RShift,
pc_ast.BitAnd, pc_ast.BitOr, pc_ast.BitXor,
+ pc_ast.BitConcat,
)
def Op(self, node):
yield node
pc_ast.Lt: "oppc_lt",
pc_ast.Le: "oppc_le",
pc_ast.Eq: "oppc_eq",
+ pc_ast.LtU: "oppc_ltu",
+ pc_ast.GtU: "oppc_gtu",
pc_ast.NotEq: "oppc_noteq",
pc_ast.Ge: "oppc_ge",
pc_ast.Gt: "oppc_gt",
pc_ast.BitAnd: "oppc_and",
pc_ast.BitOr: "oppc_or",
pc_ast.BitXor: "oppc_xor",
+ pc_ast.BitConcat: "oppc_concat",
}[node.__class__]
self[node].emit(stmt=op)
bits = f"UINT8_C({str(len(value[2:]) * 4)})"
value = int(value, 16)
else:
- bits = "ctx->XLEN"
+ bits = "(uint8_t)OPPC_XLEN"
value = int(value)
fmt = str
if (value > ((2**64) - 1)):
raise NotImplementedError()
value = f"UINT64_C({fmt(value)})"
transient = self.transient(node=node, value=value, bits=bits)
- for (level, stmt) in self[transient]:
- self[node].emit(stmt=stmt, level=level)
+ with self.pseudocode(node=node):
+ for (level, stmt) in self[transient]:
+ self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(Transient)
def Transient(self, node):
yield node
self[node].emit(stmt=str(node))
- @pc_util.Hook(CCall)
+ @pc_util.Hook(Call)
def CCall(self, node):
yield node
end = (";" if node.stmt else "")
def GPR(self, node):
yield node
with self.pseudocode(node=node):
- self[node].emit(stmt=f"&ctx->gpr[OPPC_GPR_{str(node)}]")
+ self[node].emit(stmt=f"&OPPC_GPR[OPPC_GPR_{str(node)}]")
@pc_util.Hook(pc_ast.FPR)
def FPR(self, node):
yield node
with self.pseudocode(node=node):
- self[node].emit(stmt=f"&ctx->fpr[OPPC_FPR_{str(node)}]")
+ self[node].emit(stmt=f"&OPPC_FPR[OPPC_FPR_{str(node)}]")
@pc_util.Hook(pc_ast.RepeatExpr)
def RepeatExpr(self, node):
yield node
transient = self.transient(node=node)
- ccall = self.ccall(name="oppc_repeat", node=node, code=[
+ call = self.call(name="oppc_repeat", node=node, code=[
self[transient],
self[node.subject],
self[node.times],
])
- for (level, stmt) in self[ccall]:
+ for (level, stmt) in self[call]:
self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.XLEN)
def XLEN(self, node):
yield node
- (value, bits) = ("ctx->XLEN", "(uint8_t)ctx->XLEN")
+ (value, bits) = ("OPPC_XLEN", "(uint8_t)OPPC_XLEN")
transient = self.transient(node=node, value=value, bits=bits)
- for (level, stmt) in self[transient]:
- self[node].emit(stmt=stmt, level=level)
+ with self.pseudocode(node=node):
+ for (level, stmt) in self[transient]:
+ self[node].emit(stmt=stmt, level=level)
+
+ @pc_util.Hook(pc_ast.Overflow, pc_ast.CR3, pc_ast.CR5,
+ pc_ast.XER, pc_ast.Reserve, pc_ast.Special)
+ def Special(self, node):
+ yield node
+ with self.pseudocode(node=node):
+ self[node].emit(stmt=f"&OPPC_{str(node).upper()}")
@pc_util.Hook(pc_ast.SubscriptExpr)
def SubscriptExpr(self, node):
yield node
- ccall = self.ccall(name="oppc_subscript", node=node, code=[
+ call = self.call(name="oppc_subscript", node=node, code=[
self[node.subject],
self[node.index],
])
- for (level, stmt) in self[ccall]:
+ for (level, stmt) in self[call]:
self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.RangeSubscriptExpr)
def RangeSubscriptExpr(self, node):
yield node
- ccall = self.ccall(name="oppc_subscript", node=node, code=[
+ call = self.call(name="oppc_subscript", node=node, code=[
self[node.subject],
self[node.start],
self[node.end],
])
- for (level, stmt) in self[ccall]:
+ for (level, stmt) in self[call]:
self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.ForExpr)
@pc_util.Hook(pc_ast.IfExpr)
def IfExpr(self, node):
yield node
+ test = self.call(name="oppc_bool", node=node, code=[
+ self[node.test],
+ ])
self[node].emit(stmt="if (")
with self[node]:
- for (level, stmt) in self[node.test]:
+ for (level, stmt) in self[test]:
self[node].emit(stmt=stmt, level=level)
self[node].emit(stmt=") {")
for (level, stmt) in self[node.body]:
self[node].emit(stmt=stmt, level=level)
self[node].emit(stmt="}")
+ @pc_util.Hook(pc_ast.SwitchExpr)
+ def SwitchExpr(self, node):
+ yield node
+ subject = self.call(name="oppc_int64", node=node, code=[
+ self[node.subject],
+ ])
+ self[node].emit(stmt="switch (")
+ with self[node]:
+ for (level, stmt) in self[subject]:
+ self[node].emit(stmt=stmt, level=level)
+ self[node].emit(") {")
+ with self[node]:
+ for (level, stmt) in self[node.cases]:
+ self[node].emit(stmt=stmt, level=level)
+
+ @pc_util.Hook(pc_ast.Cases)
+ def Cases(self, node):
+ yield node
+ for subnode in node:
+ for (level, stmt) in self[subnode]:
+ self[node].emit(stmt=stmt, level=level)
+
+ @pc_util.Hook(pc_ast.Case)
+ def Case(self, node):
+ yield node
+ for (level, stmt) in self[node.labels]:
+ self[node].emit(stmt=stmt, level=level)
+ for (level, stmt) in self[node.body]:
+ self[node].emit(stmt=stmt, level=level)
+
+ @pc_util.Hook(pc_ast.Labels)
+ def Labels(self, node):
+ yield node
+ if ((len(node) == 1) and isinstance(node[-1], pc_ast.DefaultLabel)):
+ stmt = "default:"
+ else:
+ labels = ", ".join(map(lambda label: str(self[label]), node))
+ stmt = f"case ({labels}):"
+ self[node].emit(stmt=stmt)
+
+ @pc_util.Hook(pc_ast.Label)
+ def Label(self, node):
+ yield node
+ self[node].emit(stmt=str(node))
+
+ @pc_util.Hook(pc_ast.LeaveKeyword)
+ def LeaveKeyword(self, node):
+ yield node
+ self[node].emit(stmt="break;")
+
@pc_util.Hook(pc_ast.Call.Name)
def CallName(self, node):
yield node
def Call(self, node):
yield node
code = tuple(map(lambda arg: self[arg], node.args))
- ccall = self.ccall(name=str(node.name), node=node, code=code)
- for (level, stmt) in self[ccall]:
+ call = self.call(name=str(node.name), node=node, code=code)
+ for (level, stmt) in self[call]:
self[node].emit(stmt=stmt, level=level)
@pc_util.Hook(pc_ast.Symbol)
def Symbol(self, node):
yield node
- self.__decls[str(node)].append(node)
- self[node].emit(stmt=f"&{str(node)}")
+ with self.pseudocode(node=node):
+ if str(node) not in ("fallthrough",):
+ self.__decls[str(node)].append(node)
+ self[node].emit(stmt=f"&{str(node)}")
@pc_util.Hook(pc_ast.Node)
def Node(self, node):