Exemplo n.º 1
0
    def FramePush(self, param_count, scope_depth):
        p = param_count
        code = [
            # 0(ebp) == return address
            x.movl(x.ebp, x.mem(x.esp, -(1+p)*4)), #     1
            x.movl(x.esp, x.ebp),
            x.movl(x.ebx, x.mem(x.ebp, -(2+p)*4)),  # 2
            x.movl(x.edi, x.mem(x.ebp, -(3+p)*4)),  # 3
            x.movl(x.esi, x.mem(x.ebp, -(4+p)*4)),  # 4
            x.movl(x.ecx, x.mem(x.ebp, -(5+p)*4)),  # 5
            x.movl(x.edx, x.mem(x.ebp, -(6+p)*4)),  # 6
            x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            x.movl(x.static('display', x.ebx), x.eax),
            x.movl(x.eax, x.mem(x.ebp, -(7+p)*4)), #7


            #x.subl(x.cint(8*4), x.esp),
            #x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            #x.pushl(x.static('display', x.ebx)),
            #x.pushl('$push_msg'),
            #x.call("printf"),
            #x.addl(x.cint(8*4 + 8), x.esp),


            x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            x.movl(x.ebp, x.static('display', x.ebx)),
            '',

        ]
        return code
Exemplo n.º 2
0
 def FramePush(self, param_count, scope_depth):
     """Generate a framepush.
     @param param_count : the number of params the function recieves.
     @param scope_depth : the scope the depth the function was declared at.
     """
     p = param_count
     code = [
         # 0(ebp) == return address
         x.movl(x.ebp, x.mem(x.esp, -(1 + p) * 4)),  #     1
         x.movl(x.esp, x.ebp),
         x.movl(x.ebx, x.mem(x.ebp, -(2 + p) * 4)),  # 2
         x.movl(x.edi, x.mem(x.ebp, -(3 + p) * 4)),  # 3
         x.movl(x.esi, x.mem(x.ebp, -(4 + p) * 4)),  # 4
         x.movl(x.ecx, x.mem(x.ebp, -(5 + p) * 4)),  # 5
         x.movl(x.edx, x.mem(x.ebp, -(6 + p) * 4)),  # 6
         x.movl(x.cint(4 * (scope_depth - 1)), x.ebx),
         x.movl(x.static("display", x.ebx), x.eax),
         x.movl(x.eax, x.mem(x.ebp, -(7 + p) * 4)),  # 7
         # x.subl(x.cint(8*4), x.esp),
         # x.movl(x.cint(4*(scope_depth-1)), x.ebx),
         # x.pushl(x.static('display', x.ebx)),
         # x.pushl('$push_msg'),
         # x.call("printf"),
         # x.addl(x.cint(8*4 + 8), x.esp),
         x.movl(x.cint(4 * (scope_depth - 1)), x.ebx),
         x.movl(x.ebp, x.static("display", x.ebx)),
         "",
     ]
     return code
Exemplo n.º 3
0
 def FramePop(self, param_count, scope_depth):
     """Generate a framepop.
     @param param_count : the number of params the function recieves.
     @param scope_depth : the scope the depth the function was declared at.
     """
     p = param_count
     code = [
         "",
         # x.movl(x.cint(4*(scope_depth-1)), x.ebx),
         # x.pushl(x.static('display', x.ebx)),
         # x.pushl('$pop1_msg'),
         # x.call("printf"),
         # x.addl(x.cint(8), x.esp),
         x.movl(x.cint(4 * (scope_depth - 1)), x.ebx),
         x.movl(x.mem(x.ebp, -(7 + p) * 4), x.eax),
         x.movl(x.eax, x.static("display", x.ebx)),
         # x.movl(x.cint(4*(scope_depth-1)), x.ebx),
         # x.pushl(x.static('display', x.ebx)),
         # x.pushl('$pop2_msg'),
         # x.call("printf"),
         # x.addl(x.cint(8), x.esp),
         x.movl(x.mem(x.ebp, -(6 + p) * 4), x.edx),
         x.movl(x.mem(x.ebp, -(5 + p) * 4), x.ecx),
         x.movl(x.mem(x.ebp, -(4 + p) * 4), x.esi),
         x.movl(x.mem(x.ebp, -(3 + p) * 4), x.edi),
         x.movl(x.mem(x.ebp, -(2 + p) * 4), x.ebx),
         x.movl(x.ebp, x.esp),  # restore stack pointer
         x.movl(x.mem(x.esp, -(1 + p) * 4), x.ebp),  # restore base(frame) pointer
     ]
     return code
