func (v *allocator) allocate(fn *ssa.Function) { for _, par := range fn.Parameters() { v.allocateValue(par) } for _, block := range fn.Blocks() { for _, instr := range block.Instrs() { if val, ok := instr.(ssa.Value); ok { v.allocateValue(val) } } } }
func (v *Target) genFunction(fn *ssa.Function) { if fn.IsPrototype() { return } allocator := newAllocator() allocator.allocate(fn) blockLabelMap := make(map[*ssa.Block]string) for _, block := range fn.Blocks() { blockLabelMap[block] = v.nextLabelName() } v.wnl() v.wop(".globl %s", fn.Name()) v.wop(".align 16, 0x90") // pad with NOPs if v.Platform.IsUnixLike() { v.wop(".type %s,@function", fn.Name()) } v.wlabel(fn.Name()) v.wop("pushq #rbp") v.wop("pushq #rbx") v.wop("pushq #r15") v.wop("movq #rsp, #rbp") v.wop("subq $%d, #rsp", (allocator.stackSize|0xF)+1) retType := fn.Type().(*types.Signature).ReturnType() if sysVClassifyType(retType)[0] == sysVClassMEMORY { v.wop("movq #rdi, #r15") } else if winIsMemory(retType) { v.wop("movq #rdx, #r15") } v.genSaveFunctionParameters(allocator, fn) for _, block := range fn.Blocks() { v.wlabel(blockLabelMap[block]) for _, instr := range block.Instrs() { v.genInstr(allocator, instr, blockLabelMap) } } }
func (v *CFG) construct(fn *ssa.Function) { blocks := fn.Blocks() nodes := make([]*CFGNode, len(blocks)) blocksToNodes := make(map[*ssa.Block]*CFGNode) for i, block := range blocks { nodes[i] = &CFGNode{ block: block, } blocksToNodes[block] = nodes[i] } for _, node := range nodes { switch term := node.block.LastInstr().(type) { case *ssa.Br: ops := ssa.GetOperands(term) node.next = []*CFGNode{ blocksToNodes[ops[0].(*ssa.Block)], } case *ssa.CondBr: ops := ssa.GetOperands(term) node.next = []*CFGNode{ blocksToNodes[ops[1].(*ssa.Block)], blocksToNodes[ops[2].(*ssa.Block)], } case *ssa.Unreachable, *ssa.Ret: // these lead to nowhere default: panic("unimplemented terminating instruction") } for _, next := range node.next { next.prev = append(next.prev, node) } } v.nodes = nodes }