Exemplo n.º 1
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        regs = []

        result = get_reg([spotmap[self.output]],
                         [spotmap[self.arg1], spotmap[self.arg2]])
        regs.append(result)

        out_size = self.output.ctype.size
        eq_val_spot = LiteralSpot(1)
        asm_code.add(asm_cmds.Mov(result, eq_val_spot, out_size))

        arg1_spot, arg2_spot = self.fix_both_literal_or_mem(
            spotmap[self.arg1], spotmap[self.arg2], regs, get_reg, asm_code)
        arg1_spot, arg2_spot = self.fix_literal_wrong_order(
            arg1_spot, arg2_spot)

        arg_size = self.arg1.ctype.size
        neq_val_spot = LiteralSpot(0)
        label = asm_code.get_label()

        asm_code.add(asm_cmds.Cmp(arg1_spot, arg2_spot, arg_size))
        asm_code.add(self.cmp_command()(label))
        asm_code.add(asm_cmds.Mov(result, neq_val_spot, out_size))
        asm_code.add(asm_cmds.Label(label))

        if result != spotmap[self.output]:
            asm_code.add(asm_cmds.Mov(spotmap[self.output], result, out_size))
Exemplo n.º 2
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        if self.output.ctype == ctypes.bool_t:
            return self.set_bool(spotmap, get_reg, asm_code)

        elif isinstance(spotmap[self.arg], LiteralSpot):
            out_spot = spotmap[self.output]
            arg_spot = spotmap[self.arg]
            size = self.output.ctype.size
            asm_code.add(asm_cmds.Mov(out_spot, arg_spot, size))

        elif self.output.ctype.size <= self.arg.ctype.size:
            if spotmap[self.output] == spotmap[self.arg]:
                return

            if isinstance(spotmap[self.output], RegSpot): r = spotmap[self.output]
            elif isinstance(spotmap[self.arg], RegSpot): r = spotmap[self.arg]
            else: r = get_reg()

            self.move_data(spotmap[self.output], spotmap[self.arg], self.output.ctype.size, r, asm_code)

        else:
            r = get_reg([spotmap[self.output], spotmap[self.arg]])

            # Move from arg_asm -> r_asm
            if self.arg.ctype.signed:
                asm_code.add(asm_cmds.Movsx(r, spotmap[self.arg], self.output.ctype.size, self.arg.ctype.size))
            elif self.arg.ctype.size == 4:
                asm_code.add(asm_cmds.Mov(r, spotmap[self.arg], 4))
            else:
                asm_code.add(asm_cmds.Movzx(r, spotmap[self.arg], self.output.ctype.size, self.arg.ctype.size))

            # If necessary, move from r_asm -> output_asm
            if r != spotmap[self.output]: asm_code.add(asm_cmds.Mov(spotmap[self.output], r, self.output.ctype.size))
Exemplo n.º 3
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        global DIRECT_VAL

        func_spot = spotmap[self.func]

        func_size = self.func.ctype.size
        ret_size = self.func.ctype.arg.ret.size

        # Check if function pointer spot will be clobbered by moving the arguments into the correct registers.
        if spotmap[self.func] in self.arg_regs[0:len(self.args)]:
            # Get a register which isn't one of the unallowed registers.
            r = get_reg([], self.arg_regs[0:len(self.args)])
            asm_code.add(asm_cmds.Mov(r, spotmap[self.func], func_size))
            func_spot = r

        for arg, reg in zip(self.args, self.arg_regs):
            if spotmap[arg] == reg: continue
            asm_code.add(asm_cmds.Mov(reg, spotmap[arg], arg.ctype.size))

        if len(STR_EX) > 1:
            DIRECT_VAL.append(spots.LiteralSpot('_ret' +
                                                str(Call.counter - 1)))
        asm_code.add(asm_cmds.Call(func_spot, None, self.func.ctype.size))
        if len(STR_EX) > 1:
            asm_code.add(
                asm_cmds.Mov(DIRECT_VAL[Call.counter], func_spot,
                             self.func.ctype.size))
            Call.counter += 1

        if not self.void_return and spotmap[self.ret] != spots.EAX:
            asm_code.add(asm_cmds.Mov(spotmap[self.ret], spots.EAX, ret_size))
