From 6aaff7ae54dbe34ea6bf3f9ee8c93e9d79db3c22 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Thu, 1 Dec 2011 22:18:27 +0000 Subject: Fix stack corruption, support func calls with arguments and automatic variables --- pp2cc.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'pp2cc.py') 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) -- cgit v1.2.1