Implemented basic math
All checks were successful
/ test (push) Successful in 16s

This commit is contained in:
Eduard Urbach 2025-07-15 14:40:10 +02:00
parent ccc221aa01
commit 2592d7aae8
Signed by: ed
GPG key ID: 49226B848C78F6C8
10 changed files with 66 additions and 20 deletions

View file

@ -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 {

View file

@ -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)
} }

View file

@ -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:
} }
} }
} }

View file

@ -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

View file

@ -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
View file

@ -0,0 +1,5 @@
import os
main() {
os.exit((2 + 3) * 2)
}

5
tests/math-2.q Normal file
View file

@ -0,0 +1,5 @@
import os
main() {
os.exit((2 + 3) * 2 / 3 - 1)
}

5
tests/math-3.q Normal file
View file

@ -0,0 +1,5 @@
import os
main() {
os.exit((2 + 3) * 2 / 3)
}

5
tests/math-5.q Normal file
View file

@ -0,0 +1,5 @@
import os
main() {
os.exit(2 + 3)
}

View file

@ -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) {