Skip to content

Commit 03be68e

Browse files
committed
Starting to build xform2 to use the new IR format
1 parent 6c4f66d commit 03be68e

8 files changed

Lines changed: 353 additions & 10 deletions

File tree

TODO.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
- [x] Get it to parse programs to ir2
183183
- [x] Handle translating tuples to multiple return values
184184
- [x] Can emit IR code in a way that simplifies text, assembly and html generation
185+
- [ ] Emits to ssa.html
185186
- [ ] Implement a simplified type system
186187
- [ ] integer types i/u 8,16,32,64
187188
- [ ] bool type
@@ -232,6 +233,21 @@
232233
- [ ] Refactor: better package naming
233234
- [ ] Generate unique package names
234235
- [ ] Identifiers in other packages are pkg_name.ident rather than pkg_name__ident
236+
- [ ] Use github.com/nochso/ctxerr for error messages
237+
- [ ] Transform xform pkg to use new IR
238+
- [x] Register func with options for config
239+
- [x] grabs name from passed xform func
240+
- [x] tags
241+
- [x] list of active stages
242+
- [x] activating op
243+
- [x] can be run on each instr
244+
- [ ] can be run on each block
245+
- [x] takes a func that takes an iterator
246+
- [x] xform func responsible for leaving iterator in a resumable position
247+
- [x] iterator tracks changes
248+
- [x] ability to tell the iterator a change was made it can't see
249+
- [ ] A way to run a single transform for testing w/tags
250+
- [ ] A way to run a single stage for testing w/tags
235251

236252
- [ ] Rework xform system
237253

compiler/compiler.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import (
2121
"github.com/rj45/nanogo/parser"
2222
"github.com/rj45/nanogo/regalloc"
2323
"github.com/rj45/nanogo/xform"
24+
"github.com/rj45/nanogo/xform2"
25+
26+
_ "github.com/rj45/nanogo/xform2/elaboration"
2427
)
2528

