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