summaryrefslogtreecommitdiff
path: root/Variables.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-12-01 18:28:36 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-12-01 18:28:36 +0000
commit20416d5ae946d4defbfea66c53e58761cf885b73 (patch)
tree2ade535a438652f14bc6e9f55dcab077ed6d4e18 /Variables.py
parent55ad98c9c392ad92c22d25f6d00978d8cec2959a (diff)
downloadpp2cc-20416d5ae946d4defbfea66c53e58761cf885b73.tar.gz
WIP for func parameter support and local (automatic) variables
Diffstat (limited to 'Variables.py')
-rw-r--r--Variables.py91
1 files changed, 69 insertions, 22 deletions
diff --git a/Variables.py b/Variables.py
index 1d37f0f..338cfdf 100644
--- a/Variables.py
+++ b/Variables.py
@@ -19,42 +19,89 @@ __maintainer__ = "Peter Wu"
__email__ = "uwretep@gmail.com"
class Variables(object):
- def __init__(self, defined_names, parent_variables):
+ def __init__(self, parent_variables, defined_names, function=None):
"""A scope for holding variable names
Keywords arguments:
- defined_names -- A list of defined variables to which additional
- variables might be appended
parent_variables -- the parent Variables object. If None, it's a global
variable scope
+ defined_names -- A list of defined variables to which additional
+ variables might be appended
+ function -- The function object used for allocating memory. If not set,
+ the variables object will ask the parent_variables object for it
"""
- self.local_vars = {}
- self.defined_names = defined_names
self.parent_variables = parent_variables
+ self.function = function
+ # if there is a parent_variables object, it must be a function
+ if self.parent_variables:
+ # key: name, value: address n relative to BP (n >= 1)
+ self.local_vars = {}
+ self.param_vars = []
+ if not self.function:
+ self.function = self.parent_variables.function
+ else:
+ # key: name of var, value: label of var
+ self.global_vars = {}
+ self.defined_names = defined_names
def uniqName(self, name):
- """Returns an unique variable name"""
+ """Returns an unique global variable name for assembly"""
uniq_name = name
i = 0
while uniq_name in self.defined_names:
uniq_name = name + "_" + str(i)
i += 1
return uniq_name
- def getName(self, name):
- """Gets the name of a declared variable as it appears in the @DATA
- section"""
- if name in self.local_vars:
- return self.local_vars[name]
+ def getAddress(self, name):
+ """Gets the address for a variable as a tuple containing a register and
+ displacement
+
+ To get the address of the variable, add the register value and
+ displacement
+ """
+ # first try the local scope
+ if self.function:
+ if name in self.local_vars:
+ # XXX don't hardcode R5
+ return ("R5", str(self.local_vars[name]))
+ try:
+ return ("R5", str(-self.param_vars.index(name)))
+ except ValueError:
+ pass
+ else:
+ # lookup in global vars
+ if name in self.global_vars:
+ return ("GB", self.global_vars[name])
+ # lookup in the parent
if self.parent_variables:
- return self.parent_variables.getName(name)
+ return self.parent_variables.getAddress(name)
raise RuntimeError("Use of undefined variable '{}'".format(name))
- def declName(self, name, size=1, prefix="var"):
- """Declares a variable in the nearest scope and returns the label
- name"""
- if name in self.local_vars:
+ def declName(self, name, size=1, is_param=False):
+ """Declares a variable in the nearest scope
+
+ Keyword arguments:
+ name -- The symbolic name of the variable
+ size -- The size of the memory to be allocated in words (default 1)
+ is_param -- Whether the name is a function parameter or not
+ """
+ already_defined = False
+ if self.function:
+ already_defined = name in self.local_vars or name in self.param_vars
+ else:
+ already_defined = name in self.global_vars
+ if already_defined:
raise RuntimeError("Redeclaration of variable '{}'".format(name))
- # global variables are prefixed "var_", locals with "varl_"
- var_name = prefix + ("l_" if self.parent_variables else "_") + name
- var_name = self.uniqName(var_name)
- self.local_vars[name] = var_name
- self.defined_names[var_name] = size
- return var_name
+
+ if self.function:
+ # parameters do not need a special allocation because the callee
+ # pushes it into the stack
+ if is_param:
+ self.param_vars.append(name)
+ else:
+ self.local_vars[name] = self.function.allocStack(size)
+ elif is_param:
+ raise RuntimeError("Parameter '{}' declared in global context".format(name))
+ else:
+ # global variables are prefixed "var_"
+ var_name = "var_" + name
+ self.global_vars[name] = var_name
+ self.defined_names[var_name] = size