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) }
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 }
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) }