コード例 #1
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    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
コード例 #2
0
    async def compile_as_arr(self, ctx: CompileContext) -> Register:
        """Compile an array literal but inline the inner values."""

        if (isinstance((await self.type).to, types.Array)
                and (not isinstance(self.first_elem, ArrayLiteral))):
            # Maybe just cast the internal type to a pointer.
            raise self.error(
                "Internal type is of array type but is not a literal.")

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

        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_size = (await self.type).to.size

        for i in self.exprs:
            await i.compile_as_arr_helper(ctx, index)

        # NOTE: will we ever hit this?
        if self.float_size:
            ctx.emit(Binary.add(index, Immediate(elem_size * self.float_size)))

        return base
コード例 #3
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    async def compile(self, ctx: CompileContext) -> Register:

        lhs_type, rhs_type = await self.left.type, await self.right.type

        if not rhs_type.implicitly_casts_to(lhs_type):
            raise self.error(
                f"Right argument to boolean operator: '{self.right.matched_region}'\n"
                f"of type: {rhs_type} cannot be casted to left argument: '{self.left.matched_region}'\n"
                f"of type {lhs_type}")

        if isinstance(lhs_type, Void):
            raise self.left.error("Void type argument to boolean operator")
        if isinstance(rhs_type, Void):
            raise self.right.error("Void type argument to boolean operator")

        r1: Register = await self.left.compile(ctx)
        ctx.emit(Compare(r1, Immediate(0, r1.size)))
        target = JumpTarget()
        op = {'or': CompType.neq, 'and': CompType.eq}[self.op]

        cond = ctx.get_register(1)
        ctx.emit(SetCmp(cond, op))

        ctx.emit(Jump(target, cond))
        r2: Register = (await self.right.compile(ctx))
        if r2.size != r1.size:
            r2_ = r2.resize(r1.size, r1.sign)
            ctx.emit(Resize(r2, r2_))
            r2 = r2_
        ctx.emit(Mov(r1, r2))
        ctx.emit(target)
        return r1
コード例 #4
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    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
コード例 #5
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
コード例 #6
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    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
コード例 #7
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    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
コード例 #8
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)))
コード例 #9
0
ファイル: operations.py プロジェクト: simmsb/A-Compiler
    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
コード例 #10
0
 async def compile(self, ctx: CompileContext) -> Register:
     reg = ctx.get_register(self._type.size, self._type.signed)
     ctx.emit(Mov(reg, Immediate(self.lit, self._type.size)))
     return reg