From a62cbd3e76c0e937b224158a206fe343a9c4d2eb Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 30 Nov 2011 09:56:50 +0000 Subject: Support for array declaration and initialization --- pp2cc.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 12 deletions(-) (limited to 'pp2cc.py') diff --git a/pp2cc.py b/pp2cc.py index 39e3d31..dc99a71 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -35,7 +35,8 @@ class Registers(object): for reg in range(0, 8): self.registers[str(reg)] = False def alloc(self, register=None): - """Retrieves a register which is marked unused and marks it as in use""" + """Retrieves a register which is marked unused, marks it as in use and + return it""" # if a register was explicitly requested if register: if not self.is_register(register): @@ -232,7 +233,7 @@ class Variables(object): if self.parent_variables: return self.parent_variables.getName(name) raise RuntimeError("Use of undefined variable '{}'".format(name)) - def declName(self, name): + def declName(self, name, size=1): """Declares a variable in the nearest scope and returns the label name""" if name in self.local_vars: @@ -241,7 +242,7 @@ class Variables(object): var_name = ("varl_" if self.parent_variables else "var_") + name var_name = self.uniqName(var_name) self.local_vars[name] = var_name - self.defined_names.append(var_name) + self.defined_names[var_name] = size return var_name class LinkedNode(object): @@ -423,7 +424,7 @@ class Parse(object): self.binary_ops.update(self.comparison_ops) # local and global variable names to be defined in @DATA - self.varNames = [] + self.varNames = {} self.functions = {} # holds instructions for initializing the global variables self.globalInit = [] @@ -473,9 +474,9 @@ class Parse(object): """Retrieves the ASM source. You need to compile it first""" output = [] output.append("@DATA") - for varName in self.varNames: + for varName, size in self.varNames.iteritems(): padding = " " * (16 - len(varName) - 1) - output.append(varName + padding + " DS 1") + output.append(varName + padding + " DS " + str(size)) output.append("") output.append("@CODE") # initialization of global variables @@ -1143,18 +1144,51 @@ class Parse(object): return lines def parseDecl(self, linked_node): lines = [] - var_name = linked_node.variables.declName(linked_node.node.name) + size = 1 + linked_type = LinkedNode(linked_node.node.type, linked_node) + if linked_type.type == "ArrayDecl": + size = self.determineConstValue(LinkedNode(linked_type.node.dim, linked_node)) + 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) + var_name = linked_node.variables.declName(linked_node.node.name, size) # if the declaration also has a definition if linked_node.node.init: - init_val = self.parseExpression(linked_node.node.init, linked_node) - result_reg = self.registers.find_register(init_val) - init_val.append(self.asm.binary_op("STOR", result_reg, "[GB+" + var_name + "]")) + init_vals = [] + node_init = linked_node.node.init + if (linked_type.type == "ArrayDecl" and + isinstance(node_init, c_ast.ExprList)): + array_index = 0 + for array_elm in node_init.exprs: + init_val = self.parseExpression(array_elm, linked_node) + result_reg = self.registers.find_register(init_val, fatal=True) + # find a free register for storing the address of variable. + # We could modify the GB register as well, but that does + # not decrease the instructions count and is not safe with + # interrupts + self.registers.alloc(result_reg) + var_reg = self.registers.alloc() + self.registers.free(var_reg) + self.registers.free(result_reg) + + init_val.append(self.asm.binary_op("LOAD", var_reg, var_name)) + if array_index: + init_val.append(self.asm.binary_op("ADD", var_reg, array_index)) + init_val.append(self.asm.binary_op("STOR", result_reg, "[GB+" + var_reg + "]")) + init_vals += init_val + else: + init_vals = self.parseExpression(linked_node.node.init, linked_node) + result_reg = self.registers.find_register(init_vals) + init_vals.append(self.asm.binary_op("STOR", result_reg, "[GB+" + var_name + "]")) # if global context (i.e. not in a function) if linked_node.getFunctionNode() is None: - self.globalInit += init_val + self.globalInit += init_vals else: - lines += init_val + lines += init_vals return lines def parseBreak(self, linked_node): loop_node = linked_node.getBreakNode() -- cgit v1.2.1