Exemplo n.º 4
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        arg1_spot = spotmap[self.arg1]
        arg1_size = self.arg1.ctype.size
        arg2_spot = spotmap[self.arg2]
        arg2_size = self.arg2.ctype.size

        if not self.is_immediate8(arg2_spot) and arg2_spot != spots.ECX:
            if arg1_spot == spots.ECX:
                out_spot = spotmap[self.output]
                temp_spot = get_reg([out_spot, arg1_spot],
                                    [arg2_spot, spots.ECX])
                asm_code.add(asm_cmds.Mov(temp_spot, arg1_spot, arg1_size))
                arg1_spot = temp_spot
            asm_code.add(asm_cmds.Mov(spots.ECX, arg2_spot, arg2_size))
            arg2_spot = spots.ECX

        if spotmap[self.output] == arg1_spot:
            asm_code.add(self.Inst(arg1_spot, arg2_spot, arg1_size, 1))
        else:
            out_spot = spotmap[self.output]
            temp_spot = get_reg([out_spot, arg1_spot], [arg2_spot])
            if arg1_spot != temp_spot:
                asm_code.add(asm_cmds.Mov(temp_spot, arg1_spot, arg1_size))
            asm_code.add(self.Inst(temp_spot, arg2_spot, arg1_size, 1))
            if temp_spot != out_spot:
                asm_code.add(asm_cmds.Mov(out_spot, temp_spot, arg1_size))
Exemplo n.º 5
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        if self.arg and spotmap[self.arg] != spots.EAX:
            size = self.arg.ctype.size
            asm_code.add(asm_cmds.Mov(spots.EAX, spotmap[self.arg], size))

        asm_code.add(asm_cmds.Mov(spots.ESP, spots.EBP, 8))
        asm_code.add(asm_cmds.Pop(spots.EBP, None, 8))
        asm_code.add(asm_cmds.Ret())
Exemplo n.º 6
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        r = get_reg([spotmap[self.output]])
        asm_code.add(asm_cmds.Lea(r, home_spots[self.var]))

        if r != spotmap[self.output]:
            size = self.output.ctype.size
            asm_code.add(asm_cmds.Mov(spotmap[self.output], r, size))
Exemplo n.º 7
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        size = self.arg.ctype.size

        output_spot = spotmap[self.output]
        arg_spot = spotmap[self.arg]

        if output_spot != arg_spot:
            asm_code.add(asm_cmds.Mov(output_spot, arg_spot, size))
        asm_code.add(self.Inst(output_spot, None, size))
Exemplo n.º 8
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        if not isinstance(spotmap[self.base], MemSpot):
            raise NotImplementedError("expected base in memory spot")

        rel_spot = self.get_rel_spot(spotmap, get_reg, asm_code)
        out_spot = self.get_reg_spot(self.output, spotmap, get_reg)
        asm_code.add(asm_cmds.Lea(out_spot, rel_spot))

        if out_spot != spotmap[self.output]: asm_code.add(asm_cmds.Mov(spotmap[self.output], out_spot, 8))
Exemplo n.º 9
0
    def move_data(self, target_spot, start_spot, size, reg, asm_code):
        """Emits code to move data from start to target.

        Given a target spot, start spot, size of data to move, and a register that can be clobbered in the move, this
        function emits code to move all the data. It is efficient whether the input spots are registers or memory, and
        in particular this function works even if the input size is not in {1, 2, 4, 8}.
        """
        # number of mov operations emitted for struct copying.
        shift = 0
        while shift < size:
            reg_size = self.reg_size(size - shift)
            start_spot = start_spot.shift(shift)
            target_spot = target_spot.shift(shift)

            if isinstance(start_spot, LiteralSpot): reg = start_spot
            elif reg != start_spot: asm_code.add(asm_cmds.Mov(reg, start_spot, reg_size))

            if reg != target_spot: asm_code.add(asm_cmds.Mov(target_spot, reg, reg_size))

            shift += reg_size
