summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-29 16:02:47 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-29 16:02:47 +0000
commit5c3345d0db35049d85259f0d2faffa089cf9e38e (patch)
tree6a05a815955dd91c498a81aa2f41b19725a8bf70 /pp2cc.py
parent27a1317e8bc90cf45207cb8810ff56e12a6a0673 (diff)
downloadpp2cc-5c3345d0db35049d85259f0d2faffa089cf9e38e.tar.gz
Fix support for pre inc/dec operator, WIP for post inc/dec
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py97
1 files changed, 76 insertions, 21 deletions
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