This commit is contained in:
parent
ccc221aa01
commit
2592d7aae8
10 changed files with 66 additions and 20 deletions
|
@ -1,10 +1,15 @@
|
|||
package codegen
|
||||
|
||||
import "git.urbach.dev/cli/q/src/ssa"
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/ssa"
|
||||
)
|
||||
|
||||
// createHints recommends registers that a value must reside in later on.
|
||||
func (f *Function) createHints(step *step) {
|
||||
switch instr := step.Value.(type) {
|
||||
case *ssa.BinaryOp:
|
||||
f.ValueToStep[instr.Left].Hint(step.Register)
|
||||
|
||||
case *ssa.Call:
|
||||
for paramIndex, param := range instr.Arguments {
|
||||
f.ValueToStep[param].Hint(f.CPU.Call.In[paramIndex])
|
||||
|
@ -21,8 +26,17 @@ func (f *Function) createHints(step *step) {
|
|||
f.ValueToStep[param].Hint(f.CPU.ExternCall.In[r])
|
||||
}
|
||||
|
||||
case *ssa.Int:
|
||||
if step.Register == -1 {
|
||||
users := step.Value.Users()
|
||||
alive := f.ValueToStep[users[len(users)-1]].Index
|
||||
step.Register = f.findFreeRegister(f.Steps[step.Index:alive])
|
||||
}
|
||||
|
||||
case *ssa.Parameter:
|
||||
f.ValueToStep[instr].Register = f.CPU.Call.In[instr.Index]
|
||||
if step.Register == -1 {
|
||||
step.Register = f.CPU.Call.In[instr.Index]
|
||||
}
|
||||
|
||||
case *ssa.Return:
|
||||
for r, param := range instr.Arguments {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"git.urbach.dev/cli/q/src/ssa"
|
||||
)
|
||||
|
||||
|
@ -20,7 +22,7 @@ func (f *Function) createSteps(ir ssa.IR) {
|
|||
f.ValueToStep[instr] = step
|
||||
}
|
||||
|
||||
for _, step := range f.Steps {
|
||||
for _, step := range slices.Backward(f.Steps) {
|
||||
f.createHints(step)
|
||||
f.createLiveRanges(step)
|
||||
}
|
||||
|
|
|
@ -5,33 +5,36 @@ import (
|
|||
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/cli/q/src/ssa"
|
||||
"git.urbach.dev/cli/q/src/token"
|
||||
)
|
||||
|
||||
// fixRegisterConflicts checks for conflicts where 2 values that are live at the same time use the same register.
|
||||
// It then assigns a new register to the value that was defined earlier.
|
||||
func (f *Function) fixRegisterConflicts() {
|
||||
for stepIndex, step := range f.Steps {
|
||||
var clobbered []cpu.Register
|
||||
|
||||
switch instr := step.Value.(type) {
|
||||
case *ssa.BinaryOp:
|
||||
if instr.Op == token.Div {
|
||||
clobbered = f.CPU.Division
|
||||
}
|
||||
case *ssa.Call:
|
||||
clobbered = f.CPU.Call.Clobbered
|
||||
case *ssa.CallExtern:
|
||||
clobbered = f.CPU.ExternCall.Clobbered
|
||||
case *ssa.Syscall:
|
||||
clobbered = f.CPU.Syscall.Clobbered
|
||||
}
|
||||
|
||||
for i, live := range step.Live {
|
||||
if live.Register == -1 {
|
||||
continue
|
||||
}
|
||||
|
||||
var clobbered []cpu.Register
|
||||
|
||||
switch step.Value.(type) {
|
||||
case *ssa.Call:
|
||||
clobbered = f.CPU.Call.Clobbered
|
||||
case *ssa.CallExtern:
|
||||
clobbered = f.CPU.ExternCall.Clobbered
|
||||
case *ssa.Syscall:
|
||||
clobbered = f.CPU.Syscall.Clobbered
|
||||
case *ssa.BinaryOp:
|
||||
|
||||
}
|
||||
|
||||
if live.Value != step.Value && slices.Contains(clobbered, live.Register) {
|
||||
live.Register = f.findFreeRegister(f.Steps[live.Index : stepIndex+1])
|
||||
goto next
|
||||
continue
|
||||
}
|
||||
|
||||
for _, previous := range step.Live[:i] {
|
||||
|
@ -47,10 +50,9 @@ func (f *Function) fixRegisterConflicts() {
|
|||
previous.Register = f.findFreeRegister(f.Steps[previous.Index : stepIndex+1])
|
||||
} else {
|
||||
live.Register = f.findFreeRegister(f.Steps[live.Index : stepIndex+1])
|
||||
goto next
|
||||
break
|
||||
}
|
||||
}
|
||||
next:
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package cpu
|
|||
// CPU represents the processor.
|
||||
type CPU struct {
|
||||
General []Register
|
||||
Division []Register
|
||||
Call ABI
|
||||
ExternCall ABI
|
||||
Syscall ABI
|
||||
|
|
|
@ -27,6 +27,7 @@ var (
|
|||
R1, R2, R6, R7, R8, R9, R10, R11, // Clobbered
|
||||
R3, R12, R13, R14, R15, // Preserved
|
||||
},
|
||||
Division: []cpu.Register{R0, R2},
|
||||
Call: cpu.ABI{
|
||||
In: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
|
||||
Out: []cpu.Register{R0, R2},
|
||||
|
@ -49,6 +50,7 @@ var (
|
|||
|
||||
MacCPU = cpu.CPU{
|
||||
General: LinuxCPU.General,
|
||||
Division: LinuxCPU.Division,
|
||||
Call: LinuxCPU.Call,
|
||||
ExternCall: LinuxCPU.ExternCall,
|
||||
Syscall: cpu.ABI{
|
||||
|
@ -64,7 +66,8 @@ var (
|
|||
R1, R2, R8, R9, R10, R11, // Clobbered
|
||||
R3, R6, R7, R12, R13, R14, R15, // Preserved
|
||||
},
|
||||
Call: LinuxCPU.Call,
|
||||
Division: LinuxCPU.Division,
|
||||
Call: LinuxCPU.Call,
|
||||
ExternCall: cpu.ABI{
|
||||
In: []cpu.Register{R1, R2, R8, R9},
|
||||
Out: []cpu.Register{R0},
|
||||
|
|
5
tests/math-10.q
Normal file
5
tests/math-10.q
Normal file
|
@ -0,0 +1,5 @@
|
|||
import os
|
||||
|
||||
main() {
|
||||
os.exit((2 + 3) * 2)
|
||||
}
|
5
tests/math-2.q
Normal file
5
tests/math-2.q
Normal file
|
@ -0,0 +1,5 @@
|
|||
import os
|
||||
|
||||
main() {
|
||||
os.exit((2 + 3) * 2 / 3 - 1)
|
||||
}
|
5
tests/math-3.q
Normal file
5
tests/math-3.q
Normal file
|
@ -0,0 +1,5 @@
|
|||
import os
|
||||
|
||||
main() {
|
||||
os.exit((2 + 3) * 2 / 3)
|
||||
}
|
5
tests/math-5.q
Normal file
5
tests/math-5.q
Normal file
|
@ -0,0 +1,5 @@
|
|||
import os
|
||||
|
||||
main() {
|
||||
os.exit(2 + 3)
|
||||
}
|
|
@ -11,6 +11,10 @@ var tests = []testRun{
|
|||
{"hello-3", "", "Hello\nHello\nHello\n", 0},
|
||||
{"param-swap", "", "", 3},
|
||||
{"script", "", "Hello\n", 0},
|
||||
{"math-5", "", "", 5},
|
||||
{"math-10", "", "", 10},
|
||||
{"math-3", "", "", 3},
|
||||
{"math-2", "", "", 2},
|
||||
}
|
||||
|
||||
func TestTests(t *testing.T) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue