Added ABI definitions
All checks were successful
/ test (push) Successful in 15s

This commit is contained in:
Eduard Urbach 2025-07-05 11:33:53 +02:00
parent 7d2eb95c83
commit 6d15ff3a35
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
9 changed files with 116 additions and 43 deletions

3
lib/os/os_mac_arm.q Normal file
View file

@ -0,0 +1,3 @@
exit(code int) {
syscall(0x1, code)
}

View file

@ -41,10 +41,37 @@ const (
ZR = SP // Zero register uses the same numerical value as SP ZR = SP // Zero register uses the same numerical value as SP
) )
var CPU = cpu.CPU{ var (
Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6}, LinuxCPU = cpu.CPU{
Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5}, Call: cpu.ABI{
ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7}, In: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
ExternCallVolatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17}, Out: []cpu.Register{X0, X1, X2},
Return: []cpu.Register{X0, X1, X2}, Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
} },
ExternCall: cpu.ABI{
In: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7},
Out: []cpu.Register{X0, X1},
Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17},
},
Syscall: cpu.ABI{
In: []cpu.Register{X8, X0, X1, X2, X3, X4, X5},
Out: []cpu.Register{X0},
Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17},
},
}
MacCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: LinuxCPU.ExternCall,
Syscall: cpu.ABI{
In: []cpu.Register{X16, X0, X1, X2, X3, X4, X5, X6, X7},
Out: LinuxCPU.Syscall.Out,
Volatile: LinuxCPU.Syscall.Volatile,
},
}
WindowsCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: LinuxCPU.ExternCall,
}
)

8
src/cpu/ABI.go Normal file
View file

@ -0,0 +1,8 @@
package cpu
// ABI is the Application Binary Interface which defines the registers used in function calls.
type ABI struct {
In []Register
Out []Register
Volatile []Register
}

View file

@ -2,9 +2,7 @@ package cpu
// CPU represents the processor. // CPU represents the processor.
type CPU struct { type CPU struct {
Call []Register Call ABI
Syscall []Register ExternCall ABI
ExternCall []Register Syscall ABI
ExternCallVolatile []Register
Return []Register
} }

View file