Exemplo n.º 4
0
    def FramePop(self, param_count, scope_depth):
        p = param_count
        code = [
            '',
            #x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            #x.pushl(x.static('display', x.ebx)),
            #x.pushl('$pop1_msg'),
            #x.call("printf"),
            #x.addl(x.cint(8), x.esp),

            x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            x.movl(x.mem(x.ebp, -(7+p)*4), x.eax),
            x.movl(x.eax, x.static('display', x.ebx)),

            #x.movl(x.cint(4*(scope_depth-1)), x.ebx),
            #x.pushl(x.static('display', x.ebx)),
            #x.pushl('$pop2_msg'),
            #x.call("printf"),
            #x.addl(x.cint(8), x.esp),

            x.movl(x.mem(x.ebp, -(6+p)*4), x.edx),
            x.movl(x.mem(x.ebp, -(5+p)*4), x.ecx),
            x.movl(x.mem(x.ebp, -(4+p)*4), x.esi),
            x.movl(x.mem(x.ebp, -(3+p)*4), x.edi),
            x.movl(x.mem(x.ebp, -(2+p)*4), x.ebx),
            x.movl(x.ebp, x.esp),                # restore stack pointer
            x.movl(x.mem(x.esp, -(1+p)*4), x.ebp),   # restore base(frame) pointer
        ]
        return code
Exemplo n.º 5
0
 def Print(self, i):
     code = self.emit(x.pushl, i.a)
     code += [
         x.pushl('$printf_msg'),
         x.call("printf"),
         x.addl(x.cint(8), x.esp),
     ]
     return code
Exemplo n.º 6
0
    def emit(self, inst, src, targ=None):
        '''emit the specified instruction with src as source operand and targ
            as the target operand. Handles requesting the operands from a non-local
            stack frame as necessary.

            using ebx or ecx is not allowed for either the src or targ.
        '''
        #print inst, src, targ
        if isinstance(src, il.Symbol) and isinstance(targ, il.Symbol):
            raise Exception, 'Cannot emit an instruction with both source and target as symbols'
        elif isinstance(src, il.Symbol) and targ is None:
            if src.islocal(self.cfunc):
                return [ inst(x.loc(src.type)) ]
            return [
                x.movl(x.cint(4*(src.scope_depth-1)), x.ebx),
                x.movl(x.static('display', x.ebx), x.ebx),
                inst(x.mem(x.ebx, src.type.offset)),
            ]
        elif not isinstance(src, il.Symbol) and targ is None:
            return [ inst(src), ]
        elif isinstance(src, il.Symbol) and targ is not None:
            if src.islocal(self.cfunc):
                return [ inst(x.loc(src.type), targ) ]
            return [
                x.movl(x.cint(4*(src.scope_depth-1)), x.ebx),
                x.movl(x.static('display', x.ebx), x.ebx),
                inst(x.mem(x.ebx, src.type.offset), targ),
            ]
        elif isinstance(targ, il.Symbol):
            #print inst, src, targ, targ.type.basereg
            if targ.islocal(self.cfunc):
                return [ inst(src, x.loc(targ.type)) ]
            return [
                x.movl(x.cint(4*(targ.scope_depth-1)), x.ebx),
                x.movl(x.static('display', x.ebx), x.ebx),
                x.movl(x.mem(x.ebx, targ.type.offset), x.ecx),
                inst(src, x.ecx),
                x.movl(x.ecx, x.mem(x.ebx, targ.type.offset)),
            ]
        else:
            return [ inst(src, targ) ]
