Skip to content

Commit

Permalink
Add more docs to new IR
Browse files Browse the repository at this point in the history
  • Loading branch information
rj45 committed Dec 7, 2021
1 parent 732154c commit c71caa5
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 47 deletions.
48 changes: 48 additions & 0 deletions ir2/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,82 @@ func (blk *Block) init(fn *Func, id ID) {
blk.succs = blk.succstorage[:0]
}

// Func returns the containing Func
func (blk *Block) Func() *Func {
return blk.fn
}

// NumPreds is the number of predecessors
func (blk *Block) NumPreds() int {
return len(blk.preds)
}

// Pred returns the ith predecessor
func (blk *Block) Pred(i int) *Block {
return blk.preds[i]
}

// AddPred adds the Block to the predecessor list
func (blk *Block) AddPred(pred *Block) {
blk.preds = append(blk.preds, pred)
}

// NumSuccs returns the number of successors
func (blk *Block) NumSuccs() int {
return len(blk.succs)
}

// Succ returns the ith successor
func (blk *Block) Succ(i int) *Block {
return blk.succs[i]
}

// AddSucc adds the Block to the successor list
func (blk *Block) AddSucc(succ *Block) {
blk.succs = append(blk.succs, succ)
}

// Unlink removes the Block from the pred/succ
// lists of surrounding Blocks
func (blk *Block) Unlink() {
if len(blk.preds) == 1 && len(blk.succs) == 1 {
replPred := blk.preds[0]
replSucc := blk.succs[0]

for j, pred := range replSucc.preds {
if pred == blk {
replSucc.preds[j] = replPred
}
}

for j, succ := range replPred.succs {
if succ == blk {
replPred.succs[j] = replSucc
}
}
} else {
panic("can't remove block")
}
}

// NumInstrs returns the number of instructions
func (blk *Block) NumInstrs() int {
return len(blk.instrs)
}

// Instr returns the ith Instr in the list
func (blk *Block) Instr(i int) *Instr {
return blk.instrs[i]
}

// Control returns the last instruction, which
// should be a control flow instruction
func (blk *Block) Control() *Instr {
return blk.instrs[len(blk.instrs)-1]
}