Exemplo n.º 10
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        ctype = self.arg1.ctype
        size = ctype.size

        output_spot = spotmap[self.output]
        arg1_spot = spotmap[self.arg1]
        arg2_spot = spotmap[self.arg2]

        # Move first operand into RAX if we can do so without clobbering other argument
        moved_to_rax = False
        if spotmap[self.arg1] != spots.EAX and spotmap[self.arg2] != spots.EAX:
            moved_to_rax = True
            asm_code.add(asm_cmds.Mov(spots.EAX, arg1_spot, size))

        # If the divisor is a literal or in a bad register, we must move it to a register.
        if self.is_immediate(spotmap[self.arg2]) or spotmap[self.arg2] in [
                spots.EAX, spots.EDX
        ]:
            r = get_reg([], [spots.EAX, spots.EDX])
            asm_code.add(asm_cmds.Mov(r, arg2_spot, size))
            arg2_final_spot = r
        else:
            arg2_final_spot = arg2_spot

        # If we did not move to RAX above, do so here.
        if not moved_to_rax and arg1_spot != self.return_reg:
            asm_code.add(asm_cmds.Mov(spots.EAX, arg1_spot, size))

        if ctype.signed:
            if ctype.size == 4: asm_code.add(asm_cmds.Cdq())
            elif ctype.size == 8: asm_code.add(asm_cmds.Cqo())
            asm_code.add(asm_cmds.Idiv(arg2_final_spot, None, size))
        else:
            # zero out RDX register
            asm_code.add(asm_cmds.Xor(spots.EDX, spots.EDX, size))
            asm_code.add(asm_cmds.Div(arg2_final_spot, None, size))

        if spotmap[self.output] != self.return_reg:
            asm_code.add(asm_cmds.Mov(output_spot, self.return_reg, size))
Exemplo n.º 11
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        size = self.cond.ctype.size

        if isinstance(spotmap[self.cond], LiteralSpot):
            r = get_reg()
            asm_code.add(asm_cmds.Mov(r, spotmap[self.cond], size))
            cond_spot = r
        else:
            cond_spot = spotmap[self.cond]

        zero_spot = LiteralSpot("0")
        asm_code.add(asm_cmds.Cmp(cond_spot, zero_spot, size))
        asm_code.add(self.command(self.label))
Exemplo n.º 12
0
    def set_bool(self, spotmap, get_reg, asm_code):
        """Emit code for SET command if arg is boolean type."""

        # If arg_asm is a LITERAL, move to register.
        if isinstance(spotmap[self.arg], LiteralSpot):
            r = get_reg([], [spotmap[self.output]])
            asm_code.add(asm_cmds.Mov(r, spotmap[self.arg], self.arg.ctype.size))
            arg_spot = r
        else:
            arg_spot = spotmap[self.arg]

        label = asm_code.get_label()
        output_spot = spotmap[self.output]

        zero = LiteralSpot("0")
        one = LiteralSpot("1")

        asm_code.add(asm_cmds.Mov(output_spot, zero, self.output.ctype.size))
        asm_code.add(asm_cmds.Cmp(arg_spot, zero, self.arg.ctype.size))
        asm_code.add(asm_cmds.Je(label))
        asm_code.add(asm_cmds.Mov(output_spot, one, self.output.ctype.size))
        asm_code.add(asm_cmds.Label(label))
Exemplo n.º 13
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        """ Make the ASM for ADD, MULT, and SUB """
        ctype = self.arg1.ctype
        size = ctype.size

        arg1_spot = spotmap[self.arg1]
        arg2_spot = spotmap[self.arg2]

        # Get temp register for computation.
        temp = get_reg([spotmap[self.output], arg1_spot, arg2_spot])

        if temp == arg1_spot:
            asm_code.add(self.Inst(temp, arg2_spot, size))
        elif temp == arg2_spot:
            asm_code.add(self.Inst(temp, arg1_spot, size))
            if not self.comm: asm_code.add(asm_cmds.Neg(temp, None, size))

        else:
            asm_code.add(asm_cmds.Mov(temp, arg1_spot, size))
            asm_code.add(self.Inst(temp, arg2_spot, size))

        if temp != spotmap[self.output]:
            asm_code.add(asm_cmds.Mov(spotmap[self.output], temp, size))
Exemplo n.º 14
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        addr_spot = spotmap[self.addr]
        output_spot = spotmap[self.output]

        if isinstance(addr_spot, RegSpot): addr_r = addr_spot
        else:
            addr_r = get_reg([], [output_spot])
            asm_code.add(asm_cmds.Mov(addr_r, addr_spot, 8))

        indir_spot = MemSpot(addr_r)
        if isinstance(output_spot, RegSpot): temp_reg = output_spot
        else: temp_reg = get_reg([], [addr_r])

        self.move_data(output_spot, indir_spot, self.output.ctype.size, temp_reg, asm_code)
