Example #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)
	}
}
Example #2
0
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
	}
}
Example #3
0
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
}
Example #4
0
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)
	}
}
Example #5
0
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
}
Example #6
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
}