// InsertInstr inserts the instruction at the ith
// position. -1 means append it.
func (blk *Block) InsertInstr(i int, instr *Instr) {
if instr.blk != nil && instr.blk != blk {
log.Panicf("remove instr %v from blk %v before inserting into %v", instr, instr.blk, blk)
Expand All @@ -75,6 +111,18 @@ func (blk *Block) InsertInstr(i int, instr *Instr) {
}
}

// SwapInstr swaps two instructions
func (blk *Block) SwapInstr(a *Instr, b *Instr) {
i := a.Index()
j := b.Index()

blk.instrs[i], blk.instrs[j] = blk.instrs[j], blk.instrs[i]

a.index = j
b.index = i
}

// RemoveInstr removes the Instr from the list
func (blk *Block) RemoveInstr(inst *Instr) {
i := inst.Index()
if i < 0 {
Expand Down
95 changes: 70 additions & 25 deletions ir2/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,27 @@ package ir2
import (
"fmt"
"go/types"
"log"

"github.com/rj45/nanogo/ir/op"
)

// slab allocation sizes
const valueSlabSize = 16
const instrSlabSize = 16
const blockSlabSize = 4

func (fn *Func) Name() string {
return fn.name
}

// Package returns the Func's Package
func (fn *Func) Package() *Package {
return fn.pkg
}

func (fn *Func) Block(b ID) *Block {
return fn.blocks[b]
}

func (fn *Func) Value(v ID) *Value {
return fn.values[v]
}

func (fn *Func) Instr(i ID) *Instr {
return fn.instrs[i]
// ValueForID returns the Value for the ID
func (fn *Func) ValueForID(v ID) *Value {
return fn.idValues[v]
}

// NewValue creates a new Value of type typ
func (fn *Func) NewValue(typ types.Type) *Value {
// allocate values in contiguous slabs in memory
// to increase data locality
Expand All @@ -40,13 +33,32 @@ func (fn *Func) NewValue(typ types.Type) *Value {
fn.valueslab = append(fn.valueslab, Value{})
val := &fn.valueslab[len(fn.valueslab)-1]

val.init(ID(len(fn.values)), typ)
val.init(ID(len(fn.idValues)), typ)

fn.values = append(fn.values, val)
fn.idValues = append(fn.idValues, val)

return val
}

// ValueFor looks up an existing Value
func (fn *Func) ValueFor(v interface{}) *Value {
switch v := v.(type) {
// todo: add constants and funcs
case *Value:
return v
}

panic(fmt.Sprintf("can't get value %#v", v))
}

// Instrs

// InstrForID returns the Instr for the ID
func (fn *Func) InstrForID(i ID) *Instr {
return fn.idInstrs[i]
}

// NewInstr creates an unbound Instr
func (fn *Func) NewInstr(op op.Op, typ types.Type, args ...interface{}) *Instr {
// allocate instrs in contiguous slabs in memory
// to increase data locality
Expand All @@ -56,9 +68,9 @@ func (fn *Func) NewInstr(op op.Op, typ types.Type, args ...interface{}) *Instr {
fn.instrslab = append(fn.instrslab, Instr{})
instr := &fn.instrslab[len(fn.instrslab)-1]

instr.init(ID(len(fn.instrs)))
instr.init(ID(len(fn.idInstrs)))

fn.instrs = append(fn.instrs, instr)
fn.idInstrs = append(fn.idInstrs, instr)

for _, a := range args {
arg := fn.ValueFor(a)
Expand All @@ -80,6 +92,14 @@ func (fn *Func) NewInstr(op op.Op, typ types.Type, args ...interface{}) *Instr {
return instr
}

// Blocks

// BlockForID returns a Block by ID
func (fn *Func) BlockForID(b ID) *Block {
return fn.idBlocks[b]
}

// NewBlock adds a new block
func (fn *Func) NewBlock() *Block {
// allocate blocks in contiguous slabs in memory
// to increase data locality
Expand All @@ -89,18 +109,43 @@ func (fn *Func) NewBlock() *Block {
fn.blockslab = append(fn.blockslab, Block{})
blk := &fn.blockslab[len(fn.blockslab)-1]

blk.init(fn, ID(len(fn.blocks)))
blk.init(fn, ID(len(fn.idBlocks)))

fn.blocks = append(fn.blocks, blk)
fn.idBlocks = append(fn.idBlocks, blk)

return blk
}

func (fn *Func) ValueFor(v interface{}) *Value {
switch v := v.(type) {
case *Value:
return v
// InsertBlock inserts the block at the specific
// location in the list
func (fn *Func) InsertBlock(i int, blk *Block) {
if blk.fn != fn {
log.Panicf("inserting block %v from %v int another func %v not supported", blk, blk.fn, fn)
}

panic(fmt.Sprintf("can't get value %#v", v))
if i < 0 || i >= len(fn.blocks) {
fn.blocks = append(fn.blocks, blk)
return
}

fn.blocks = append(fn.blocks[:i+1], fn.blocks[i:]...)
fn.blocks[i] = blk
}

// BlockIndex returns the index of the Block in the list
func (fn *Func) BlockIndex(blk *Block) int {
for i, b := range fn.blocks {
if b == blk {
return i
}
}
return -1
}

// RemoveBlock removes the Block from the list but
// does not remove it from succ/pred lists. See blk.Unlink()
func (fn *Func) RemoveBlock(blk *Block) {
i := fn.BlockIndex(blk)

fn.blocks = append(fn.blocks[:i], fn.blocks[i+1:]...)
}
41 changes: 41 additions & 0 deletions ir2/instr.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,56 @@ func (in *Instr) init(id ID) {
in.args = in.argstorage[:0]
}

// Func returns the Func the Instr is in
func (in *Instr) Func() *Func {
return in.blk.fn
}

// Block returns the containing Block
func (in *Instr) Block() *Block {
return in.blk
}

// Index returns the index in the Block's
// Instr list
func (in *Instr) Index() int {
if in.blk.instrs[in.index] != in {
log.Panicf("bad index on %v", in)
}
return in.index
}

// MoveBefore moves this instruction before other
func (in *Instr) MoveBefore(other *Instr) {
in.blk.RemoveInstr(in)
other.blk.InsertInstr(other.Index(), in)
}

// MoveAfter moves this instruction after other
func (in *Instr) MoveAfter(other *Instr) {
in.blk.RemoveInstr(in)
other.blk.InsertInstr(other.Index()+1, in)
}

// Definitions (Defs)

// Defs returns a copy of the list of Values
// defined by this Instr
func (in *Instr) Defs() []*Value {
return append([]*Value(nil), in.defs...)
}

// NumDefs returns the number of Values defined
func (in *Instr) NumDefs() int {
return len(in.defs)
}

// Def returns the ith Value defined
func (in *Instr) Def(i int) *Value {
return in.defs[i]
}

// AddDef adds a Value definition
func (in *Instr) AddDef(val *Value) *Value {
in.defs = append(in.defs, val)
val.def = in
Expand All @@ -47,14 +68,18 @@ func (in *Instr) AddDef(val *Value) *Value {

// Arguments (Args) / Operands

// Args returns a copy of the arguments
func (in *Instr) Args() []*Value {
return append([]*Value(nil), in.args...)
}

// NumArgs returns the number of arguments
func (in *Instr) NumArgs() int {
return len(in.defs)
}

// ArgIndex returns the index of the arg, or
// -1 if not found
func (in *Instr) ArgIndex(arg *Value) int {
for i, a := range in.args {
if a == arg {
Expand All @@ -64,10 +89,13 @@ func (in *Instr) ArgIndex(arg *Value) int {
return -1
}

// Arg returns the ith argument
func (in *Instr) Arg(i int) *Value {
return in.args[i]
}

// InsertArg inserts the Value in the argument
// list at position i, or appending if i is -1
func (in *Instr) InsertArg(i int, arg *Value) {
arg.addUse(in)

Expand All @@ -80,9 +108,22 @@ func (in *Instr) InsertArg(i int, arg *Value) {
in.args[i] = arg
}

// RemoveArg removes the value from the arguments list
func (in *Instr) RemoveArg(arg *Value) {
i := in.ArgIndex(arg)
arg.removeUse(in)

in.args = append(in.args[:i], in.args[i+1:]...)
}

// ReplaceArg replaces the ith argument with the
// value specified
func (in *Instr) ReplaceArg(i int, arg *Value) {
if in.ArgIndex(arg) != -1 {
panic("tried to replace already existing arg")
}

in.args[i].removeUse(in)
in.args[i] = arg
in.args[i].addUse(in)
}
4 changes: 2 additions & 2 deletions ir2/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func (pkg *Package) Funcs() []*Func {
// if there is no match, by short name.
func (pkg *Package) Func(name string) *Func {
for _, fn := range pkg.funcs {
if fn.name == name {
if fn.Name == name {
return fn
}
}
Expand All @@ -24,7 +24,7 @@ func (pkg *Package) Func(name string) *Func {
// AddFunc adds a func to the list
func (pkg *Package) NewFunc(name string) {
fn := &Func{
name: name,
Name: name,
FullName: pkg.genUniqueName(name),
}
fn.pkg = pkg
Expand Down
Loading

0 comments on commit c71caa5

Please sign in to comment.