summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-12-01 18:48:02 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-12-01 18:48:02 +0000
commit01844bc4e06c89fcec3c06257800ceab4feea46b (patch)
tree496e676d0321e054c4f1ddbc569dc174e0224bef
parent20416d5ae946d4defbfea66c53e58761cf885b73 (diff)
downloadpp2cc-01844bc4e06c89fcec3c06257800ceab4feea46b.tar.gz
Add some debugging aid
-rwxr-xr-xpp2cc.py115
1 files changed, 81 insertions, 34 deletions
diff --git a/pp2cc.py b/pp2cc.py
index 5a079c8..0ae2803 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -30,11 +30,17 @@ class Logger(object):
pass
def warning(self, message, linked_node=None):
self.log(message, linked_node=linked_node, type="warning")
+ def error(self, message, linked_node=None):
+ self.log(message, linked_node=linked_node, type="error")
+ while linked_node:
+ print " in", linked_node.node.coord, linked_node.type
+ linked_node = linked_node.parent
+ raise
def log(self, message, linked_node=None, type="log"):
source = ""
if isinstance(linked_node, LinkedNode):
source = str(linked_node.getLocation()) + ": "
- print type + ":" + source + message
+ print type + ":" + source, message
class Parse(object):
def __init__(self):
@@ -105,7 +111,7 @@ class Parse(object):
return lbl
def addLabel(self, labelname):
if labelname in self.labels:
- raise RuntimeError("Redefinition of label '{}'".format(labelname))
+ self.logger.error("Redefinition of label '{}'".format(labelname))
self.labels.add(labelname)
def compile(self):
"""Loops through the nodes in an AST syntax tree and generates ASM"""
@@ -146,7 +152,8 @@ class Parse(object):
funcname = node.decl.name
if funcname in self.functions:
- raise RuntimeError("Redefinition of function '{}'".format(funcname))
+ self.logger.error("Redefinition of function '{}'".format(funcname),
+ linked_node=linked_node)
function = self.functions[funcname] = Function(node)
lbl_func = function.labelBegin()
@@ -262,7 +269,8 @@ class Parse(object):
elif node.op in ("&&", "||"):
return self.parseBinaryLogicalOp(linked_node)
else:
- raise RuntimeError("Binary op is not implemented yet: " + node.op)
+ self.logger.error("Binary op is not implemented yet: " + node.op,
+ linked_node=linked_node)
# process the first operand, the result is likely in R0 or R1
ops_first = self.parseExpression(node.left, linked_node, level_increment=True)
@@ -419,7 +427,8 @@ class Parse(object):
binop = binops[op[1:]]
stmt = linked_node.getStatementNode()
if not stmt:
- raise RuntimeError("No statement found for post inc/decrement")
+ self.logger.error("No statement found for post inc/decrement",
+ linked_node=linked_node)
# assume that the result register is R0
lvalue = self.parseLValue(linked_cn)
lines = lvalue;
@@ -435,7 +444,8 @@ class Parse(object):
lines.append(self.asm.binary_op(binop, "R1", 1))
lines.append(self.asm.binary_op("STOR", "R1", "[R0]"))
else:
- raise RuntimeError("Unknown lvalue unary operator '{}'".format(op))
+ self.logger.error("Unknown lvalue unary operator '{}'".format(op),
+ linked_node=linked_node)
return lines
def parseUnaryOp(self, linked_node):
"""Returns lines of assembly for unary operators
@@ -484,9 +494,11 @@ class Parse(object):
lines.append(self.asm.binary_op("LOAD", reg, 0, label=lbl_false))
lines.append(self.asm.noop(lbl_end, register=reg))
elif op == "sizeof":
- raise RuntimeError("Sizeof operator 'sizeof' is not supported.")
+ self.logger.error("Sizeof operator 'sizeof' is not supported.",
+ linked_node=linked_node)
else:
- raise RuntimeError("Unknown unary operator '{}'".format(op))
+ self.logger.error("Unknown unary operator '{}'".format(op),
+ linked_node=linked_node)
return lines
def parseTernaryOp(self, linked_node):
"""Returns lines of ASM for ternary operation cond?expr_true:expr_false
@@ -533,7 +545,8 @@ class Parse(object):
if isinstance(node, c_ast.Constant) and node.type == "int":
value = node.value
else:
- raise RuntimeError("Value is not given and node is not a valid integer constant")
+ self.logger.error("Value is not given and node is not a valid"
+ " integer constant")
value = value.upper()
if "LL" in value: # long long integer, ignore
@@ -579,12 +592,16 @@ class Parse(object):
if node.type == "int":
value = self.convertInteger(node.value)
else:
- raise RuntimeError("Unsupported constant type: " + node.type)
+ self.logger.error("Unsupported constant type: " + node.type,
+ linked_node=linked_node)
return [self.asm.binary_op("LOAD", register, value)]
def parseID(self, linked_node, register="R0"):
"""Returns the name for a name"""
# XXX this is not made for functions
- addr = "+".join(linked_node.variables.getAddress(linked_node.node.name))
+ try:
+ addr = "+".join(linked_node.variables.getAddress(linked_node.node.name))
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
return [self.asm.binary_op("LOAD", register, "[" + addr + "]")]
def parseIf(self, linked_node):
linked_node.incrementLevel()
@@ -640,7 +657,8 @@ class Parse(object):
"""Return from a function. For non-void functions the result is in R0"""
func_node = linked_node.getFunctionNode()
if not func_node:
- raise RuntimeError("return not in function")
+ self.logger.error("return not in function",
+ linked_node=linked_node)
return_value = linked_node.node.expr
if return_value:
@@ -825,7 +843,8 @@ class Parse(object):
lines.append(self.asm.binary_op("STOR", lvalue_reg,
"[" + result_reg + "]"))
else:
- raise RuntimeError("Unsupported assignment operator: " + node.op)
+ self.logger.error("Unsupported assignment operator: " + node.op,
+ linked_node=linked_node)
return lines
def parseLValue(self, linked_node, register="R0"):
"""Returns lines of ASM for a lvalue type.
@@ -840,11 +859,15 @@ class Parse(object):
lines.append(self.asm.binary_op("LOAD", register,
"[" + register + "]"))
elif linked_node.type == "ID":
- var_reg, var_disp = linked_node.variables.getAddress(linked_node.node.name)
+ try:
+ var_reg, var_disp = linked_node.variables.getAddress(linked_node.node.name)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
lines.append(self.asm.binary_op("LOAD", register, var_reg))
lines.append(self.asm.binary_op("ADD", register, var_disp))
else:
- raise RuntimeError("Expected a lvalue (pointer or names)")
+ self.logger.error("Expected a lvalue (pointer or names)",
+ linked_node=linked_node)
return lines
def parseDecl(self, linked_node):
lines = []
@@ -869,7 +892,8 @@ class Parse(object):
# it's an error if the array dimension is unavailable, e.g.:
# int a[];
if size is None:
- raise RuntimeError("Array size missing in '{}'".format(name))
+ self.logger.error("Array size missing in '{}'".format(name),
+ linked_node=linked_node)
elif linked_type.type == "PtrDecl":
# no check whether the pointer is valid or not
pass
@@ -881,11 +905,15 @@ class Parse(object):
# still special because it has params
return self.parseStatement(linked_type.node, linked_node)
else:
- raise RuntimeError("Unknown declaration type '{}'".format(linked_type.type))
+ self.logger.error("Unknown declaration type '{}'".format(linked_type.type),
+ linked_node=linked_node)
- linked_node.variables.declName(name, size)
- # address of variable split up in register and displacement
- var_reg, var_disp = linked_node.variables.getAddress(name)
+ try:
+ linked_node.variables.declName(name, size)
+ # address of variable split up in register and displacement
+ var_reg, var_disp = linked_node.variables.getAddress(name)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
# if the declaration also has a definition
if linked_node.node.init:
@@ -941,12 +969,14 @@ class Parse(object):
def parseBreak(self, linked_node):
loop_node = linked_node.getBreakNode()
if not loop_node:
- raise RuntimeError("break not in a loop or switch")
+ self.logger.error("break not in a loop or switch",
+ linked_node=linked_node)
return [self.asm.branch_op("BRA", loop_node.break_label)]
def parseContinue(self, linked_node):
loop_node = linked_node.getContinueNode()
if not loop_node:
- raise RuntimeError("continue not in a loop")
+ self.logger.error("continue not in a loop",
+ linked_node=linked_node)
return [self.asm.branch_op("BRA", loop_node.continue_label)]
def parseEmptyStatement(self, linked_node):
"""Returns an empty list for an "empty statement" (duh)"""
@@ -1031,7 +1061,10 @@ class Parse(object):
return lines
def parseLabel(self, linked_node):
lines = []
- label_name = linked_node.setLabel(linked_node.node.name)
+ try:
+ label_name = linked_node.setLabel(linked_node.node.name)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
lines.append(self.asm.noop(label_name))
lines += self.parseStatement(linked_node.node.stmt, linked_node)
return lines
@@ -1039,7 +1072,10 @@ class Parse(object):
"""Provides support for the infinitely abused goto statement. Use it
for debugging only!
"""
- label_name = linked_node.lookupLabel(linked_node.node.name)
+ try:
+ label_name = linked_node.lookupLabel(linked_node.node.name)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
return [self.asm.branch_op("BRA", label_name)]
def parseFuncDecl(self, linked_node):
lines = []
@@ -1055,8 +1091,11 @@ class Parse(object):
lines = []
variables = linked_node.getFunctionNode().variables
params = linked_node.node.params
- for param in params:
- variables.declName(param.name, is_param=True)
+ try:
+ for param in params:
+ variables.declName(param.name, is_param=True)
+ except RuntimeError as errmsg:
+ self.logger.error(errmsg, linked_node=linked_node)
return lines
def parseStatement(self, node, parent_linked_node, level_increment=False):
linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment)
@@ -1068,7 +1107,8 @@ class Parse(object):
# add for support post increment and decrement
lines += linked_node.post_lines
else:
- raise RuntimeError("Not implemented for type " + repr(node))
+ self.logger.error("Not implemented for type " + repr(node),
+ linked_node=linked_node)
else:
lines += self.parseExpression(node, parent_linked_node, level_increment)
return lines
@@ -1086,13 +1126,16 @@ class Parse(object):
elif linked_node.type in ("Compound", "If", "Return", "DoWhile",
"While", "For", "Decl", "FuncDef", "Break", "Continue",
"EmptyStatement"):
- raise RuntimeError("A statement is used in expression context")
+ self.logger.error("A statement is used in expression context",
+ linked_node=linked_node)
elif linked_node.type in ("CompoundLiteral",# won't be supported
"IdentifierType", "NamedInitializer",# attributes, remove
"StructRef", "Typename"):
- raise RuntimeError("Not implemented for expression type " + repr(node))
+ self.logger.error("Not implemented for expression type " + repr(node),
+ linked_node=linked_node)
else:
- raise RuntimeError("Not implemented expression and unknown type: " + repr(node))
+ self.logger.error("Not implemented expression and unknown type: " +
+ repr(node), linked_node=linked_node)
return lines
def determineConstValue(self, linked_node):
"""Returns the value of the constant expression of linked_node as an
@@ -1106,7 +1149,8 @@ class Parse(object):
if linked_node.type == "Constant":
if node.type != "int":
- raise RuntimeError("Unsupported constant type '{}'".format(node.type))
+ self.logger.error("Unsupported constant type '{}'".format(node.type),
+ linked_node=linked_node)
value = self.convertStrToInteger(self.convertInteger(node.value))
elif linked_node.type == "UnaryOp":
op = node.op
@@ -1117,7 +1161,8 @@ class Parse(object):
"~": "invert"
}
if op not in operators:
- raise RuntimeError("Operator '{}' is not supported".format(op))
+ self.logger.error("Operator '{}' is not supported".format(op),
+ linked_node=linked_node)
else:
operand = self.determineConstValue(node.expr)
if op == "-":
@@ -1151,7 +1196,8 @@ class Parse(object):
">>": "rshift"
}
if op not in operators:
- raise RuntimeError("Operator '{}' is not supported".format(op))
+ self.logger.error("Operator '{}' is not supported".format(op),
+ linked_node=linked_node)
else:
operand1 = self.determineConstValue(node.left)
operand2 = self.determineConstValue(node.right)
@@ -1174,7 +1220,8 @@ class Parse(object):
else:
value = int(getattr(operator, op)(operand1, operand2))
else:
- raise RuntimeError("Unsupported node type '{}'".format(linked_node.type))
+ self.logger.error("Unsupported node type '{}'".format(linked_node.type),
+ linked_node=linked_node)
# The PP2 can only count in 18-bit, therefore AND the result. Note that
# overflow may occur for large numbes. This is a non-issue for unary +
# - ~ (and ! because it results in 0 or 1). For binary comparison