summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py75
1 files changed, 55 insertions, 20 deletions
diff --git a/pp2cc.py b/pp2cc.py
index 15d451a..5a079c8 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -155,16 +155,20 @@ class Parse(object):
self.addLabel(lbl_end)
linked_node.setFunction(function)
- lines = [self.asm.noop(lbl_func)]
+ # 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)
self.asm.level = linked_node.level
-
- # functions other than main() are subroutines
- #if funcname != "main":
- # since main should never be left, add the instruction anyway.
- # Otherwise, it'd crash anyway because it loops into the stack (if it
- # had not crashed before)
+
+ # restore stack pointer
+ lines.append(self.asm.binary_op("LOAD", "SP", self.registers.BP))
+ # restore Base Pointer
+ lines.append(self.asm.pull(self.registers.BP))
+ # return from function
lines.append(self.asm.format_line("RTS", label=lbl_end))
# add an extra newline
lines.append("")
@@ -580,8 +584,8 @@ class Parse(object):
def parseID(self, linked_node, register="R0"):
"""Returns the name for a name"""
# XXX this is not made for functions
- var_name = linked_node.variables.getName(linked_node.node.name)
- return [self.asm.binary_op("LOAD", register, "[GB+" + var_name + "]")]
+ addr = "+".join(linked_node.variables.getAddress(linked_node.node.name))
+ return [self.asm.binary_op("LOAD", register, "[" + addr + "]")]
def parseIf(self, linked_node):
linked_node.incrementLevel()
node = linked_node.node
@@ -836,9 +840,9 @@ class Parse(object):
lines.append(self.asm.binary_op("LOAD", register,
"[" + register + "]"))
elif linked_node.type == "ID":
- var_name = linked_node.variables.getName(linked_node.node.name)
- lines.append(self.asm.binary_op("LOAD", register, "GB"))
- lines.append(self.asm.binary_op("ADD", register, var_name))
+ var_reg, var_disp = linked_node.variables.getAddress(linked_node.node.name)
+ lines.append(self.asm.binary_op("LOAD", register, var_reg))
+ lines.append(self.asm.binary_op("ADD", register, var_disp))
else:
raise RuntimeError("Expected a lvalue (pointer or names)")
return lines
@@ -846,7 +850,7 @@ class Parse(object):
lines = []
size = 1
linked_type = LinkedNode(linked_node.node.type, linked_node)
- var_name = linked_node.variables.declName(linked_node.node.name, 1)
+ name = linked_node.node.name
if linked_type.type == "ArrayDecl":
if linked_type.node.dim is not None:
size = self.determineConstValue(LinkedNode(linked_type.node.dim,
@@ -865,15 +869,23 @@ class Parse(object):
# it's an error if the array dimension is unavailable, e.g.:
# int a[];
if size is None:
- raise RuntimeError("Array size missing in '{}'".format(var_name))
- var_array = linked_node.variables.declName(var_name, size,
- prefix="arr")
+ raise RuntimeError("Array size missing in '{}'".format(name))
elif linked_type.type == "PtrDecl":
# no check whether the pointer is valid or not
pass
elif linked_type.type == "TypeDecl":
if not linked_type.node.type.names[0] in ("int", "void"):
self.logger.warning("Only void and int types are supported", linked_node)
+ elif linked_type.type == "FuncDecl":
+ # a function declaration does not accept an initializaer, but it's
+ # still special because it has params
+ return self.parseStatement(linked_type.node, linked_node)
+ else:
+ raise RuntimeError("Unknown declaration type '{}'".format(linked_type.type))
+
+ linked_node.variables.declName(name, size)
+ # address of variable split up in register and displacement
+ var_reg, var_disp = linked_node.variables.getAddress(name)
# if the declaration also has a definition
if linked_node.node.init:
@@ -885,10 +897,15 @@ class Parse(object):
# contains the address of the first array element
reg_array = "R1"
# store the address of the first array element in the pointer
- init_vals.append(self.asm.binary_op("LOAD", reg_array, "GB"))
- init_vals.append(self.asm.binary_op("ADD", reg_array, var_array))
+ init_vals.append(self.asm.binary_op("LOAD", reg_array, var_reg))
+ init_vals.append(self.asm.binary_op("ADD", reg_array, var_arr))
+ # in this particular case, it happens that the array values are
+ # next to the pointer to the array
+ init_vals.append(self.asm.binary_op("ADD", reg_array, 1))
+ # store address of the first array element in the array pointer
init_vals.append(self.asm.binary_op("STOR", reg_array,
- "[GB+" + var_name + "]"))
+ "[" + var_reg + "+" +
+ var_disp + "]"))
array_index = 0
for array_elm in linked_init.node.exprs:
linked_arrelm = LinkedNode(array_elm, linked_init)
@@ -912,7 +929,8 @@ class Parse(object):
linked_node)
result_reg = self.registers.find_register(init_vals)
init_vals.append(self.asm.binary_op("STOR", result_reg,
- "[GB+" + var_name + "]"))
+ "[" + var_reg + "+" +
+ var_disp + "]"))
# if global context (i.e. not in a function)
if linked_node.getFunctionNode() is None:
@@ -1023,6 +1041,23 @@ class Parse(object):
"""
label_name = linked_node.lookupLabel(linked_node.node.name)
return [self.asm.branch_op("BRA", label_name)]
+ def parseFuncDecl(self, linked_node):
+ lines = []
+ node = linked_node.node
+ if node.args:
+ argstype = type(node.args).__name__
+ assert argstype == "ParamList", "Expected function arguments, found '{}' instead".format(argstype)
+ lines += self.parseStatement(node.args, linked_node)
+ return lines
+ def parseParamList(self, linked_node):
+ """Processes function parameters and returns assembly for modifying SP
+ """
+ lines = []
+ variables = linked_node.getFunctionNode().variables
+ params = linked_node.node.params
+ for param in params:
+ variables.declName(param.name, is_param=True)
+ return lines
def parseStatement(self, node, parent_linked_node, level_increment=False):
linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment)
self.asm.level = linked_node.level