diff options
-rwxr-xr-x | pp2cc.py | 115 |
1 files changed, 81 insertions, 34 deletions
@@ -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 |