예제 #1
0
// NewBlock creates a new block enclosed by the given function.
func NewBlock(parent *Function, block *ssa.BasicBlock, curr int) *Block {
	blockFn := fmt.Sprintf("%s#%d", parent.Fn.String(), block.Index)
	parent.ChildBlocks[block.Index] = &Block{
		Function: parent,
		MigoDef:  migo.NewFunction(blockFn),
		Pred:     curr,
		Index:    block.Index,
	}
	return parent.ChildBlocks[block.Index]
}
예제 #2
0
// NewMainFunction returns a new main() call context.
func NewMainFunction(prog *Program, mainFn *ssa.Function) *Function {
	return &Function{
		Fn:          mainFn,
		Prog:        prog,
		Visited:     make(map[*ssa.BasicBlock]int),
		FuncDef:     migo.NewFunction("main.main"),
		ChildBlocks: make(map[int]*Block),

		commaok:   make(map[Instance]*CommaOk),
		defers:    []*ssa.Defer{},
		locals:    make(map[ssa.Value]Instance),
		retvals:   []Instance{},
		extraargs: []ssa.Value{},
		revlookup: make(map[string]string),
		selects:   make(map[Instance]*Select),
		tuples:    make(map[Instance]Tuples),
		loopstack: NewLoopStack(),
		Storage:   NewStorage(),
	}
}
예제 #3
0
// NewFunction returns a new function call context, and takes the caller's
// context as parameter.
func NewFunction(caller *Function) *Function {
	return &Function{
		Caller:      caller,
		Prog:        caller.Prog,
		Visited:     make(map[*ssa.BasicBlock]int),
		FuncDef:     migo.NewFunction("__uninitialised__"),
		Level:       caller.Level + 1,
		ChildBlocks: make(map[int]*Block),

		commaok:   make(map[Instance]*CommaOk),
		defers:    []*ssa.Defer{},
		locals:    make(map[ssa.Value]Instance),
		revlookup: make(map[string]string),
		extraargs: []ssa.Value{},
		retvals:   []Instance{},
		selects:   make(map[Instance]*Select),
		tuples:    make(map[Instance]Tuples),
		loopstack: NewLoopStack(),
		Storage:   NewStorage(),
	}
}
예제 #4
0
func visitJump(jump *ssa.Jump, infer *TypeInfer, ctx *Context) {
	if len(jump.Block().Succs) != 1 {
		infer.Logger.Fatal(ErrInvalidJumpSucc)
	}
	curr, next := jump.Block(), jump.Block().Succs[0]
	infer.Logger.Printf(ctx.F.Sprintf(SkipSymbol+"block %d%s%d", curr.Index, fmtLoopHL(JumpSymbol), next.Index))
	switch ctx.L.State {
	case Exit:
		ctx.L.State = NonLoop
	}
	if len(next.Preds) > 1 {
		infer.Logger.Printf(ctx.F.Sprintf(SplitSymbol+"Jump (%d ⇾ %d) %s", curr.Index, next.Index, ctx.L.String()))
		var stmt *migo.CallStatement
		//if ctx.L.Bound == Static && ctx.L.HasNext() {
		//stmt = &migo.CallStatement{Name: fmt.Sprintf("%s#%d_loop%d", ctx.F.Fn.String(), next.Index, ctx.L.Index), Params: []*migo.Parameter{}}
		//} else {
		stmt = &migo.CallStatement{Name: fmt.Sprintf("%s#%d", ctx.F.Fn.String(), next.Index)}
		for i := 0; i < len(ctx.F.FuncDef.Params); i++ {
			for k, ea := range ctx.F.extraargs {
				if phi, ok := ea.(*ssa.Phi); ok {
					if jump.Block().Index < len(phi.Edges) {
						for _, e := range phi.Edges {
							if ctx.F.FuncDef.Params[i].Caller.Name() == e.Name() {
								ctx.F.FuncDef.Params[i].Callee = phi
								// Remove from extra args
								if k < len(ctx.F.extraargs) {
									ctx.F.extraargs = append(ctx.F.extraargs[:k], ctx.F.extraargs[k+1:]...)
								} else {
									ctx.F.extraargs = ctx.F.extraargs[:k]
								}
							}
						}
					}
				}
			}
			// This loop copies args from current function to Successor.
			if phi, ok := ctx.F.FuncDef.Params[i].Callee.(*ssa.Phi); ok {
				// Resolve in current scope if phi
				stmt.AddParams(&migo.Parameter{Caller: phi.Edges[jump.Block().Index], Callee: ctx.F.FuncDef.Params[i].Callee})
			} else {
				stmt.AddParams(&migo.Parameter{Caller: ctx.F.FuncDef.Params[i].Callee, Callee: ctx.F.FuncDef.Params[i].Callee})
			}
		}
		for _, ea := range ctx.F.extraargs {
			if phi, ok := ea.(*ssa.Phi); ok {
				stmt.AddParams(&migo.Parameter{Caller: phi.Edges[jump.Block().Index], Callee: phi})
			} else {
				stmt.AddParams(&migo.Parameter{Caller: ea, Callee: ea})
			}
		}
		//}
		ctx.F.FuncDef.AddStmts(stmt)
		if _, visited := ctx.F.Visited[next]; !visited {
			newBlock := NewBlock(ctx.F, next, ctx.B.Index)
			oldFunc, newFunc := ctx.F.FuncDef, newBlock.MigoDef
			if ctx.L.Bound == Static && ctx.L.HasNext() {
				newFunc = migo.NewFunction(fmt.Sprintf("%s#%d_loop%d", ctx.F.Fn.String(), next.Index, ctx.L.Index))
			}
			for _, p := range stmt.Params {
				newFunc.AddParams(&migo.Parameter{Caller: p.Callee, Callee: p.Callee})
			}
			ctx.F.FuncDef = newFunc
			infer.Env.MigoProg.AddFunction(newFunc)
			visitBasicBlock(next, infer, ctx.F, newBlock, ctx.L)
			ctx.F.FuncDef = oldFunc
			return
		}
	}
	visitBasicBlock(next, infer, ctx.F, NewBlock(ctx.F, next, ctx.B.Index), ctx.L)
}