@ -72,9 +72,23 @@ func (s *scanner) scanFunction(file *fs.File, tokens token.List, i int) (int, er
switch s.build.Arch { switch s.build.Arch {
case build.ARM: case build.ARM:
function.CPU = &arm.CPU switch s.build.OS {
case build.Linux:
function.CPU = &arm.LinuxCPU
case build.Mac:
function.CPU = &arm.MacCPU
case build.Windows:
function.CPU = &arm.WindowsCPU
}
case build.X86: case build.X86:
function.CPU = &x86.CPU switch s.build.OS {
case build.Linux:
function.CPU = &x86.LinuxCPU
case build.Mac:
function.CPU = &x86.MacCPU
case build.Windows:
function.CPU = &x86.WindowsCPU
}
} }
function.Body = tokens[bodyStart:i] function.Body = tokens[bodyStart:i]

View file

@ -29,32 +29,32 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
if isStruct { if isStruct {
for _, field := range structure.Arguments { for _, field := range structure.Arguments {
f.ValueToStep[field].Hint(f.CPU.Call[offset+r]) f.ValueToStep[field].Hint(f.CPU.Call.In[offset+r])
offset++ offset++
} }
offset-- offset--
} else { } else {
f.ValueToStep[param].Hint(f.CPU.Call[offset+r]) f.ValueToStep[param].Hint(f.CPU.Call.In[offset+r])
} }
} }
case *ssa.CallExtern: case *ssa.CallExtern:
for r, param := range instr.Arguments[1:] { for r, param := range instr.Arguments[1:] {
f.ValueToStep[param].Hint(f.CPU.ExternCall[r]) f.ValueToStep[param].Hint(f.CPU.ExternCall.In[r])
} }
case *ssa.Parameter: case *ssa.Parameter:
f.ValueToStep[instr].Register = f.CPU.Call[instr.Index] f.ValueToStep[instr].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 {
f.ValueToStep[param].Hint(f.CPU.Return[r]) f.ValueToStep[param].Hint(f.CPU.Call.Out[r])
} }
case *ssa.Syscall: case *ssa.Syscall:
for r, param := range slices.Backward(instr.Arguments) { for r, param := range slices.Backward(instr.Arguments) {
f.ValueToStep[param].Hint(f.CPU.Syscall[r]) f.ValueToStep[param].Hint(f.CPU.Syscall.In[r])
} }
} }
@ -89,7 +89,7 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
liveParam, isParam := live.Value.(*ssa.Parameter) liveParam, isParam := live.Value.(*ssa.Parameter)
if isParam { if isParam {
oldRegister = f.CPU.Call[liveParam.Index] oldRegister = f.CPU.Call.In[liveParam.Index]
} }
for _, existing := range step.Live[:liveIndex] { for _, existing := range step.Live[:liveIndex] {

View file

@ -35,9 +35,9 @@ func (f *Compiler) Exec(step *Step) {
if isStruct { if isStruct {
for _, field := range structure.Arguments { for _, field := range structure.Arguments {
if f.ValueToStep[field].Register != f.CPU.Call[offset+i] { if f.ValueToStep[field].Register != f.CPU.Call.In[offset+i] {
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Call[offset+i], Destination: f.CPU.Call.In[offset+i],
Source: f.ValueToStep[field].Register, Source: f.ValueToStep[field].Register,
}) })
} }
@ -47,9 +47,9 @@ func (f *Compiler) Exec(step *Step) {
offset-- offset--
} else { } else {
if f.ValueToStep[arg].Register != f.CPU.Call[offset+i] { if f.ValueToStep[arg].Register != f.CPU.Call.In[offset+i] {
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Call[offset+i], Destination: f.CPU.Call.In[offset+i],
Source: f.ValueToStep[arg].Register, Source: f.ValueToStep[arg].Register,
}) })
} }
@ -59,22 +59,22 @@ func (f *Compiler) Exec(step *Step) {
fn := instr.Arguments[0].(*ssa.Function) fn := instr.Arguments[0].(*ssa.Function)
f.Assembler.Append(&asm.Call{Label: fn.UniqueName}) f.Assembler.Append(&asm.Call{Label: fn.UniqueName})
if step.Register == -1 || step.Register == f.CPU.Return[0] { if step.Register == -1 || step.Register == f.CPU.Call.Out[0] {
return return
} }
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register, Destination: step.Register,
Source: f.CPU.Return[0], Source: f.CPU.Call.Out[0],
}) })
case *ssa.CallExtern: case *ssa.CallExtern:
args := instr.Arguments[1:] args := instr.Arguments[1:]
for i, arg := range args { for i, arg := range args {
if f.ValueToStep[arg].Register != f.CPU.ExternCall[i] { if f.ValueToStep[arg].Register != f.CPU.ExternCall.In[i] {
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.ExternCall[i], Destination: f.CPU.ExternCall.In[i],
Source: f.ValueToStep[arg].Register, Source: f.ValueToStep[arg].Register,
}) })
} }
@ -86,13 +86,13 @@ func (f *Compiler) Exec(step *Step) {
function := fn.UniqueName[dot+1:] function := fn.UniqueName[dot+1:]
f.Assembler.Append(&asm.CallExtern{Library: library, Function: function}) f.Assembler.Append(&asm.CallExtern{Library: library, Function: function})
if step.Register == -1 || step.Register == f.CPU.Return[0] { if step.Register == -1 || step.Register == f.CPU.ExternCall.Out[0] {
return return
} }
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register, Destination: step.Register,
Source: f.CPU.Return[0], Source: f.CPU.ExternCall.Out[0],
}) })
case *ssa.Int: case *ssa.Int:
@ -102,7 +102,7 @@ func (f *Compiler) Exec(step *Step) {
}) })
case *ssa.Parameter: case *ssa.Parameter:
source := f.CPU.Call[instr.Index] source := f.CPU.Call.In[instr.Index]
if step.Register == -1 || step.Register == source { if step.Register == -1 || step.Register == source {
return return
@ -129,9 +129,9 @@ func (f *Compiler) Exec(step *Step) {
case *ssa.Syscall: case *ssa.Syscall:
for i, arg := range instr.Arguments { for i, arg := range instr.Arguments {
if f.ValueToStep[arg].Register != f.CPU.Syscall[i] { if f.ValueToStep[arg].Register != f.CPU.Syscall.In[i] {
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Syscall[i], Destination: f.CPU.Syscall.In[i],
Source: f.ValueToStep[arg].Register, Source: f.ValueToStep[arg].Register,
}) })
} }
@ -139,13 +139,13 @@ func (f *Compiler) Exec(step *Step) {
f.Assembler.Append(&asm.Syscall{}) f.Assembler.Append(&asm.Syscall{})
if step.Register == -1 || step.Register == f.CPU.Return[0] { if step.Register == -1 || step.Register == f.CPU.Syscall.Out[0] {
return return
} }
f.Assembler.Append(&asm.MoveRegisterRegister{ f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register, Destination: step.Register,
Source: f.CPU.Return[0], Source: f.CPU.Syscall.Out[0],
}) })
} }
} }

View file

@ -21,10 +21,33 @@ const (
R15 R15
) )
var CPU = cpu.CPU{ var (
Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, LinuxCPU = cpu.CPU{
Syscall: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, Call: cpu.ABI{
ExternCall: []cpu.Register{R1, R2, R8, R9}, In: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
ExternCallVolatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11}, Out: []cpu.Register{R0, R7, R6},
Return: []cpu.Register{R0, R7, R6}, Volatile: []cpu.Register{R0, R1, R2, R6, R7, R8, R9, R10, R11},
} },
ExternCall: cpu.ABI{
In: []cpu.Register{R7, R6, R2, R1, R8, R9},
Out: []cpu.Register{R0, R2},
Volatile: []cpu.Register{R0, R1, R2, R6, R7, R8, R9, R10, R11},
},
Syscall: cpu.ABI{
In: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
Out: []cpu.Register{R0},
Volatile: []cpu.Register{R0, R7, R6},
},
}
MacCPU = LinuxCPU
WindowsCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: cpu.ABI{
In: []cpu.Register{R1, R2, R8, R9},
Out: []cpu.Register{R0},
Volatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11},
},
}
)