Improved Windows x86-64 ABI support
All checks were successful
/ test (push) Successful in 29s

This commit is contained in:
Eduard Urbach 2025-07-05 22:27:01 +02:00
parent 8ea491bb92
commit 8d13f1ece8
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
6 changed files with 38 additions and 7 deletions

View file

@ -25,6 +25,9 @@ type CallExtern struct {
Function string
}
type CallExternStart struct{}
type CallExternEnd struct{}
type FunctionStart struct{}
type FunctionEnd struct{}
@ -51,6 +54,10 @@ type MoveRegisterRegister struct {
Source cpu.Register
}
type PushRegister struct {
Register cpu.Register
}
type Return struct{}
type SubRegisterNumber struct {

View file

@ -32,6 +32,12 @@ func (c *compilerARM) Compile(instr Instruction) {
offset := (address - start) / 4
binary.LittleEndian.PutUint32(c.code[start:start+4], arm.Call(offset))
})
case *CallExtern:
panic("not implemented")
case *CallExternStart:
panic("not implemented")
case *CallExternEnd:
panic("not implemented")
case *Jump:
start := len(c.code)
c.append(arm.Jump(0))
@ -76,6 +82,8 @@ func (c *compilerARM) Compile(instr Instruction) {
c.code = arm.MoveRegisterNumber(c.code, instr.Destination, instr.Number)
case *MoveRegisterRegister:
c.append(arm.MoveRegisterRegister(instr.Destination, instr.Source))
case *PushRegister:
panic("not implemented")
case *Return:
c.append(arm.Return())
case *Syscall:

View file

@ -41,12 +41,8 @@ func (c *compilerX86) Compile(instr Instruction) {
binary.LittleEndian.PutUint32(c.code[end-4:end], uint32(offset))
})
case *CallExtern:
c.code = x86.MoveRegisterRegister(c.code, x86.R5, x86.SP)
c.code = x86.AndRegisterNumber(c.code, x86.SP, -16)
c.code = x86.SubRegisterNumber(c.code, x86.SP, 32)
c.code = x86.CallAt(c.code, 0)
end := len(c.code)
c.code = x86.MoveRegisterRegister(c.code, x86.SP, x86.R5)
c.Defer(func() {
index := c.libraries.Index(instr.Library, instr.Function)
@ -59,6 +55,12 @@ func (c *compilerX86) Compile(instr Instruction) {
offset := address - end
binary.LittleEndian.PutUint32(c.code[end-4:end], uint32(offset))
})
case *CallExternStart:
c.code = x86.MoveRegisterRegister(c.code, x86.R5, x86.SP)
c.code = x86.AndRegisterNumber(c.code, x86.SP, -16)
c.code = x86.SubRegisterNumber(c.code, x86.SP, 32)
case *CallExternEnd:
c.code = x86.MoveRegisterRegister(c.code, x86.SP, x86.R5)
case *FunctionStart:
case *FunctionEnd:
case *Jump:
@ -100,6 +102,8 @@ func (c *compilerX86) Compile(instr Instruction) {
c.code = x86.MoveRegisterNumber(c.code, instr.Destination, instr.Number)
case *MoveRegisterRegister:
c.code = x86.MoveRegisterRegister(c.code, instr.Destination, instr.Source)
case *PushRegister:
c.code = x86.PushRegister(c.code, instr.Register)
case *Return:
c.code = x86.Return(c.code)
case *SubRegisterNumber:

View file

@ -41,6 +41,12 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
case *ssa.CallExtern:
for r, param := range instr.Arguments[1:] {
if r >= len(f.CPU.ExternCall.In) {
// Temporary hack to allow arguments 5 and 6 to be hinted as r10 and r11, then pushed later.
f.ValueToStep[param].Hint(f.CPU.ExternCall.Volatile[1+r])
continue
}
f.ValueToStep[param].Hint(f.CPU.ExternCall.In[r])
}

View file

@ -69,10 +69,15 @@ func (f *Compiler) Exec(step *Step) {
})
case *ssa.CallExtern:
f.Assembler.Append(&asm.CallExternStart{})
args := instr.Arguments[1:]
for i, arg := range args {
if f.ValueToStep[arg].Register != f.CPU.ExternCall.In[i] {
if i >= len(f.CPU.ExternCall.In) {
f.Assembler.Append(&asm.PushRegister{
Register: f.ValueToStep[arg].Register,
})
} else if f.ValueToStep[arg].Register != f.CPU.ExternCall.In[i] {
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.ExternCall.In[i],
Source: f.ValueToStep[arg].Register,
@ -85,6 +90,7 @@ func (f *Compiler) Exec(step *Step) {
library := fn.UniqueName[:dot]
function := fn.UniqueName[dot+1:]
f.Assembler.Append(&asm.CallExtern{Library: library, Function: function})
f.Assembler.Append(&asm.CallExternEnd{})
if step.Register == -1 || step.Register == f.CPU.ExternCall.Out[0] {
return