Exemplo n.º 1
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
Exemplo n.º 2
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
Exemplo n.º 3
0
    async def compile(self, ctx: CompileContext) -> Register:
        my_type = await self.type
        ptr = await self.load_lvalue(ctx)

        if isinstance(my_type, Void):
            raise self.error("Cannot dereference a void pointer.")

        reg = ctx.get_register(my_type.size, my_type.signed)
        ctx.emit(Mov(reg, Dereference(ptr, reg.size)))
        return reg
Exemplo n.º 4
0
 def p_res(i):
     if i.operation is ASMExprType.index_register:
         r = AllocatedRegister(i.size, i.val)
     elif i.operation is ASMExprType.int_immediate:
         r = Immediate(i.val, i.size)
     elif i.operation is ASMExprType.expr_index:
         if i.val not in range(len(expr_registers)):
             raise InternalCompileException(f"Missing expression index for asm instruction {i.val}. regs: {expr_registers}")
         r = expr_registers[i.val].copy()  # make sure to copy the register object
     if i.deref:
         r = Dereference(r, i.size)
     return r
Exemplo n.º 5
0
    async def compile(self, ctx: CompileContext) -> Register:
        ptr: Register = await self.load_lvalue(ctx)
        if ptr.size != Pointer.size:
            ptr0 = ptr.resize(Pointer.size)
            ctx.emit(Resize(ptr, ptr0))
            ptr = ptr0

        # indexes that leave an array type dont dereference
        if isinstance(await self.type, Array):
            return ptr

        my_type = await self.type
        res = ctx.get_register(my_type.size, my_type.signed)
        ctx.emit(Mov(res, Dereference(ptr, res.size)))
        return res
Exemplo n.º 6
0
 async def compile_as_arr_helper(self, ctx: CompileContext, base: Register):
     if isinstance(self.first_elem, ArrayLiteral) and isinstance(
             await self.type, types.Array):
         for i in self.exprs:
             await i.compile_as_arr_helper(ctx, base)
     else:
         elem_type = (await self.type).to
         for i in self.exprs:
             r = await i.compile(ctx)
             if r.size != elem_type.size:
                 r0 = r.resize(elem_type.size, elem_type.signed)
                 ctx.emit(Resize(r, r0))
                 r = r0
             ctx.emit(Mov(Dereference(base, r.size), r))
             ctx.emit(
                 Binary.add(base, Immediate(r.size, types.Pointer.size)))
Exemplo n.º 7
0
    async def compile_as_ref(self, ctx: CompileContext) -> Register:
        """Compile to the array literal and return a reference to the start.

        This function is for when an array of references is the wanted outcome.
        This function will not work on array types.
        """

        if self.var is None:
            self.var = ctx.declare_unique_variable(await self.type)
            self.var.lvalue_is_rvalue = True

        if (isinstance(self.first_elem, ArrayLiteral) and (not isinstance(
            (await self.type).to, types.Pointer))):
            raise self.error(
                "Cannot compile to references if internal array type is an array and not a pointer"
            )

        base = ctx.get_register(types.Pointer.size)
        index = ctx.get_register(types.Pointer.size)

        ctx.emit(LoadVar(self.var, base))
        ctx.emit(Mov(index, base))

        elem_type = (await self.type).to

        for i in self.exprs:
            r = await i.compile(ctx)

            if r.size != elem_type.size:
                r0 = r.resize(elem_type.size, elem_type.signed)
                ctx.emit(Resize(r, r0))
                r = r0

            ctx.emit(Mov(Dereference(index, r.size), r))
            ctx.emit(Binary.add(index, Immediate(r.size, types.Pointer.size)))

        if self.float_size:
            # fill in missing values
            ctx.emit(
                Binary.add(
                    index,
                    Immediate(elem_type.size * self.float_size, index.size)))

        return base
Exemplo n.º 8
0
    async def compile(self, ctx: CompileContext) -> Register:
        rhs: Register = (await self.right.compile(ctx))
        lhs: Register = (await self.left.load_lvalue(ctx))

        lhs_type = await self.left.type
        rhs_type = await self.right.type
        lhs_sign = lhs_type.signed
        lhs_size = lhs_type.size

        if not rhs_type.implicitly_casts_to(lhs_type):
            raise self.right.error(f"Incompatible rhs type '{rhs_type}' assignment to type '{lhs_type}'")

        if lhs_type.const:
            raise self.error("cannot assign to const type.")

        if lhs_size != rhs.size:
            rhs_ = rhs.resize(lhs_size, lhs_sign)
            ctx.emit(Resize(rhs, rhs_))
            rhs = rhs_
        ctx.emit(Mov(Dereference(lhs, rhs.size), rhs))
        return rhs