Exemplo n.º 7
0
 def Op(self, i):
     # print i
     ops = {il.ADD: x.addl, il.SUB: x.subl, il.MUL: x.imull}
     code = []
     if i.op == il.DIV:
         code += [x.movl(x.cint(0), x.edx)]
         code += self.emit(x.movl, i.a, x.eax)
         code += self.emit(x.divl, i.b)
         code += self.emit(x.movl, x.eax, i.result)
     else:
         code += self.emit(x.movl, i.a, x.eax)
         code += self.emit(ops[i.op], i.b, x.eax)
         code += self.emit(x.movl, x.eax, i.result)
     return code
Exemplo n.º 8
0
 def Return(self, i):
     code = list()
     #if len(self.code) >= 90 and len(self.code) < 110:
         #code = [
             #(vm.IMM,  3, len(self.code), 'DEBUG'),
             #(vm.PRNT, 3, 0, 'DEBUG'),
             #(vm.PRNT, 2, 0, 'DEBUG'),
             #(vm.EXIT, 0, 0, 'DEBUG'),
         #]
     code += [
         x.addl(x.cint(4), x.esp),
         x.jmp(x.mem(x.esp, -4, True)),
         #x.ret(),
     ]
     return code
Exemplo n.º 9
0
    def emit(self, inst, src, targ=None):
        """emit the specified instruction with src as source operand and targ
            as the target operand. Handles requesting the operands from a
            non-local stack frame as necessary.

            using ebx or ecx is not allowed for either the src or targ.
        """

        ## We have several choices to make in order to emit the right inst.
        ## (1) does the inst only refer to symbols local to the current scope?
        ##      (a) if yes: emit the instruction with no changes
        ##      (b) if no: detirmine what changes have to be made.
        ## (2) We now know the instruction is not local. One (but not both) of
        ##     the symbols does not come from this stack frame. That means they
        ##     have to be fetched from the appropriate stack frame. We detirmine
        ##     the appropriate frame to fetch (or put) the sym from(to) by
        ##     consulting the display.
        ## (3) The display is a static array:
        ##
        ##               +------------+------------+------------+------------+
        ##   scope depth | 0          | 1          | 2          | 3          |
        ##               +------------+------------+------------+------------+
        ## frame address | 0x???????? | 0x???????? | 0x???????? | 0x???????? |
        ##               +------------+------------+------------+------------+
        ##
        ##     The 'frame address' contains the address of the the stack frame
        ##     most recently seen function. When that function returns it will
        ##     update the display with the previous address it contained. When
        ##     A new function is called at that scope depth a new address will
        ##     be placed in the display and the old will be saved.
        ##
        ## (4) Therefore to get the non-local symbols we simply need to consult
        ##     the display to find the appropriate frame. Each symbol knows what
        ##     scope-depth it was declared at.
        ##
        ## NB: The symbols store there scope depths starting at 1. Therefore, in
        ##     order to index into the display one must subtract 1 from the
        ##     stored scope depth.
        ##
        ## NB: We multiply by 4 because each address is 4 bytes wide.

        if isinstance(src, il.Symbol) and isinstance(targ, il.Symbol):
            raise Exception, ("Cannot emit an instruction with both source and target as " "symbols")
        elif isinstance(src, il.Symbol) and targ is None:
            if src.islocal(self.cfunc):
                return [inst(x.loc(src.type))]
            return [
                x.movl(x.cint(4 * (src.scope_depth - 1)), x.ebx),  # compute the
                # index into the
                # display and
                # store in ebx
                x.movl(x.static("display", x.ebx), x.ebx),  # get the non-
                # local stack
                # pointer and
                # store in ebx
                inst(x.mem(x.ebx, src.type.offset)),  # emit the inst.
            ]
        elif not isinstance(src, il.Symbol) and targ is None:
            return [inst(src)]
        elif isinstance(src, il.Symbol) and targ is not None:
            if src.islocal(self.cfunc):
                return [inst(x.loc(src.type), targ)]
            return [
                x.movl(x.cint(4 * (src.scope_depth - 1)), x.ebx),
                x.movl(x.static("display", x.ebx), x.ebx),
                inst(x.mem(x.ebx, src.type.offset), targ),
            ]
        elif isinstance(targ, il.Symbol):
            # print inst, src, targ, targ.type.basereg
            if targ.islocal(self.cfunc):
                return [inst(src, x.loc(targ.type))]
            return [
                ## This version is slightly tricky we have to fetch and store
                ## the contents of the variable stored in the non-local stack
                ## frame.
                x.movl(x.cint(4 * (targ.scope_depth - 1)), x.ebx),
                x.movl(x.static("display", x.ebx), x.ebx),
                x.movl(x.mem(x.ebx, targ.type.offset), x.ecx),
                inst(src, x.ecx),
                x.movl(x.ecx, x.mem(x.ebx, targ.type.offset)),
            ]
        else:
            return [inst(src, targ)]
