Beispiel #1
0
// 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)
	}
}
Beispiel #2
0
// 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
}