summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py57
1 files changed, 48 insertions, 9 deletions
diff --git a/pp2cc.py b/pp2cc.py
index 0ae2803..c50bff2 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -16,6 +16,7 @@ from Asm import Asm
from Registers import Registers
from LinkedNode import LinkedNode
from Function import Function
+from Variables import Variables, GlobalVariables
__author__ = "Peter Wu"
__copyright__ = "Copyright 2011, Peter Wu"
@@ -115,7 +116,9 @@ class Parse(object):
self.labels.add(labelname)
def compile(self):
"""Loops through the nodes in an AST syntax tree and generates ASM"""
- root_node = LinkedNode(self.node, defined_names=self.varNames)
+ root_node = LinkedNode(self.node)
+ variables = GlobalVariables(self.varNames)
+ root_node.setVariablesObj(variables)
for thing in self.node.ext:
if not isinstance(thing, c_ast.Decl) and not isinstance(thing, c_ast.FuncDef):
linked_node = LinkedNode(thing, parent=root_node)
@@ -161,22 +164,30 @@ class Parse(object):
self.addLabel(lbl_func)
self.addLabel(lbl_end)
linked_node.setFunction(function)
-
# save Base Pointer
lines = [self.asm.push(self.registers.BP, lbl_func)]
lines.append(self.asm.binary_op("LOAD", self.registers.BP, "SP"))
# parse function declaration (which will parse params as well)
lines += self.parseStatement(node.decl, linked_node)
- lines += self.parseStatement(node.body, linked_node)
+ body = self.parseStatement(node.body, linked_node)
self.asm.level = linked_node.level
- # restore stack pointer
- lines.append(self.asm.binary_op("LOAD", "SP", self.registers.BP))
+ # Reserve space on the stack for local variables if necessary
+ if function.reserved_stack:
+ lines.append(self.asm.binary_op("SUB", "SP", function.reserved_stack))
+ lines += body
+ # restore SP
+ lines.append(self.asm.binary_op("LOAD", "SP", self.registers.BP,
+ label=lbl_end))
+ else:
+ lines += body
+ lines.append(self.asm.noop(lbl_end))
+
# restore Base Pointer
lines.append(self.asm.pull(self.registers.BP))
# return from function
- lines.append(self.asm.format_line("RTS", label=lbl_end))
+ lines.append(self.asm.format_line("RTS"))
# add an extra newline
lines.append("")
return lines
@@ -677,10 +688,27 @@ class Parse(object):
#lines.append(self.asm.format_line("RTS"))
return lines
def parseFuncCall(self, linked_node):
- # XXX function arguments
+ lines = []
# node.name is a c_ast.ID, the real function name is in name
funcname = linked_node.node.name.name
- return [self.asm.branch_op("BRS", self.functionLabel(funcname))]
+ params = linked_node.node.args
+ if params:
+ linked_params = LinkedNode(params, linked_node)
+ # call convention: params in reverse order
+ for expr in reversed(params.exprs):
+ line = self.parseExpression(expr, linked_params)
+ result_reg = self.registers.find_register(line, fatal=True)
+ lines += line
+ lines.append(self.asm.push(result_reg))
+
+ lines.append(self.asm.branch_op("BRS", self.functionLabel(funcname)))
+
+ if params:
+ lines.append(self.asm.binary_op("ADD", "SP", len(params.exprs)))
+ # by convention, a function call must return the result in R0, we
+ # also make sure that the PSW flags are set properly
+ lines.append(self.asm.binary_op("LOAD", "R0", "R0"))
+ return lines
def parseCast(self, linked_node):
self.logger.warning("Found a type cast, but these are unsupported.", linked_node=linked_node)
return self.parseExpression(linked_node.node.expr, linked_node)
@@ -765,6 +793,9 @@ class Parse(object):
lines.append(self.asm.noop(lbl_for_end))
return lines
def parseExprList(self, linked_node):
+ """Parse an expression list. This method should not be used when
+ parsing a list declaration (done by parseDecl) nor function params
+ """
lines = []
for expr in linked_node.node.exprs:
lines += self.parseExpression(expr, linked_node)
@@ -1062,7 +1093,9 @@ class Parse(object):
def parseLabel(self, linked_node):
lines = []
try:
- label_name = linked_node.setLabel(linked_node.node.name)
+ name = linked_node.node.name
+ label_name = self.uniqLbl(name)
+ linked_node.setLabel(name, label_name)
except RuntimeError as errmsg:
self.logger.error(errmsg, linked_node=linked_node)
lines.append(self.asm.noop(label_name))
@@ -1099,9 +1132,13 @@ class Parse(object):
return lines
def parseStatement(self, node, parent_linked_node, level_increment=False):
linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment)
+ if linked_node.needNewScope():
+ linked_node.setVariablesObj(Variables(linked_node.parent.variables))
self.asm.level = linked_node.level
lines = []
if linked_node.isTypeStatement():
+ lines.append(self.asm.format_line("; " + linked_node.type + " " +
+ linked_node.getLocation()))
if hasattr(self, "parse" + linked_node.type):
lines += getattr(self, "parse" + linked_node.type)(linked_node)
# add for support post increment and decrement
@@ -1120,6 +1157,8 @@ class Parse(object):
self.asm.level = linked_node.level
lines = []
+ lines.append(self.asm.format_line("; " + linked_node.type + " " +
+ linked_node.getLocation()))
if linked_node.type in ("ID", "Constant", "UnaryOp", "FuncCall", "Cast",
"BinaryOp", "TernaryOp", "Assignment", "ExprList", "ArrayRef"):
lines += getattr(self, "parse" + linked_node.type)(linked_node)