Exemplo n.º 10
0
 def Imm(self, i):
     code = self.emit(x.movl, x.cint(i.a), i.result)
     return code
Exemplo n.º 11
0
 def Return(self, i):
     """Generate code to return from the current function"""
     return [x.addl(x.cint(4), x.esp), x.jmp(x.mem(x.esp, -4, True))]
Exemplo n.º 12
0
    def Func(self, name, main=False):
        """Generates x86 code for the function given by name. This is the entry
        point for all code generation."""

        ## Get the function.
        func = self.functions[name]
        self.cfunc = func

        ## Generate a label for the function
        self.code += [x.label(name)]

        ## If this is not the `main` function generate a stack push
        if not main:
            self.code += self.FramePush(len(func.params), func.scope_depth)

        ## Move the stack pointer down. This creates the stack frame.
        syms = self.gather_syms(func.blks)
        sp_offset = self.place_symbols(syms, func)
        self.code += [x.subl(x.cint(sp_offset * 4), x.esp)]

        def block(insts):
            """Generate the x86 instruction for the given block of instructions.
            """

            ## We could do something more clever than switch case here, but I
            ## (for now) perfer the simplicity.
            for i in insts:
                if i.op == il.PRNT:
                    self.code += self.Print(i)
                elif i.op == il.IMM:
                    self.code += self.Imm(i)
                elif i.op == il.GPRM:
                    self.code += self.Gprm(i)
                elif i.op == il.IPRM:
                    self.code += self.Iprm(i)
                elif i.op == il.OPRM:
                    ## OPRMs always appear directly before RTRN instructions.
                    ## Based on the way the stack frame pop is generated the pop
                    ## must be generated before the OPRM instruction. So the
                    ## output params can be properly returned.
                    if not main and func.oparam_count > 0:
                        self.code += self.FramePop(len(func.params), func.scope_depth)
                    if func.oparam_count == 0:
                        raise Exception, "expected no return paramters got at least 1."
                    self.code += self.Oprm(i)
                elif i.op == il.RPRM:
                    self.code += self.Rprm(i)
                elif i.op == il.CALL:
                    self.code += self.Call(i)
                elif i.op == il.RTRN:
                    if not main and func.oparam_count == 0:
                        self.code += self.FramePop(len(func.params), func.scope_depth)
                    self.code += self.Return(i)
                elif i.op == il.MV:
                    self.code += self.Mv(i)
                elif i.op in [il.ADD, il.SUB, il.MUL, il.DIV]:
                    self.code += self.Op(i)
                elif i.op in [il.IFEQ, il.IFNE, il.IFLT, il.IFLE, il.IFGT, il.IFGE]:
                    self.code += self.BranchOp(i)
                elif i.op == il.J:
                    self.code += self.J(i)
                elif i.op == il.NOP:
                    self.code += self.Nop(i)
                else:
                    raise Exception, il.opsr[i.op]

        ## generate a label for the entry block of the function.
        self.code += [x.label(func.entry.name)]
        block(self.blocks[func.entry.name].insts)  # generate the function.

        ## for each block in the function (excluding entry and exit) generate
        ## the code.
        for b in func.blks:
            if b.name == func.entry.name:
                continue
            if b.name == func.exit.name:
                continue
            self.code += [x.label(b.name)]
            self.code += [x.nop()]
            block(self.blocks[b.name].insts)

        ## If there a distinct exit block, generate it.
        if func.entry.name != func.exit.name:
            self.code += [x.label(func.exit.name)]
            b = func.exit
            self.code += [x.nop()]
            block(self.blocks[b.name].insts)
