Skip to content

Commit

Permalink
Add field and index addr elaboration
Browse files Browse the repository at this point in the history
  • Loading branch information
rj45 committed Dec 22, 2021
1 parent dc30733 commit 1dc0983
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 8 deletions.
19 changes: 11 additions & 8 deletions ir2/instr.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ func (in *Instr) Update(op Op, typ types.Type, args ...interface{}) {
func (in *Instr) update(fn *Func, op Op, typ types.Type, args []interface{}) {
in.Op = op

if tuple, ok := typ.(*types.Tuple); ok {
for i := 0; i < tuple.Len(); i++ {
v := tuple.At(i)

in.updateDef(fn, i, v.Type())
if !op.IsSink() {
if tuple, ok := typ.(*types.Tuple); ok {
for i := 0; i < tuple.Len(); i++ {
v := tuple.At(i)

in.updateDef(fn, i, v.Type())
}
} else if typ != nil {
in.updateDef(fn, 0, typ)
}
} else if typ != nil {
in.updateDef(fn, 0, typ)
}

for i, a := range args {
Expand Down Expand Up @@ -100,7 +102,8 @@ func (in *Instr) AddDef(val *Value) *Value {
// updateDef updates an existing def or adds one if necessary
func (in *Instr) updateDef(fn *Func, i int, typ types.Type) *Value {
typ = validType(typ)
if len(in.defs) < i {

if i < len(in.defs) {
in.defs[i].Type = typ
return in.defs[i]
}
Expand Down
1 change: 1 addition & 0 deletions ir2/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ type Op interface {
IsCompare() bool
IsCopy() bool
IsCommutative() bool
IsSink() bool
}

// Instr is an instruction that may define one or more Values,
Expand Down
42 changes: 42 additions & 0 deletions xform2/elaboration/fieldaddrs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package elaboration

import (
"go/types"

"github.com/rj45/nanogo/ir/op"
"github.com/rj45/nanogo/ir2"
"github.com/rj45/nanogo/sizes"
"github.com/rj45/nanogo/xform2"
)

var _ = xform2.Register(fieldAddrs,
xform2.OnlyPass(xform2.Elaboration),
xform2.OnOp(op.FieldAddr),
)

func fieldAddrs(it ir2.Iter) {
instr := it.Instr()

field, ok := ir2.IntValue(instr.Arg(0).Const())
if !ok {
panic("expected int constant")
}

elem := instr.Arg(1).Type.(*types.Pointer).Elem()
strct := elem.Underlying().(*types.Struct)
fieldType := strct.Field(field).Type()
fieldPtr := types.NewPointer(fieldType)

fields := sizes.Fieldsof(strct)
offsets := sizes.Offsetsof(fields)
offset := offsets[field]

if offset == 0 {
// would just be adding zero, so this instruction can just be removed
instr.Def(0).ReplaceUsesWith(instr.Arg(1))
it.Remove()
return
}

it.Update(op.Add, fieldPtr, instr.Arg(1), offset)
}
29 changes: 29 additions & 0 deletions xform2/elaboration/indexaddrs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package elaboration

import (
"go/types"

"github.com/rj45/nanogo/ir/op"
"github.com/rj45/nanogo/ir2"
"github.com/rj45/nanogo/sizes"
"github.com/rj45/nanogo/xform2"
)

var _ = xform2.Register(indexAddrs,
xform2.OnlyPass(xform2.Elaboration),
xform2.OnOp(op.IndexAddr),
)

// indexAddrs converts `IndexAddr` instructions into a `mul` and `add` instruction
// The `mul` is by a constant which can be optimized into shifts and adds later.
func indexAddrs(it ir2.Iter) {
instr := it.Instr()
elem := instr.Def(0).Type.(*types.Pointer).Elem()

size := sizes.Sizeof(elem)

mul := it.Insert(op.Mul, types.Typ[types.Int], instr.Arg(1), size)

instr.Op = op.Add
instr.ReplaceArg(1, mul.Def(0))
}

0 comments on commit 1dc0983

Please sign in to comment.