Esempio n. 1
0
    def _arith(self, left, right, il_code):
        """Return the result of this operation on given arithmetic operands.

        Promotions and conversions are done by caller, so the implementation of
        this function need not convert operands.

        A default implementation is provided, but this can be overriden by
        derived classes.

        left - ILValue for left operand
        right - ILValue for right operand
        """
        out = ILValue(left.ctype)
        il_code.add(self.default_il_cmd(out, left, right))
        return out
Esempio n. 2
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for a literal number.

        This function does not actually make any code in the IL, it just
        returns a LiteralILValue that can be used in IL code by the caller.
        """
        v = int(str(self.number))

        if ctypes.int_min <= v <= ctypes.int_max:
            il_value = ILValue(ctypes.integer)
        elif ctypes.long_min <= v <= ctypes.long_max:
            il_value = ILValue(ctypes.longint)
        else:
            err = "integer literal too large to be represented by any " \
                  "integer type"
            raise CompilerError(err, self.number.r)

        il_code.register_literal_var(il_value, v)

        # Literal integer 0 is a null pointer constant
        if v == 0:
            il_value.null_ptr_const = True

        return il_value
Esempio n. 3
0
def set_type(il_value, ctype, il_code, output=None):
    """If necessary, emit code to cast given il_value to the given ctype.

    This function does no type checking and will never produce a warning or
    error.

    """
    if not output and il_value.ctype.compatible(ctype):
        return il_value
    elif output == il_value:
        return il_value
    else:
        if not output:
            output = ILValue(ctype)
        il_code.add(value_cmds.Set(output, il_value))
        return output
Esempio n. 4
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""

        # This is of function pointer type, so func.arg is the function type.
        func = self.func.make_il(il_code, symbol_table, c)

        if not func.ctype.is_pointer() or not func.ctype.arg.is_function():
            descrip = "called object is not a function pointer"
            raise CompilerError(descrip, self.func.r)

        if not func.ctype.arg.args:
            final_args = self._get_args_without_prototype(
                il_code, symbol_table, c)
        else:
            final_args = self._get_args_with_prototype(
                func.ctype.arg, il_code, symbol_table, c)

        ret = ILValue(func.ctype.arg.ret)
        il_code.add(control_cmds.Call(func, final_args, ret))
        return ret
Esempio n. 5
0
 def make_il(self, il_code, symbol_table, c):
     """Make code for this node."""
     expr = self.expr.make_il(il_code, symbol_table, c)
     if not self._check_type(expr):
         err = f"{self.descrip} requires {self.opnd_descrip} type operand"
         raise CompilerError(err, self.expr.r)
     # perform integer promotion
     if expr.ctype.size < 4:
         expr = set_type(expr, ctypes.integer, il_code)
     if self.cmd:
         out = ILValue(expr.ctype)
         # perform constant folding
         if expr.literal:
             val = self._arith_const(expr.literal.val, expr.ctype)
             val = shift_into_range(val, expr.ctype)
             il_code.register_literal_var(out, val)
         else:
             il_code.add(self.cmd(out, expr))
         return out
     return expr
Esempio n. 6
0
    def _nonarith(self, left, right, il_code):
        """Make addition code if either operand is non-arithmetic type."""

        # One operand should be pointer to complete object type, and the
        # other should be any integer type.
        if left.ctype.is_pointer() and right.ctype.is_integral():
            arith, pointer = right, left
        elif right.ctype.is_pointer() and left.ctype.is_integral():
            arith, pointer = left, right
        else:
            err = "invalid operand types for addition"
            raise CompilerError(err, self.op.r)

        if not pointer.ctype.arg.is_complete():
            err = "invalid arithmetic on pointer to incomplete type"
            raise CompilerError(err, self.op.r)

        # Multiply by size of objects
        out = ILValue(pointer.ctype)
        shift = get_size(pointer.ctype.arg, arith, il_code)
        il_code.add(math_cmds.Add(out, pointer, shift))
        return out
Esempio n. 7
0
    def do_body(self, il_code, symbol_table, c):
        """Create code for function body.

        Caller must check that this function has a body.
        """
        is_main = self.identifier.content == "main"

        for param in self.param_names:
            if not param:
                err = "function definition missing parameter name"
                raise CompilerError(err, self.range)

        if is_main:
            self.check_main_type()

        c = c.set_return(self.ctype.ret)
        il_code.start_func(self.identifier.content)

        symbol_table.new_scope()

        num_params = len(self.ctype.args)
        iter = zip(self.ctype.args, self.param_names, range(num_params))
        for ctype, param, i in iter:
            arg = symbol_table.add_variable(
                param, ctype, symbol_table.DEFINED, None,
                symbol_table.AUTOMATIC)
            il_code.add(value_cmds.LoadArg(arg, i))

        self.body.make_il(il_code, symbol_table, c, no_scope=True)
        if not il_code.always_returns() and is_main:
            zero = ILValue(ctypes.integer)
            il_code.register_literal_var(zero, 0)
            il_code.add(control_cmds.Return(zero))
        elif not il_code.always_returns():
            il_code.add(control_cmds.Return(None))

        symbol_table.end_scope()
Esempio n. 8
0
    def _nonarith(self, left, right, il_code):
        """Check equality of non-arithmetic expressions."""

        # If either operand is a null pointer constant, cast it to the
        # other's pointer type.
        if (left.ctype.is_pointer()
             and getattr(right.literal, "val", None) == 0):
            right = set_type(right, left.ctype, il_code)
        elif (right.ctype.is_pointer()
              and getattr(left.literal, "val", None) == 0):
            left = set_type(left, right.ctype, il_code)

        # If both operands are not pointer types, quit now
        if not left.ctype.is_pointer() or not right.ctype.is_pointer():
            with report_err():
                err = "comparison between incomparable types"
                raise CompilerError(err, self.op.r)

        # If one side is pointer to void, cast the other to same.
        elif left.ctype.arg.is_void():
            check_cast(right, left.ctype, self.op.r)
            right = set_type(right, left.ctype, il_code)
        elif right.ctype.arg.is_void():
            check_cast(left, right.ctype, self.op.r)
            left = set_type(left, right.ctype, il_code)

        # If both types are still incompatible, warn!
        elif not left.ctype.compatible(right.ctype):
            with report_err():
                err = "comparison between distinct pointer types"
                raise CompilerError(err, self.op.r)

        # Now, we can do comparison
        out = ILValue(ctypes.integer)
        il_code.add(self.eq_il_cmd(out, left, right))
        return out
Esempio n. 9
0
 def _arith(self, left, right, il_code):
     """Compare arithmetic expressions."""
     out = ILValue(ctypes.integer)
     il_code.add(self.comp_cmd(out, left, right))
     return out
Esempio n. 10
0
 def _arith(self, left, right, il_code):
     """Check equality of arithmetic expressions."""
     out = ILValue(ctypes.integer)
     il_code.add(self.eq_il_cmd(out, left, right))
     return out
Esempio n. 11
0
 def _lvalue(self, il_code, symbol_table, c):
     il_value = ILValue(ArrayCType(ctypes.char, len(self.chars)))
     il_code.register_string_literal(il_value, self.chars)
     return DirectLValue(il_value)
Esempio n. 12
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
Esempio n. 13
0
 def val(self, il_code):
     self._fix_chunk_count(il_code)
     out = ILValue(self.ctype())
     il_code.add(value_cmds.ReadRel(
         out, self.base, self.fixed_chunk, self.fixed_count))
     return out
Esempio n. 14
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
Esempio n. 15
0
 def val(self, il_code):  # noqa D102
     out = ILValue(self.ctype())
     il_code.add(value_cmds.ReadAt(out, self.addr_val))
     return out
Esempio n. 16
0
 def _lvalue(self, il_code, symbol_table, c):
     il_value = ILValue(ASMCType(ctypes.integer, len(self.code)))
     il_code.register_asm_literal(il_value, self.code)
     return DirectLValue(il_value)