Skip to content

Commit

Permalink
Feat: Switched from phis to block parameters in new IR
Browse files Browse the repository at this point in the history
  • Loading branch information
rj45 committed Jan 4, 2022
1 parent c5bb564 commit ba9351f
Show file tree
Hide file tree
Showing 9 changed files with 383 additions and 190 deletions.
14 changes: 8 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,16 @@
- [x] Handle translating tuples to multiple return values
- [x] Can emit IR code in a way that simplifies text, assembly and html generation
- [x] Emits to ssa.html
- [ ] Block parameters instead of phis
- [x] Block parameters instead of phis
- [x] Values can be used by both Blocks and Instrs
- [x] Blocks and Instrs are Users of Values
- [ ] Block parameters are emitted
- [ ] Block parameter defs are parsed
- [ ] Terminal instructions specify dest block arguments
- [ ] Frontend builds blocks with parameters
- [ ] Phis are eliminated
- [x] Block parameters are emitted
- [x] params are emitted on block labels
- [x] correct args are passed to successor blocks
- [x] Block parameter defs are parsed
- [x] Terminal instructions specify dest block arguments
- [x] Frontend builds blocks with parameters
- [x] Phis are eliminated
- [ ] Implement a simplified type system
- [ ] integer types i/u 8,16,32,64
- [ ] bool type
Expand Down
2 changes: 0 additions & 2 deletions frontend/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ type FrontEnd struct {
ssaFuncs map[*ir2.Func]*ssa.Function
parsed map[*ir2.Func]bool

instrmap map[*ir2.Instr]ssa.Instruction
val2instr map[ssa.Value]*ir2.Instr
val2val map[ssa.Value]*ir2.Value
blockmap map[*ssa.BasicBlock]*ir2.Block
Expand Down Expand Up @@ -180,7 +179,6 @@ func (fe *FrontEnd) ParseFunc(fn *ir2.Func) {

fe.val2instr = make(map[ssa.Value]*ir2.Instr)
fe.val2val = make(map[ssa.Value]*ir2.Value)
fe.instrmap = make(map[*ir2.Instr]ssa.Instruction)
fe.blockmap = make(map[*ssa.BasicBlock]*ir2.Block)

fe.translateFunc(fn, fe.ssaFuncs[fn])
Expand Down
136 changes: 65 additions & 71 deletions frontend/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package frontend

import (
"fmt"
"log"
"strings"

"github.com/rj45/nanogo/ir/op"
Expand All @@ -25,13 +24,13 @@ func (fe *FrontEnd) translateFunc(irFunc *ir2.Func, ssaFunc *ssa.Function) {
blockList[i], blockList[j] = blockList[j], blockList[i]
}

type critical struct {
pred *ssa.BasicBlock
succ *ssa.BasicBlock
blk *ir2.Block
}
var criticals []critical
var returns []*ir2.Block
// type critical struct {
// pred *ssa.BasicBlock
// succ *ssa.BasicBlock
// blk *ir2.Block
// }
// var criticals []critical
// var returns []*ir2.Block

for bn, ssaBlock := range blockList {
irBlock := irFunc.NewBlock()
Expand All @@ -46,17 +45,18 @@ func (fe *FrontEnd) translateFunc(irFunc *ir2.Func, ssaFunc *ssa.Function) {
instr.Pos = getPos(param)

fe.val2instr[param] = instr
fe.val2val[param] = instr.Def(0)
}
}

fe.blockmap[ssaBlock] = irBlock

fe.translateInstrs(irBlock, ssaBlock)

lastInstr := ssaBlock.Instrs[len(ssaBlock.Instrs)-1]
if _, ok := lastInstr.(*ssa.Return); ok {
returns = append(returns, irBlock)
}
// lastInstr := ssaBlock.Instrs[len(ssaBlock.Instrs)-1]
// if _, ok := lastInstr.(*ssa.Return); ok {
// returns = append(returns, irBlock)
// }

for _, succ := range ssaBlock.Succs {
if len(ssaBlock.Succs) > 1 && len(succ.Preds) > 1 {
Expand All @@ -65,90 +65,84 @@ func (fe *FrontEnd) translateFunc(irFunc *ir2.Func, ssaFunc *ssa.Function) {

irBlock.InsertInstr(-1, irFunc.NewInstr(op.Jump2, nil))

criticals = append(criticals, critical{
pred: ssaBlock,
succ: succ,
blk: irBlock,
})
// criticals = append(criticals, critical{
// pred: ssaBlock,
// succ: succ,
// blk: irBlock,
// })
}
}
}

// todo: if this panic never happens, maybe placeholders not necessary?
if irFunc.HasPlaceholders() {
panic("Invalid assumption that placeholders no longer necessary")
}

fe.resolvePlaceholders(irFunc)

for _, block := range blockList {
irBlock := fe.blockmap[block]

for it := irBlock.InstrIter(); it.HasNext(); it.Next() {
if ssaInstr, ok := fe.instrmap[it.Instr()]; ok {
_ = ssaInstr
// fe.translateArgs(it.Block(), it.Instr(), ssaInstr)
} else if it.Instr().Op != op.Parameter {
log.Panicf("missing instruction: %v : %d/%d, %d/%d", it.Instr(),
it.BlockIndex(), irFunc.NumBlocks(),
it.InstrIndex(), it.Block().NumInstrs())
}
}

for _, succ := range block.Succs {
found := false
for _, crit := range criticals {
if crit.pred == block && crit.succ == succ {
irBlock.AddSucc(crit.blk)
crit.blk.AddPred(irBlock)
found = true
break
}
}
// for _, crit := range criticals {
// if crit.pred == block && crit.succ == succ {
// irBlock.AddSucc(crit.blk)
// crit.blk.AddPred(irBlock)
// found = true
// break
// }
// }

if !found {
irBlock.AddSucc(fe.blockmap[succ])
}
}
for _, pred := range block.Preds {
found := false
for _, crit := range criticals {
if crit.pred == pred && crit.succ == block {
irBlock.AddPred(crit.blk)
crit.blk.AddSucc(irBlock)
found = true
break
}
}
// for _, crit := range criticals {
// if crit.pred == pred && crit.succ == block {
// irBlock.AddPred(crit.blk)
// crit.blk.AddSucc(irBlock)
// found = true
// break
// }
// }

if !found {
irBlock.AddPred(fe.blockmap[pred])
}
}
}

if len(returns) > 1 {
realRet := irFunc.NewBlock()
irFunc.InsertBlock(-1, realRet)

// var phis []*ir.Value

// for i := 0; i < returns[0].NumControls(); i++ {
// phi := irFunc.NewValue(op.Phi, returns[0].Control(i).Type)
// realRet.InsertInstr(-1, phi)
// realRet.InsertControl(-1, phi)
// phis = append(phis, phi)
// }

for _, ret := range returns {
ret.AddSucc(realRet)
realRet.AddPred(ret)
// ret.Op = op.Jump

// for i := 0; i < ret.NumControls(); i++ {
// phis[i].InsertArg(-1, ret.Control(i))
// }

// for ret.NumControls() > 0 {
// ret.RemoveControl(0)
// }
}
}
// if len(returns) > 1 {
// realRet := irFunc.NewBlock()
// irFunc.InsertBlock(-1, realRet)

// // var phis []*ir.Value

// // for i := 0; i < returns[0].NumControls(); i++ {
// // phi := irFunc.NewValue(op.Phi, returns[0].Control(i).Type)
// // realRet.InsertInstr(-1, phi)
// // realRet.InsertControl(-1, phi)
// // phis = append(phis, phi)
// // }

// for _, ret := range returns {
// ret.AddSucc(realRet)
// realRet.AddPred(ret)
// // ret.Op = op.Jump

// // for i := 0; i < ret.NumControls(); i++ {
// // phis[i].InsertArg(-1, ret.Control(i))
// // }

// // for ret.NumControls() > 0 {
// // ret.RemoveControl(0)
// // }
// }
// }
}

func genName(pkg, name string) string {
Expand Down
49 changes: 47 additions & 2 deletions frontend/instrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (fe *FrontEnd) translateInstrs(irBlock *ir2.Block, ssaBlock *ssa.BasicBlock
case *ssa.Panic:
opcode = op.Panic2
case *ssa.Phi:
opcode = op.Phi
fe.translateBlockParams(irBlock, ins)
case *ssa.Store:
typ = ins.Val.Type()
opcode = op.Store
Expand Down Expand Up @@ -199,8 +199,53 @@ func (fe *FrontEnd) translateInstrs(irBlock *ir2.Block, ssaBlock *ssa.BasicBlock
fe.val2val[vin] = ins.Def(0)
}
}
}

fe.translateBlockArgs(irBlock, ssaBlock)
}

func (fe *FrontEnd) translateBlockParams(block *ir2.Block, phi *ssa.Phi) {
param := block.Func().NewValue(phi.Type())
block.AddDef(param)

fe.val2val[phi] = param
}

fe.instrmap[ins] = instr
func (fe *FrontEnd) translateBlockArgs(irBlock *ir2.Block, ssaBlock *ssa.BasicBlock) {
// for each succ block
for _, succ := range ssaBlock.Succs {
pred := 0
for i, p := range succ.Preds {
if p == ssaBlock {
pred = i
}
}

if succ.Preds[pred] != ssaBlock {
panic("not found")
}

// scan through each phi in that succ block
for _, instr := range succ.Instrs {
phi, ok := instr.(*ssa.Phi)
if !ok {
break
}

// pick out the arg for the current pred block
ssaVal := phi.Edges[pred]
arg := fe.val2val[ssaVal]

if con, ok := ssaVal.(*ssa.Const); ok {
arg = irBlock.Func().ValueFor(phi.Type(), con.Value)
}

if arg == nil {
log.Panicf("Can't find val for %s %T in phi %s in block %s", ssaVal, ssaVal, phi, irBlock)
}

irBlock.InsertArg(-1, arg)
}
}
}

Expand Down
42 changes: 39 additions & 3 deletions ir2/emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"go/types"
"io"
"log"
"sort"
"strings"
)
Expand Down Expand Up @@ -144,7 +145,7 @@ func (blk *Block) Emit(out io.Writer, dec Decorator) {
dec.Begin(out, blk)

dec.BeginLabel(out, blk)
fmt.Fprintf(out, ".%s:", dec.WrapLabel(blk.String(), blk))
fmt.Fprintf(out, ".%s", dec.WrapLabel(blk.String(), blk))

// if len(blk.preds) > 0 {
// fmt.Fprintf(out, " ; <=")
Expand All @@ -154,7 +155,22 @@ func (blk *Block) Emit(out io.Writer, dec Decorator) {
// }
// }

fmt.Fprintln(out)
if dec.SSAForm() && len(blk.defs) > 0 {
fmt.Fprint(out, "(")
for i, def := range blk.defs {
if i != 0 {
fmt.Fprint(out, ", ")
}

lab := dec.WrapLabel(def.String(), def)
typ := dec.WrapType(types.TypeString(def.Type, qualifier(blk.fn.pkg.Type)))

fmt.Fprintf(out, "%s:%s", lab, typ)
}
fmt.Fprint(out, ")")
}

fmt.Fprintln(out, ":")
dec.EndLabel(out, blk)

for it := blk.InstrIter(); it.HasNext(); it.Next() {
Expand Down Expand Up @@ -257,11 +273,31 @@ func (in *Instr) Emit(out io.Writer, dec Decorator) {
} else {
str += " "
}
argn := 0
for i, succ := range in.blk.succs {
if i != 0 {
str += ", "
}
str += dec.WrapRef(succ.String(), succ)
str += dec.WrapRef("."+succ.String(), succ)

if dec.SSAForm() && len(succ.defs) > 0 {
str += "("
for i, _ := range succ.defs {
if i != 0 {
str += ", "
}

if argn >= len(in.blk.args) {
log.Panicf("missing args on block args: %v defs: %v", in.blk.args, succ.defs)
}

arg := in.blk.args[argn]
argn++

str += dec.WrapLabel(arg.String(), arg)
}
str += ")"
}
}
}

Expand Down
Loading

0 comments on commit ba9351f

Please sign in to comment.