Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657package codegen
import ( "slices"
"git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/cpu" "git.urbach.dev/cli/q/src/ssa")
func (f *Function) executeCallExtern(step *Step, instr *ssa.CallExtern) { args := instr.Arguments var pushed []cpu.Register
for i, arg := range slices.Backward(args) { argStep := f.ValueToStep[arg] source := f.resolveOperand(argStep, step.Live)
if i >= len(f.CPU.ExternCall.In) { pushed = append(pushed, source) continue }
if source == f.CPU.ExternCall.In[i] { continue }
f.Assembler.Append(&asm.Move{ Destination: f.CPU.ExternCall.In[i], Source: source, }) }
// Pushing an odd number of registers would not maintain the 16-byte // stack alignment, so we allocate additional 8 bytes before pushing // the 5th argument. if len(pushed)&1 != 0 { f.Assembler.Append(&asm.SubtractNumber{Destination: f.CPU.StackPointer, Source: f.CPU.StackPointer, Number: 8}) }
// TODO: Replace push instructions with store instructions using a fixed offset. if len(pushed) > 0 { f.Assembler.Append(&asm.Push{Registers: pushed}) }
f.Assembler.Append(&asm.CallExtern{Library: instr.Func.Package(), Function: instr.Func.Name()})
if len(pushed) > 0 { f.Assembler.Append(&asm.Pop{Registers: pushed}) }
if len(pushed)&1 != 0 { f.Assembler.Append(&asm.AddNumber{Destination: f.CPU.StackPointer, Source: f.CPU.StackPointer, Number: 8}) }
f.moveCallResult(step, f.CPU.ExternCall.Out[0])}