oppc: decouple attribute name
[openpower-isa.git] / src / openpower / oppc / pc_code.py
index f351f5b825678fc4632807e01c13ad0abdf19cff..d7cdeef5ee8fcbc9ee7844215f517f35531f35c9 100644 (file)
@@ -7,17 +7,17 @@ import openpower.oppc.pc_pseudocode as pc_pseudocode
 
 
 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
@@ -40,7 +40,7 @@ class CodeVisitor(pc_util.Visitor):
         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):
@@ -51,13 +51,14 @@ class CodeVisitor(pc_util.Visitor):
     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
@@ -70,10 +71,26 @@ class CodeVisitor(pc_util.Visitor):
             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):
@@ -97,36 +114,30 @@ class CodeVisitor(pc_util.Visitor):
         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):
@@ -140,30 +151,40 @@ class CodeVisitor(pc_util.Visitor):
             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,
@@ -171,8 +192,10 @@ class CodeVisitor(pc_util.Visitor):
             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
@@ -186,6 +209,8 @@ class CodeVisitor(pc_util.Visitor):
             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",
@@ -194,6 +219,7 @@ class CodeVisitor(pc_util.Visitor):
             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)
 
@@ -209,22 +235,23 @@ class CodeVisitor(pc_util.Visitor):
             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 "")
@@ -251,53 +278,61 @@ class CodeVisitor(pc_util.Visitor):
     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)
@@ -366,9 +401,12 @@ class CodeVisitor(pc_util.Visitor):
     @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]:
@@ -379,6 +417,56 @@ class CodeVisitor(pc_util.Visitor):
                 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
@@ -395,15 +483,17 @@ class CodeVisitor(pc_util.Visitor):
     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):