2629
type Arch interface {
@@ -121,6 +124,8 @@ func Compile(outname, dir string, patterns []string, mode Mode) int {
121124
fe.Scan()
122125
for fn := fe.NextUnparsedFunc(); fn != nil; fn = fe.NextUnparsedFunc() {
123126
fe.ParseFunc(fn)
127+
128+
xform2.Transform(xform2.Elaboration, fn)
124129
}
125130

126131
fe.Program().Emit(finalout, ir2.SSAString{})

ir2/instr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (in *Instr) Args() []*Value {
116116

117117
// NumArgs returns the number of arguments
118118
func (in *Instr) NumArgs() int {
119-
return len(in.defs)
119+
return len(in.args)
120120
}
121121

122122
// ArgIndex returns the index of the arg, or

ir2/iters.go

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,61 @@ import (
44
"go/types"
55
)
66

7+
// Iter is a iterator over instructions
8+
type Iter interface {
9+
// Instr returns the current instruction
10+
Instr() *Instr
11+
12+
// InstrIndex returns the index of the current instruction in the Block
13+
InstrIndex() int
14+
15+
// Block returns the current block
16+
Block() *Block
17+
18+
// BlockIndex returns the index of the Block within the Func
19+
BlockIndex() int
20+
21+
// HasNext returns whether Next() will succeed
22+
HasNext() bool
23+
24+
// Next increments the position and returns whether that was successful
25+
Next() bool
26+
27+
// HasPrev returns whether Prev() will succeed
28+
HasPrev() bool
29+
30+
// Prev decrements the position and returns whether that was successful
31+
Prev() bool
32+
33+
// Insert inserts an instruction at the cursor position and increments the position
34+
Insert(op Op, typ types.Type, args ...interface{}) *Instr
35+
36+
// Remove will remove the instruction at the current position and decrement the position,
37+
// returning the removed instruction.
38+
// NOTE: this only removes the instruction from the Block, it does not Unlink() it from
39+
// any uses.
40+
Remove() *Instr
41+
42+
// Update updates the instruction at the cursor position
43+
Update(op Op, typ types.Type, args ...interface{}) *Instr
44+
45+
// HasChanged returns true if `Changed()` was called, or one of the mutation methods
46+
HasChanged() bool
47+
48+
// Changed forces `HasChanged()` to return true
49+
Changed()
50+
}
51+
52+
var _ Iter = &BlockIter{}
53+
var _ Iter = &CrossBlockIter{}
54+
755
/// in-block iterator
856

957
// BlockIter is an iterator that iterates over instructions in a Block
1058
type BlockIter struct {
11-
blk *Block
12-
insIdx int
59+
blk *Block
60+
insIdx int
61+
changed bool
1362
}
1463

1564
// InstrIter will return an Iter which iterates over every
@@ -74,13 +123,25 @@ func (it *BlockIter) HasPrev() bool {
74123
return it.insIdx >= 0 // todo: there is a bug here
75124
}
76125

126+
// HasChanged returns true if `Changed()` was called, or one of the mutation methods
127+
func (it *BlockIter) HasChanged() bool {
128+
return it.changed
129+
}
130+
131+
// Changed forces `HasChanged()` to return true
132+
func (it *BlockIter) Changed() {
133+
it.changed = true
134+
}
135+
77136
// Insert inserts an instruction at the cursor position and increments the position
78137
func (it *BlockIter) Insert(op Op, typ types.Type, args ...interface{}) *Instr {
79138
instr := it.blk.fn.NewInstr(op, typ, args...)
80139

81140
it.blk.InsertInstr(it.insIdx, instr)
82141
it.Next()
83142

143+
it.changed = true
144+
84145
return instr
85146
}
86147

@@ -95,6 +156,8 @@ func (it *BlockIter) Remove() *Instr {
95156
it.blk.RemoveInstr(instr)
96157
it.Prev()
97158

159+
it.changed = true
160+
98161
return instr
99162
}
100163

@@ -104,6 +167,8 @@ func (it *BlockIter) Update(op Op, typ types.Type, args ...interface{}) *Instr {
104167

105168
instr.Update(op, typ, args...)
106169

170+
it.changed = true
171+
107172
return instr
108173
}
109174

@@ -128,24 +193,25 @@ func (fn *Func) InstrIter() *CrossBlockIter {
128193

129194
// HasNext returns whether Next() will succeed
130195
func (it *CrossBlockIter) HasNext() bool {
131-
return it.insIdx < len(it.blk.instrs) && it.blkIdx < len(it.fn.blocks)
196+
return (it.insIdx+1) < len(it.blk.instrs) || (it.blkIdx+1) < len(it.fn.blocks)
132197
}
133198

134199
// Next increments the position and returns whether that was successful
135200
func (it *CrossBlockIter) Next() bool {
136-
if it.insIdx >= len(it.blk.instrs) {
137-
if (it.blkIdx + 1) >= len(it.fn.blocks) {
138-
return false
139-
}
201+
if !it.HasNext() {
202+
return false
203+
}
204+
205+
it.insIdx++
140206

207+
if it.insIdx >= len(it.blk.instrs) {
141208
it.blkIdx++
142209
it.insIdx = 0
143210
it.blk = it.fn.blocks[it.blkIdx]
144211
return true
145212
}
146213

147-
it.insIdx++
148-
return it.insIdx < len(it.blk.instrs)
214+
return true
149215
}
150216

151217
// HasPrev returns whether Prev() will succeed

ir2/structs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ const (
163163
VFunc
164164
VTemp
165165
VReg
166+
VArg
166167
VStack
167168
VGlob
168169
VHeap

xform2/elaboration/calls.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package elaboration
2+
3+
import (
4+
"go/types"
5+
"log"
6+
7+
"github.com/rj45/nanogo/ir/op"
8+
"github.com/rj45/nanogo/ir/reg"
9+
"github.com/rj45/nanogo/ir2"
10+
"github.com/rj45/nanogo/xform2"
11+
)
12+
13+
var _ = xform2.Register(calls,
14+
xform2.OnlyPass(xform2.Elaboration),
15+
xform2.OnOp(op.Call),
16+
)
17+
18+
func calls(it ir2.Iter) {
19+
instr := it.Instr()
20+
fnType := instr.Arg(0).Type.(*types.Signature)
21+
22+
if instr.NumArgs() > 1 && instr.Arg(1).Def() != nil && instr.Arg(1).Def().Op == op.Copy {
23+
log.Println("arg copy already done")
24+
return
25+
}
26+
27+
if instr.NumDefs() > 0 && instr.Def(0).NumUses() == 1 && instr.Def(0).Use(0).Op == op.Copy {
28+
log.Println("result copy already done")
29+
return
30+
}
31+
32+
// todo:
33+
// - add parallel copy for clobbered regs?
34+
35+
if instr.NumArgs() > 1 {
36+
params := fnType.Params()
37+
38+
args := make([]interface{}, instr.NumArgs()-1)
39+
for i := 1; i < instr.NumArgs(); i++ {
40+
args[i-1] = instr.Arg(i)
41+
}
42+
43+
paramCopy := it.Insert(op.Copy, params, args...)
44+
log.Println(paramCopy.LongString())
45+
for i := 0; i < paramCopy.NumDefs(); i++ {
46+
if i < len(reg.ArgRegs) {
47+
paramCopy.Def(i).Loc = ir2.VReg
48+
paramCopy.Def(i).Index = reg.ArgRegs[i].RegNumber()
49+
} else {
50+
paramCopy.Def(i).Loc = ir2.VArg
51+
paramCopy.Def(i).Index = i - len(reg.ArgRegs)
52+
}
53+
instr.ReplaceArg(i+1, paramCopy.Def(i))
54+
}
55+
}
56+
57+
if instr.NumDefs() > 0 {
58+
results := fnType.Results()
59+
60+
args := make([]interface{}, instr.NumDefs())
61+
for i := 0; i < instr.NumDefs(); i++ {
62+
args[i] = instr.Def(i)
63+
}
64+
65+
it.Next()
66+
resCopy := it.Insert(op.Copy, results, args...)
67+
log.Println(resCopy.LongString())
68+
for i := 0; i < resCopy.NumArgs(); i++ {
69+
if i < len(reg.ArgRegs) {
70+
resCopy.Arg(i).Loc = ir2.VReg
71+
resCopy.Arg(i).Index = reg.ArgRegs[i].RegNumber()
72+
} else {
73+
resCopy.Arg(i).Loc = ir2.VArg
74+
resCopy.Arg(i).Index = i - len(reg.ArgRegs)
75+
}
76+
77+
// todo: could use a version of this that doesn't
78+
// clobber the current instruction or something
79+
instr.Def(i).ReplaceUsesWith(resCopy.Def(i))
80+
81+
// switch this back to what it was
82+
resCopy.ReplaceArg(i, instr.Def(i))
83+
}
84+
}
85+
86+
log.Println(instr.LongString())
87+
}

xform2/tag.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package xform2
2+
3+
type Tag uint8
4+
5+
const (
6+
Invalid Tag = iota
7+
HasFramePointer
8+
9+
// ...
10+
11+
NumTags
12+
)
13+
14+
var activeTags []bool
15+
16+
type Arch interface {
17+
XformTags() []Tag
18+
}
19+
20+
func SetArch(a Arch) {
21+
activeTags = make([]bool, NumTags)
22+
for _, tag := range a.XformTags() {
23+
activeTags[tag] = true
24+
}
25+
}

0 commit comments

Comments
 (0)