summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-12-03 13:55:31 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-12-03 13:55:31 +0000
commitcbb589740133d53224fcd66c4c2decf43a7eca6e (patch)
tree3675a6cf2165af6d5c14b9bc6c5982facb7598cb
parent658bfe6c92b6dccea353da38a7651c61cd4ef1ce (diff)
downloadpp2cc-cbb589740133d53224fcd66c4c2decf43a7eca6e.tar.gz
Support multiple declarations in the global scope
-rw-r--r--README3
-rw-r--r--Variables.py21
-rwxr-xr-xpp2cc.py16
3 files changed, 35 insertions, 5 deletions
diff --git a/README b/README
index 29b6dff..6adfb4a 100644
--- a/README
+++ b/README
@@ -100,7 +100,8 @@ A8.7 Initialization - Supported for an expression resulting in an int, arrays
may be initialized with a list of expressions yielding a constant
value, e.g. int a[2]={3,1+2};int b[]={2}; in If the number of
initializers are larger than the dimension, the excess elements are
- discarded.
+ discarded. Multi-dimensional arrays are not supported at
+ initialization.
A8.8 Type names - not verified
A8.9 Typedef - won't be supported as we have int only
diff --git a/Variables.py b/Variables.py
index 617113f..89c8501 100644
--- a/Variables.py
+++ b/Variables.py
@@ -84,7 +84,10 @@ class GlobalVariables(Variables):
defined in assembly
"""
self.defined_names = defined_names
+ # key: variable name, value: name as it appears in assembly
self.global_vars = {}
+ # a list of variable names which are declared and defined
+ self.global_vars_defined = []
def _uniqName(self, name):
"""Returns an unique global variable name for assembly"""
uniq_name = name
@@ -93,6 +96,12 @@ class GlobalVariables(Variables):
uniq_name = name + "_" + str(i)
i += 1
return uniq_name
+ def isDeclared(self, name):
+ """Returns True if the global variable is declared, False otherwise"""
+ return name in self.global_vars
+ def isDefined(self, name):
+ """Returns True if the global variable is defined, False otherwise"""
+ return name in self.global_vars_defined
def getAddress(self, name):
"""Gets the address for a variable as a tuple containing a register and
displacement
@@ -100,7 +109,7 @@ class GlobalVariables(Variables):
To get the address of the variable, add the register value and
displacement
"""
- if name in self.global_vars:
+ if self.isDeclared(name):
return ("GB", self.global_vars[name])
raise RuntimeError("Use of undefined variable '{}'".format(name))
def declName(self, name, size=1, is_param=False, is_static=False):
@@ -138,3 +147,13 @@ class GlobalVariables(Variables):
else:
# insert size items, initialized with 0
self.defined_names[var_name] = ["0"] * size
+ def defName(self, name):
+ """Marks a variable name as defined
+
+ Variables may be declared multiple times in the globa scope, but not
+ defined multiple times
+ """
+ assert self.isDeclared(name), "Definition of undeclared '{}'".format(name)
+ if self.isDefined(name):
+ raise RuntimeError("Redefinition of '{}'".format(name))
+ self.global_vars_defined.append(name)
diff --git a/pp2cc.py b/pp2cc.py
index 03a57a1..190f10a 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -988,7 +988,7 @@ class Parse(object):
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
+ # a function declaration does not accept an initializer, but it's
# still special because it has params
return self.parseStatement(linked_type.node, linked_node)
else:
@@ -1000,8 +1000,11 @@ class Parse(object):
size += 1
try:
- is_static = "static" in linked_node.node.storage
- linked_node.variables.declName(name, size, is_static=is_static)
+ # global variables may be declared multiple times, local variables
+ # are not allowed for that
+ if in_function or not linked_node.variables.isDeclared(name):
+ is_static = "static" in linked_node.node.storage
+ linked_node.variables.declName(name, size, is_static=is_static)
# address of variable split up in register and displacement
var_reg, var_disp = linked_node.variables.getAddress(name)
except RuntimeError as errmsg:
@@ -1020,6 +1023,13 @@ class Parse(object):
var_reg + "+" + var_disp + "]"))
# if the declaration also has a definition
if linked_node.node.init:
+ # global variables needs to be marked as defined
+ if not in_function:
+ try:
+ linked_node.variables.defName(name)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
+
init_vals = []
linked_init = LinkedNode(linked_node.node.init, linked_node)
if (linked_type.type == "ArrayDecl" and