Exemplo n.º 13
0
    def Func(self, name, main=False):
        #print name
        self.code += [
            x.label(name)
        ]

        #print '->', insts
        func = self.functions[name]
        self.cfunc = func
        #insts = self.blocks[func.entry.name].insts

        self.bp_offset = 3

        if not main:
            self.code += self.FramePush(len(func.params), func.scope_depth)
        syms = self.gather_syms(func.blks)
        #print syms
        fp_offset = self.place_symbols(syms, func)
        #print name, 'fp_offset', fp_offset
        self.code += [
            x.subl(x.cint(fp_offset*4), x.esp)
            #(vm.IMM, 4, fp_offset, 'start func %s' % (name)),
            #(vm.ADD, 1, 4, 'fp offset add inst'),
        ]

        def block(insts):
            for i in insts:
                if i.op == il.PRNT:
                    self.code += self.Print(i)
                elif i.op == il.IMM:
                    self.code += self.Imm(i)
                elif i.op == il.GPRM:
                    self.code += self.Gprm(i)
                elif i.op == il.IPRM:
                    self.code += self.Iprm(i)
                elif i.op == il.OPRM:
                    if not main and func.oparam_count > 0:
                        self.code += self.FramePop(len(func.params), func.scope_depth)
                    if func.oparam_count == 0:
                        raise Exception, "expected no return paramters got at least 1."
                    self.code += self.Oprm(i)
                elif i.op == il.RPRM:
                    self.code += self.Rprm(i)
                elif i.op == il.CALL:
                    self.code += self.Call(i)
                elif i.op == il.RTRN:
                    if not main and func.oparam_count == 0:
                        self.code += self.FramePop(len(func.params), func.scope_depth)
                    self.code += self.Return(i)
                elif i.op == il.MV:
                    self.code += self.Mv(i)
                elif i.op in [il.ADD, il.SUB, il.MUL, il.DIV]:
                    self.code += self.Op(i)
                elif i.op in [il.IFEQ, il.IFNE, il.IFLT, il.IFLE, il.IFGT, il.IFGE]:
                    self.code += self.BranchOp(i)
                elif i.op == il.J:
                    self.code += self.J(i)
                elif i.op == il.NOP:
                    self.code += self.Nop(i)
                else:
                    raise Exception, il.opsr[i.op]
                #if i.label is not None:
                    #print code[l]
                    #code[l] = (code[l][0], code[l][1], code[l][2], i.label)
        self.code += [ x.label(func.entry.name) ]
        block(self.blocks[func.entry.name].insts)
        for b in func.blks:
            if b.name == func.entry.name: continue
            if b.name == func.exit.name: continue
            self.code += [ x.label(b.name) ]
            self.floc[b.name] = len(self.code)
            self.code += [ x.nop() ]
            block(self.blocks[b.name].insts)
        if func.entry.name != func.exit.name:
            self.code += [ x.label(func.exit.name) ]
            b = func.exit
            self.floc[b.name] = len(self.code)
            self.code += [ x.nop() ]
            block(self.blocks[b.name].insts)