Exemple #1
0
    async def compile(self, ctx: CompileContext) -> Register:
        lhs, rhs = await self.compile_meta(ctx)

        res = ctx.get_register(lhs.size, self.sign)

        op = {"+": "add", "-": "sub"}[self.op]

        if isinstance(await self.type, Pointer):
            # adding a pointer with an integer multiplies the integer side by the pointed to type
            (ptr_type, non_ptr) = ((self.left_type, rhs) if isinstance(
                self.left_type, Pointer) else (self.right_type, lhs))

            if isinstance(ptr_type.to, Void):
                raise self.error("Cannot perform pointer arithmetic on pointer to void.")

            ctx.emit(Binary.mul(non_ptr, Immediate(ptr_type.to.size, non_ptr.size)))
        elif (op == "sub"
              and isinstance(self.left_type, Pointer)
              and isinstance(self.right_type, Pointer)):
            if isinstance(self.left_type.to, Void):
                raise self.error("Cannot perform pointer arithmetic on pointer to void.")

            if self.left_type != self.right_type:
                raise self.error("Both sides of pointer subtraction must be the same type.")

            # subtracting two pointers of equal type yields the number of elements between them
            ctx.emit(Binary(lhs, rhs, op, res))
            ctx.emit(Binary.udiv(res, Immediate(self.left_type.to.size, res.size)))
            return res

        ctx.emit(Binary(lhs, rhs, op, res))
        return res
Exemple #2
0
    async def compile(self, ctx: CompileContext) -> Register:
        op = {"|": "or", "^": "xor", "&": "and"}[self.op]

        lhs, rhs = await self.compile_meta(ctx)
        res = ctx.get_register(lhs.size, self.sign)
        ctx.emit(Binary(lhs, rhs, op, res))
        return res
Exemple #3
0
    async def compile(self, ctx: CompileContext) -> Register:
        my_type = await self.type

        ptr: Register = await self.load_lvalue(ctx)
        tmp = ctx.get_register(my_type.size, my_type.signed)

        increment = 1
        # in the case of pointer increments, increment by the size of the pointer's underlying type
        if isinstance(my_type, Pointer):
            increment = my_type.to.size

        ctx.emit(Mov(tmp, Dereference(ptr, tmp.size)))
        ctx.emit(Binary(tmp, Immediate(increment, tmp.size), self.op))
        ctx.emit(Mov(Dereference(ptr, tmp.size), tmp))
        return tmp
Exemple #4
0
    async def compile(self, ctx: CompileContext) -> Register:
        my_type = await self.type

        ptr: Register = await self.arg.load_lvalue(ctx)
        size = my_type.size
        res, temp = (ctx.get_register(size, my_type.signed),
                     ctx.get_register(size))

        increment = 1
        if isinstance(my_type, Pointer):
            increment = my_type.to.size

        ctx.emit(Mov(res, Dereference(ptr, res.size)))
        ctx.emit(Binary(res, Immediate(increment, size), self.op, temp))
        ctx.emit(Mov(Dereference(ptr, temp.size), temp))
        return res
Exemple #5
0
    async def compile(self, ctx: CompileContext) -> Register:
        lhs, rhs = await self.compile_meta(ctx)
        if rhs.sign:
            raise self.right.error(
                "RHS operand to a binary shift op must be unsigned.")

        res = ctx.get_register(lhs.size, self.sign)

        if self.op == "<<":
            op = "shl"
        elif self.op == ">>" and lhs.sign:
            op = "sar"
        else:
            op = "shr"

        ctx.emit(Binary(lhs, rhs, op, res))
        return res
Exemple #6
0
    async def compile(self, ctx: CompileContext) -> Register:
        lhs, rhs = await self.compile_meta(ctx)

        res = ctx.get_register(lhs.size, self.sign)

        if self.op == "*":
            op = "mul"
        elif self.op == "%":
            if self.sign:
                op = "imod"
            else:
                op = "umod"
        elif self.op == "/" and self.sign:
            op = "idiv"
        else:
            op = "udiv"

        ctx.emit(Binary(lhs, rhs, op, res))
        return res