예제 #1
0
 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)
예제 #2
0
    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()
예제 #3
0
    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)
예제 #4
0
 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)
예제 #5
0
 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')
예제 #6
0
    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
예제 #7
0
 def error_specifier(token, spec):
     raise ParseError(
         "cannot combine '%s' with previous declaration specifier %s" %
         (token, spec),
         coord=coord)