// loopDetectBounds detects static bounds (or set as dynamic bounds) from based // on loop state machine. func loopDetectBounds(instr *ssa.Phi, infer *TypeInfer, ctx *Context) { switch ctx.L.State { case Enter: switch ctx.L.Bound { case Unknown: phiSelectEdge(instr, infer, ctx) loopSetIndex(instr, infer, ctx) case Static: switch ctx.L.Bound { case Static: phiSelectEdge(instr, infer, ctx) if instr == ctx.L.IndexVar { ctx.L.Next() infer.Logger.Printf(ctx.F.Sprintf(LoopSymbol+"Increment %s by %s to %s", ctx.L.IndexVar.Name(), fmtLoopHL(ctx.L.Step), fmtLoopHL(ctx.L.Index))) } default: visitSkip(instr, infer, ctx) } case Dynamic: phiSelectEdge(instr, infer, ctx) infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"(dynamic bound) %s", instr.String())) } default: phiSelectEdge(instr, infer, ctx) } }
func visitPhi(inst *ssa.Phi, fr *frame) { // In the case of channels, find the last defined channel and replace it. if _, ok := inst.Type().(*types.Chan); ok { //preds := inst.Block().Preds // PredBlocks: order is significant. fr.locals[inst], _ = fr.get(inst.Edges[0]) fr.phi[inst] = inst.Edges } }
func (f *Function) Phi(phi *ssa.Phi) (string, *Error) { if ident := f.Ident(phi); ident == nil { return ErrorMsg("Error in ssa.Phi allocation") } asm := fmt.Sprintf("// BEGIN ssa.Phi, name (%v), comment (%v), value (%v)\n", phi.Name(), phi.Comment, phi) asm += fmt.Sprintf("// END ssa.Phi, %v\n", phi) return asm, nil }
func visitPhi(instr *ssa.Phi, infer *TypeInfer, ctx *Context) { loopDetectBounds(instr, infer, ctx) if _, ok := instr.Type().(*types.Chan); ok { // Replace existing non-edge extra args with the same name. for _, e := range instr.Edges { EALOOP: for i, ea := range ctx.F.extraargs { if e.Name() == ea.Name() { ctx.F.extraargs = append(ctx.F.extraargs[:i], ctx.F.extraargs[i+1:]...) break EALOOP } } } ctx.F.extraargs = append(ctx.F.extraargs, instr) } }
func (f *Function) computePhiInstr(phi *ssa.Phi) *Error { blockIndex := phi.Block().Index for i, edge := range phi.Edges { edgeBlock := -1 if phi.Block() != nil && i < len(phi.Block().Preds) { edgeBlock = phi.Block().Preds[i].Index } if edgeBlock == -1 { ice("malformed CFG") } if _, ok := f.phiInfo[edgeBlock]; !ok { f.phiInfo[edgeBlock] = make(map[int][]phiInfo) } f.phiInfo[edgeBlock][blockIndex] = append(f.phiInfo[edgeBlock][blockIndex], phiInfo{value: edge, phi: phi}) } return nil }
// phiSelectEdge selects edge based on predecessor block and returns the edge index. func phiSelectEdge(instr *ssa.Phi, infer *TypeInfer, ctx *Context) (edge int) { for i, pred := range instr.Block().Preds { if pred.Index == ctx.B.Pred { e, ok := ctx.F.locals[instr.Edges[i]] if !ok { switch t := instr.Edges[i].(type) { case *ssa.Const: ctx.F.locals[instr.Edges[i]] = &Const{t} e, edge = ctx.F.locals[instr.Edges[i]], pred.Index infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"%s/%s = %s, selected const from block %d", instr.Name(), e, instr.String(), edge)) case *ssa.Function: ctx.F.locals[instr.Edges[i]] = &Value{instr.Edges[i], ctx.F.InstanceID(), ctx.L.Index} e, edge = ctx.F.locals[instr.Edges[i]], pred.Index infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"%s/%s = %s, selected function from block %d", instr.Name(), e, instr.String(), edge)) case *ssa.Call: ctx.F.locals[instr.Edges[i]] = &Value{instr.Edges[i], ctx.F.InstanceID(), ctx.L.Index} e, edge = ctx.F.locals[instr.Edges[i]], pred.Index infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"%s/%s = %s, selected call from block %d", instr.Name(), e, instr.String(), edge)) case *ssa.UnOp: ctx.F.locals[instr.Edges[i]] = &Value{instr.Edges[i], ctx.F.InstanceID(), ctx.L.Index} e, edge = ctx.F.locals[instr.Edges[i]], pred.Index infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"%s/%s = %s, selected UnOp from block %d", instr.Name(), e, instr.String(), edge)) default: infer.Logger.Fatalf("phi: create instance Edge[%d]=%#v: %s", i, instr.Edges[i], ErrUnknownValue) return } } ctx.F.locals[instr], edge = e, pred.Index infer.Logger.Printf(ctx.F.Sprintf(PhiSymbol+"%s/%s = %s, selected from block %d", instr.Name(), e, instr.String(), edge)) ctx.F.revlookup[instr.Name()] = instr.Edges[i].Name() if a, ok := ctx.F.arrays[e]; ok { ctx.F.arrays[ctx.F.locals[instr]] = a } if s, ok := ctx.F.structs[e]; ok { ctx.F.structs[ctx.F.locals[instr]] = s } return } } infer.Logger.Fatalf("phi: %d->%d: %s", ctx.B.Pred, instr.Block().Index, ErrPhiUnknownEdge) return }