Beispiel #1
0
func visitJump(inst *ssa.Jump, fr *frame) {
	//fmt.Fprintf(os.Stderr, " -jump-> Block %d\n", inst.Block().Succs[0].Index)
	if len(inst.Block().Succs) != 1 {
		panic("Cannot Jump with multiple successors!")
	}
	visitBlock(inst.Block().Succs[0], fr)
}
Beispiel #2
0
func (f *Function) Jump(jmp *ssa.Jump) (string, *Error) {
	asm := ""
	block := -1
	if jmp.Block() != nil && len(jmp.Block().Succs) == 1 {
		block = jmp.Block().Succs[0].Index
	} else {
		ice("malformed CFG with jmp stmt")
	}
	a, err := f.JumpPreamble(jmp, jmp.Block().Index, block)
	if err != nil {
		return "", err
	}
	asm += a
	asm += "JMP block" + strconv.Itoa(block) + "\n"
	asm = "// BEGIN ssa.Jump\n" + asm
	asm += "// END ssa.Jump\n"
	return asm, nil
}
Beispiel #3
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)
}