func (v Target) genInstr(a *allocator, instr ssa.Instruction, blockLabelMap map[*ssa.Block]string) { v.wstring("#" + instr.String() + "\n") switch instr := instr.(type) { case *ssa.Ret: v.genRet(a, instr) case *ssa.BinOp: v.genBinOp(a, instr) case *ssa.ICmp: v.genICmp(a, instr) case *ssa.Br: v.genBr(a, instr, blockLabelMap) case *ssa.CondBr: v.genCondBr(a, instr, blockLabelMap) case *ssa.Call: v.genCall(a, instr) case *ssa.Convert: v.genConvert(a, instr) case *ssa.GEP: v.genGEP(a, instr) case *ssa.Load: v.genLoad(a, instr) case *ssa.Alloc: v.genAlloc(a, instr) case *ssa.Store: v.genStore(a, instr) case *ssa.Phi: // do nothing case *ssa.Unreachable: v.wop("hlt") default: panic("unim") } }
func checkInstr(instr ssa.Instruction, blockDomTree *analysis.DominatorTree) error { thisBlockNode := blockDomTree.NodeForBlock(instr.Block()) if _, ok := instr.(*ssa.Phi); !ok { for _, op := range ssa.GetOperands(instr) { if opInstr, ok := op.(ssa.Instruction); ok { opInstrBlock := opInstr.Block() if thisBlockNode.DominatedBy(blockDomTree.NodeForBlock(opInstrBlock), true) { continue } else if opInstrBlock == instr.Block() { if opInstrBlock.InstrIndex(opInstr) < opInstrBlock.InstrIndex(instr) { continue } } return &InstrError{ Instr: instr, Message: "Instruction is not dominated by operand `" + ssa.ValueString(op) + "`", } } } } switch i := instr.(type) { case *ssa.BinOp: return checkBinOp(i) case *ssa.Load: return checkLoad(i) case *ssa.Call: return checkCall(i) case *ssa.Alloc: return checkAlloc(i) case *ssa.Store: return checkStore(i) case *ssa.Convert: return checkConvert(i) case *ssa.ICmp: return checkICmp(i) case *ssa.CondBr: return checkCondBr(i) case *ssa.Br: return checkBr(i) case *ssa.Phi: return checkPhi(i, blockDomTree) case *ssa.Ret: return checkRet(i) case *ssa.GEP: return checkGEP(i) case *ssa.Unreachable: // do nothing default: panic("unim") } return nil }