summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-30 09:56:50 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-30 09:56:50 +0000
commita62cbd3e76c0e937b224158a206fe343a9c4d2eb (patch)
tree67f6b6349ccc743e74660f52950004665181e3a8 /pp2cc.py
parent8f0749764335c2196933ce0847f1551bf4a556b9 (diff)
downloadpp2cc-a62cbd3e76c0e937b224158a206fe343a9c4d2eb.tar.gz
Support for array declaration and initialization
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py58
1 files changed, 46 insertions, 12 deletions
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()