def InitCode(self): """The pre-amble to the generated code. Contains data and the _start label. Creates a new stack frame.""" return [ ".section .data", "printf_msg:", r' .ascii "%d\n\0"', ## START DEBUG MESSAGES ## "push_msg:", r' .ascii "push 0x%x\n\0"', "pop1_msg:", r' .ascii "pop1 0x%x\n\0"', "pop2_msg:", r' .ascii "pop2 0x%x\n\0"', ## END DEBUG MESSAGES ## ## The display stores the location of non-local stack frames ## see. def emit(...) "display:", r" .long %s" % ", ".join("0" for x in xrange(self.table.max_depth)), "", ".section .text", ".global _start", x.label("_start"), x.movl(x.esp, x.ebp), x.movl(x.ebp, "0(%ebp)"), #'.global main', # x86.label('main'), ]
def InitCode(self): return [ '.section .data', 'printf_msg:', r' .ascii "%d\n\0"', 'push_msg:', r' .ascii "push 0x%x\n\0"', 'pop1_msg:', r' .ascii "pop1 0x%x\n\0"', 'pop2_msg:', r' .ascii "pop2 0x%x\n\0"', 'display:', r' .long %s' % ', '.join('0' for x in xrange(self.table.max_depth)), '', '.section .text', '.global _start', x.label('_start'), x.movl(x.esp, x.ebp), x.movl(x.ebp, '0(%ebp)'), #'.global main', #x86.label('main'), ]
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)
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)