diff options
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-x | pp2cc.py | 75 |
1 files changed, 55 insertions, 20 deletions
@@ -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 |