Exemple #1
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)
Exemple #2
0
 def Nop(self, i):
     code = [x.nop()]
     return code
Exemple #3
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)