Exemplo n.º 15
0
    def make_asm(self, spotmap, home_spots, get_reg, asm_code):
        addr_spot = spotmap[self.addr]
        value_spot = spotmap[self.val]

        if isinstance(addr_spot, RegSpot):
            addr_r = addr_spot
        else:
            addr_r = get_reg([], [value_spot])
            asm_code.add(asm_cmds.Mov(addr_r, addr_spot, 8))

        indirect_spot = MemSpot(addr_r)
        if isinstance(value_spot, RegSpot): temp_reg = value_spot
        else: temp_reg = get_reg([], [addr_r])

        self.move_data(indirect_spot, value_spot, self.val.ctype.size, temp_reg, asm_code)
Exemplo n.º 16
0
    def fix_both_literal_or_mem(self, arg1_spot, arg2_spot, regs, get_reg,
                                asm_code):
        """ Fix arguments if both are literal or memory. Adds any called registers to given regs list. Returns tuple
        where first element is new spot of arg1 and second element is new spot of arg2.
        """
        if ((isinstance(arg1_spot, LiteralSpot)
             and isinstance(arg2_spot, LiteralSpot))
                or (isinstance(arg1_spot, MemSpot)
                    and isinstance(arg2_spot, MemSpot))):

            r = get_reg([], regs)
            regs.append(r)
            asm_code.add(asm_cmds.Mov(r, arg1_spot, self.arg1.ctype.size))
            return r, arg2_spot
        else:
            return arg1_spot, arg2_spot
Exemplo n.º 17
0
    def get_rel_spot(self, spotmap, get_reg, asm_code):
        """Get a relative spot for the relative value."""

        # If there's no count, we only need to shift by the chunk
        if not self.count:
            return spotmap[self.base].shift(self.block)

        if isinstance(spotmap[self.count], LiteralSpot) or isinstance(spotmap[self.count], RegSpot):
            return spotmap[self.base].shift(self.block, spotmap[self.count])

        # Otherwise, move count to a register.
        r = get_reg([], [spotmap[self.val]] + self.used_regs)
        self.used_regs.append(r)

        count_size = self.count.ctype.size
        asm_code.add(asm_cmds.Mov(r, spotmap[self.count], count_size))

        return spotmap[self.base].shift(self.block, r)
Exemplo n.º 18
0
    def generate_asm(self, commands, live_vars, spotmap):
        """ Generate assembly code """

        max_offset = max(spot.rbp_offset() for spot in spotmap.values())
        if max_offset % 16 != 0: max_offset += 16 - max_offset % 16

        # Back up ebp and move esp
        self.asm_code.add(asm_cmds.Push(spots.EBP, None, 8))
        self.asm_code.add(asm_cmds.Mov(spots.EBP, spots.ESP, 8))

        offset_spot = LiteralSpot(str(max_offset))
        self.asm_code.add(asm_cmds.Sub(spots.ESP, offset_spot, 8))

        # Generate code for each command
        for i, command in enumerate(commands):
            self.asm_code.add(asm_cmds.Comment(type(command).__name__.upper()))

            def get_reg(pref=None, conf=None):
                if not pref: pref = []
                if not conf: conf = []

                # Spot is bad if it is containing a variable that is live both entering and exiting this command.
                bad_vars = set(live_vars[i][0]) & set(live_vars[i][1])
                bad_spots = set(spotmap[var] for var in bad_vars)

                # Spot is free if it is where an output is stored.
                for v in command.outputs():
                    bad_spots.discard(spotmap[v])

                # Spot is bad if it is listed as a conflicting spot.
                bad_spots |= set(conf)

                for s in (pref + self.all_registers):
                    if isinstance(s, RegSpot) and s not in bad_spots:
                        return s

                raise NotImplementedError("spill required for get_reg")

            command.make_asm(spotmap, spotmap, get_reg, self.asm_code)
Exemplo n.º 19
0
 def make_asm(self, spotmap, home_spots, get_reg, asm_code):
     if spotmap[self.output] == self.arg_reg: return
     else: asm_code.add(asm_cmds.Mov(spotmap[self.output], self.arg_reg, self.output.ctype.size))