Example #1
0
    def make_il(self, il_code, symbol_table, c):  # noqa D102
        lvalue = self.lvalue(il_code, symbol_table, c)

        # Decay array
        if lvalue.ctype().is_array():
            addr = lvalue.addr(il_code)
            return set_type(addr, PointerCType(lvalue.ctype().el), il_code)

        # Decay function
        elif lvalue.ctype().is_function():
            return lvalue.addr(il_code)

        # Nothing to decay
        else:
            return lvalue.val(il_code)
Example #2
0
    def _lvalue(self, il_code, symbol_table, c):
        head_lv = self.head.lvalue(il_code, symbol_table, c)
        struct_ctype = head_lv.ctype() if head_lv else None
        offset, ctype = self.get_offset_info(struct_ctype)

        if isinstance(head_lv, DirectLValue):
            head_val = self.head.make_il(il_code, symbol_table, c)
            return RelativeLValue(ctype, head_val, offset)
        else:
            struct_addr = head_lv.addr(il_code)

            shift = ILValue(ctypes.longint)
            il_code.register_literal_var(shift, str(offset))

            out = ILValue(PointerCType(ctype))
            il_code.add(math_cmds.Add(out, struct_addr, shift))
            return IndirectLValue(out)
Example #3
0
    def make_ctype(self, decl, prev_ctype):
        """Generate a ctype from the given declaration.

        Return a `ctype, identifier token` tuple.

        decl - Node of decl_nodes to parse. See decl_nodes.py for explanation
        about decl_nodes.
        prev_ctype - The ctype formed from all parts of the tree above the
        current one.
        """
        if isinstance(decl, decl_nodes.Pointer):
            new_ctype = PointerCType(prev_ctype, decl.const)
        elif isinstance(decl, decl_nodes.Array):
            new_ctype = self._generate_array_ctype(decl, prev_ctype)
        elif isinstance(decl, decl_nodes.Function):
            new_ctype = self._generate_func_ctype(decl, prev_ctype)
        elif isinstance(decl, decl_nodes.Identifier):
            return prev_ctype, decl.identifier

        return self.make_ctype(decl.child, new_ctype)
Example #4
0
 def addr(self, il_code):  # noqa D102
     out = ILValue(PointerCType(self.il_value.ctype))
     il_code.add(value_cmds.AddrOf(out, self.il_value))
     return out
Example #5
0
 def addr(self, il_code):
     self._fix_chunk_count(il_code)
     out = ILValue(PointerCType(self.ctype()))
     il_code.add(value_cmds.AddrRel(
         out, self.base, self.fixed_chunk, self.fixed_count))
     return out
Example #6
0
    def make_ctype(self, decl, prev_ctype, symbol_table):
        """Generate a ctype from the given declaration.

        Return a `ctype, identifier token, storage class` triple.

        decl - Node of decl_nodes to parse. See decl_nodes.py for explanation
        about decl_nodess.
        prev_ctype - The ctype formed from all parts of the tree above the
        current one.
        storage - The storage class of this declaration.
        """
        if isinstance(decl, decl_nodes.Pointer):
            new_ctype = PointerCType(prev_ctype, decl.const)
        elif isinstance(decl, decl_nodes.Array):
            new_ctype = ArrayCType(prev_ctype, decl.n)
        elif isinstance(decl, decl_nodes.Function):
            # Prohibit storage class specifiers in parameters.
            for param in decl.args:
                decl_info = self.get_decl_infos(param, symbol_table)[0]
                if decl_info.storage:
                    err = "storage class specified for function parameter"
                    raise CompilerError(err, decl_info.range)

            # Create a new scope because if we create a new struct type inside
            # the function parameters, it should be local to those parameters.
            symbol_table.new_scope()
            args = [
                self.get_decl_infos(decl, symbol_table)[0].ctype
                for decl in decl.args
            ]
            symbol_table.end_scope()

            # adjust array and function parameters
            has_void = False
            for i in range(len(args)):
                ctype = args[i]
                if ctype.is_array():
                    args[i] = PointerCType(ctype.el)
                elif ctype.is_function():
                    args[i] = PointerCType(ctype)
                elif ctype.is_void():
                    has_void = True

            if has_void and len(args) > 1:
                decl_info = self.get_decl_infos(decl.args[0], symbol_table)[0]
                err = "'void' must be the only parameter"
                raise CompilerError(err, decl_info.range)

            # Function declarators cannot have a function or array return type.
            # TODO: Relevant only when typedef is implemented.

            if has_void:
                new_ctype = FunctionCType([], prev_ctype, False)
            elif not args:
                new_ctype = FunctionCType([], prev_ctype, True)
            else:
                new_ctype = FunctionCType(args, prev_ctype)

        elif isinstance(decl, decl_nodes.Identifier):
            return prev_ctype, decl.identifier

        return self.make_ctype(decl.child, new_ctype, symbol_table)