From 5c3345d0db35049d85259f0d2faffa089cf9e38e Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Tue, 29 Nov 2011 16:02:47 +0000 Subject: Fix support for pre inc/dec operator, WIP for post inc/dec --- pp2cc.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 21 deletions(-) (limited to 'pp2cc.py') diff --git a/pp2cc.py b/pp2cc.py index bea3a21..7683af2 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -231,6 +231,8 @@ class LinkedNode(object): self.type = type(node).__name__ self.level = 0 self.variables = None + # for supporting post increment and post decrement + self.post_lines = [] parent_variables = None # inherit level and variables from parent if parent: @@ -249,6 +251,10 @@ class LinkedNode(object): raise RuntimeError("No variables object found") if level_increment: self.incrementLevel() + def handle_post_lines(self, lines): + """Add post-increment lines to the lines list and clear the queue""" + lines += self.post_lines + self.post_lines = [] def getScopeNode(self): """Get the nearest node which introduces a new scope. @@ -259,9 +265,30 @@ class LinkedNode(object): if self.parent: return self.parent.getScopeNode() raise RuntimeError("No global variable scope was found") + def isTypeStatement(self): + """Returns True if the node is a statement type""" + return self.type in ("Compound", "If", "Return", "DoWhile", "While", + "For", "Decl", "FuncDef", "Break", "Continue", + "EmptyStatement", "Switch", "DeclList", + "FuncDecl", "ArrayDecl", "Case", + "Default", "EllipsisParam",# (int a, ...) + "Enum", # enum type + "Enumerator", # enum value + "EnumeratorList", # list of enum values + "FuncDecl", "Goto", "Label", "ParamList", "PtrDecl", "Struct", + "TypeDecl", "Typedef", "Union") + def getStatementNode(self): + """Returns the nearest LinkedNode which is a statement node type""" + if self.isTypeStatement(): + return self + if self.parent: + return self.parent.getStatementNode() + return None def incrementLevel(self): self.level += 1 def getFunctionNode(self): + """Returns the nearest LinkedNode which is a function definition node + type""" if self.type == "FuncDef": return self if self.parent: @@ -664,6 +691,40 @@ class Parse(object): else: lines.append(self.asm.binary_op(op, reg_first, operand)) return lines + def parseUnaryOpLValue(self, linked_node): + lines = [] + binops = { + "++": "ADD", + "--": "SUB" + } + op = linked_node.node.op + if op == "*": + lines = self.parseLValue(linked_node) + elif op in ("p++", "p--"): + # XXX support postinc/dec + raise RuntimeError("Post increment and post decrement operators" + " are not supported.") + binop = binops[op[1:]] + stmt = linked_node.getStatementNode() + if not stmt: + raise RuntimeError("No statement found for post inc/decrement") + # assume that the result register is R0 + lvalue = self.parseLValue(LinkedNode(linked_node.node.expr, linked_node)) + lines = lvalue; + stmt.post_lines += lvalue + stmt.post_lines.append(self.asm.binary_op("LOAD", "R1", "[R0]")) + stmt.post_lines.append(self.asm.binary_op(binop, "R1", 1)) + stmt.post_lines.append(self.asm.binary_op("STOR", "R1", "[R0]")) + elif op in ("--", "++"): + binop = binops[op] + lvalue = self.parseLValue(LinkedNode(linked_node.node.expr, linked_node)) + lines = lvalue; + lines.append(self.asm.binary_op("LOAD", "R1", "[R0]")) + lines.append(self.asm.binary_op(binop, "R1", 1)) + lines.append(self.asm.binary_op("STOR", "R1", "[R0]")) + else: + raise RuntimeError("Unknown lvalue unary operator '{}'".format(op)) + return lines def parseUnaryOp(self, linked_node): """Returns lines of assembly for unary operators @@ -679,6 +740,9 @@ class Parse(object): end:NOOP """ op = linked_node.node.op + # some operators works on lvalues + if op in ("*", "--", "++", "p++", "p--"): + return self.parseUnaryOpLValue(linked_node) # first fetch the operand lines = self.parseExpression(linked_node.node.expr, linked_node) # determine the register in which the result is stored @@ -704,19 +768,10 @@ class Parse(object): lines.append(self.asm.branch_op("BRA", lbl_end)) lines.append(self.asm.binary_op("LOAD", reg, 0, label=lbl_false)) lines.append(self.asm.noop(lbl_end, register=reg)) - elif op == "--": - lines.append(self.asm.binary_op("SUB", reg, 1)) - elif op == "++": - lines.append(self.asm.binary_op("ADD", reg, 1)) elif op == "&": raise RuntimeError("Address operator '&' is not supported.") - elif op == "*": - lines.append(self.asm.binary_op("LOAD", reg, "[" + reg + "]")) elif op == "sizeof": raise RuntimeError("Sizeof operator 'sizeof' is not supported.") - elif op == "p++" or op == "p--": - # XXX postfix/prefix - raise RuntimeError("Post-inc or post-dec is not supported (yet?).") else: raise RuntimeError("Unknown unary operator '{}'".format(op)) return lines @@ -1005,6 +1060,11 @@ class Parse(object): raise RuntimeError("Unsupported assignment operator: " + node.op) return lines def parseLValue(self, linked_node, register="R0"): + """Returns lines of ASM for a lvalue type. + + It's assumed that register does not change to another one. If this is + changed in the future, please revisit all uses of it. + """ lines = [] if linked_node.type == "UnaryOp" and linked_node.node.op == "*": lines += self.parseLValue(LinkedNode(linked_node.node.expr, @@ -1101,18 +1161,13 @@ class Parse(object): linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment) self.asm.level = linked_node.level lines = [] - if linked_node.type in ("Compound", "If", "Return", "DoWhile", "While", - "For", "Decl", "FuncDef", "Break", "Continue", - "EmptyStatement", "Switch", "DeclList"): - lines += getattr(self, "parse" + linked_node.type)(linked_node) - elif linked_node.type in ("FuncDecl", "ArrayDecl", "Case", - "Default", "EllipsisParam",# (int a, ...) - "Enum", # enum type - "Enumerator", # enum value - "EnumeratorList", # list of enum values - "FuncDecl", "Goto", "Label", "ParamList", "PtrDecl", "Struct", - "TypeDecl", "Typedef", "Union"): - raise RuntimeError("Not implemented for type " + repr(node)) + if linked_node.isTypeStatement(): + if hasattr(self, "parse" + linked_node.type): + lines += getattr(self, "parse" + linked_node.type)(linked_node) + # add for support post increment and decrement + lines += linked_node.post_lines + else: + raise RuntimeError("Not implemented for type " + repr(node)) else: lines += self.parseExpression(node, parent_linked_node, level_increment) return lines -- cgit v1.2.1