def get_constant_value(self, node, offset=0): if node.type == 'int': return il.Types.int, Frontend.make_int_constant( int(node.value, 0) + offset) elif node.type == 'string': assert type(node.value) == str if node.value[0] != '"' or node.value[-1] != '"': raise ParseError('invalid char constant ' + node.value, coord=node.coord) str_value = node.value[1:-1] + '\0' value_escaped = ''.join(c for c in str_value if c.isalnum()) var_name = '__A_' + value_escaped il_var = il.Variable(var_name, il.Types.char, coord=node.coord) string_init = il.CompiledValue(map(ord, str_value), il.CompiledValueType.WordArray) self._globals.append( il.GlobalName(var_name, il_var, string_init, self.cur_pragma_loc, self.cur_pragma_linkage, coord=node.coord)) return il.Types.ptr, Frontend.make_pointer_constant(var_name) elif node.type == 'char': if node.value[0] != "'" or node.value[-1] != "'": raise ParseError('invalid char constant ' + node.value, coord=node.coord) return il.Types.char, Frontend.make_int_constant( ord(str(node.value[1:-1]).decode('string-escape'))) else: raise UnsupportedFeatureError('unsupported constant type ' + node.type)
def on_break_node(self, node): assert type(node) == c_ast.Break if not self.cur_func: raise ParseError("use of 'break' outside of function", coord=node.coord) if not self.loop_stack: raise ParseError("use of 'break' outside of loop", coord=node.coord) start_block, end_block = self.loop_stack[-1] self.add_stmt(il.GotoStmt(end_block, coord=node.coord)) self.cur_block = self.cur_func.cfg.new_block()
def on_id_node(self, node): """Resolve an identifier (ID) node into a variable""" scope, ast_decl = self.current_scope.resolve_symbol(node.name) if not scope: raise ParseError('use of undeclared symbol ' + node.name, coord=node.coord) try: il_var = self._c_variables[ast_decl] return il_var except KeyError: raise ParseError('Cannot use variable in its definition.', coord=node.coord)
def parse_binary_op(op, coord=None): if op == '+': return il.BinaryOp.Add elif op == '-': return il.BinaryOp.Sub elif op == '*': return il.BinaryOp.Mul elif op == '==': return il.BinaryOp.Equ elif op == '!=': return il.BinaryOp.Neq elif op == '<': return il.BinaryOp.Lt elif op == '>': return il.BinaryOp.Gt elif op == '&&': return il.BinaryOp.LogicalAnd elif op == '||': return il.BinaryOp.LogicalOr elif op == '&': return il.BinaryOp.And elif op == '|': return il.BinaryOp.Or elif op == '*': return il.BinaryOp.Mul else: raise ParseError('unsupported binary operation ' + op, coord=coord)
def on_pragma_node(self, node): pragma = node.string parts = pragma.split(' ') if parts[0] == 'location': try: loc = int(parts[1], 0) except ValueError: raise ParseError('invalid pragma location: ' + parts[1], coord=node.coord) self.cur_pragma_loc = loc elif parts[0] == 'extern': if len(parts) != 2: raise ParseError('invalid linkage pragma: ' + node.string, coord=node.coord) self.cur_pragma_linkage = parts[1] else: sys.stderr.write('warning: ignored pragma ' + pragma + '\n')
def on_decl_node(self, node): """ :param node: c_ast.Decl node :return: new IL variable corresponding to the declaration """ assert type(node) == c_ast.Decl decl_name = node.name if decl_name in self.current_scope.symbols: raise ParseError("redefinition of %s" % (decl_name, ), coord=node.coord) else: self.current_scope.symbols[decl_name] = node var_type = self.get_node_type(node.type) if var_type == il.Types.ptr: ref_level, ref_type = self.extract_pointer_type(node.type) # print 'pointer declared: %s %d %s' % (node.name, ref_level, ref_type) else: # print 'local declared: %s' % (node.name,) ref_level, ref_type = 0, None var_name = '_' + str(self.current_scope.name) + '_' + node.name il_var = il.Variable(var_name, var_type, ref_level, ref_type) if self.scope_depth > 1: # we are in a function -> this is a local decl. if node.init: init_expr_var = self.on_expr_node(node.init) self.add_stmt(self.on_assign(il_var, init_expr_var)) if self.cur_func: self.cur_func.locals.append(il_var) else: init = None if node.init: if type(node.init) == c_ast.Constant: const_type, init = self.get_constant_value(node.init) elif type(node.init) == c_ast.ID: id_var = self.on_id_node(node.init) for glob in self._globals: if glob.name == node.init.name: init = glob.init break else: raise RuntimeError( "couldn't find initialiser for referenced global " + node.init.name) else: raise UnsupportedFeatureError( 'global variable initialisers must be constant') self._globals.append( il.GlobalName(node.name, il_var, init, self.cur_pragma_loc, self.cur_pragma_linkage)) self._c_variables[node] = il_var return il_var
def error_specifier(token, spec): raise ParseError( "cannot combine '%s' with previous declaration specifier %s" % (token, spec), coord=coord)