func (v *gen) genFunction(fn *ir.Function) { v.nl() v.emitDirec(".globl %s", fn.Name()) v.emitDirec(".type %s,@function", fn.Name()) v.emitLabel("%s:", fn.Name()) // setup the stack v.emitOp("pushl @ebp") v.emitOp("movl @esp, @ebp") v.emitOp("pusha") v.emitOp("andl $-16, @esp") // align SP to 16-byte boundary alloc := v.target.newAllocator() alloc.allocFunction(fn) v.emitOp("subl $%d, @esp", alloc.stackSize) // actually allocate the stack vars labelNames := make(map[*ir.Block]string) for _, block := range fn.Blocks() { labelNames[block] = v.nextLabelName() } for _, block := range fn.Blocks() { v.genBlock(block, alloc, labelNames) } }
func (v Target) functionParameterStackSize(fn *ir.Function) int { res := 0 for _, par := range fn.Parameters() { res += v.TypeSize(par.Type()) } return res }
func (v *allocator) allocFunction(fn *ir.Function) { switch fn.CallConv() { case ir.CCallConv, ir.X86_StdCallConv: parPos := 8 for _, par := range fn.Parameters() { v.locs[par] = &location{ stackPos: parPos, } bytes := v.target.TypeSize(par.Type()) if bytes%2 == 1 { bytes++ } parPos += bytes } default: panic("x86 target does not support " + fn.CallConv().String()) } for _, block := range fn.Blocks() { for _, instr := range block.Instrs() { if !instr.Type().IsVoid() { v.addValue(instr) } } } }