Skip to content

Commit 4cfef06

Browse files
committed
merge
2 parents ca2ddd2 + 607e025 commit 4cfef06

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

source/backends/arm64.d

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,23 +419,68 @@ class BackendARM64 : CompilerBackend {
419419
output ~= format("bl %s\n", ExternSymbol(node.name));
420420
}
421421
else if (word.type == WordType.C) {
422-
// TODO: support more of the calling convention (especially structs)
422+
// Calling convention (simplified):
423+
// First 8 parameters in x0-x7
424+
// All remaining parameters on the stack
425+
// On Linux, these are extended to 8 bytes
426+
// Return value in x0
427+
// sp must be 16-byte aligned when used
428+
429+
output ~= "mov x9, sp\n";
430+
output ~= "str x9, [x20, #-8]!\n";
431+
output ~= "and sp, x20, ~0xf\n";
432+
433+
ulong registerParams = min(word.params.length, 8);
434+
ulong stackParams = word.params.length - registerParams;
423435

424436
if (word.params.length > 8) {
425-
Error(node.error, "C call has too many parameters");
437+
ulong stackSpace = 0;
438+
if (os == "osx") {
439+
for (auto i = 8; i < word.params.length; i++) {
440+
stackSpace += word.params[i].size;
441+
}
442+
}
443+
else {
444+
stackSpace = stackParams * 8;
445+
}
446+
ulong stackOffset = stackSpace;
447+
448+
// Ensure 16-byte alignment of the stack
449+
stackSpace = (stackSpace + 15) & ~15;
450+
output ~= format("sub sp, sp, #%d\n", stackSpace);
451+
452+
for (auto i = 0; i < stackParams; i++) {
453+
output ~= "ldr x9, [x19, #-8]!\n";
454+
if (os == "osx") {
455+
auto size = word.params[i + 8].size;
456+
stackOffset -= size;
457+
switch (size) {
458+
case 1: output ~= format("strb w9, [sp, #%d]\n", stackOffset); break;
459+
case 2: output ~= format("strh w9, [sp, #%d]\n", stackOffset); break;
460+
case 4: output ~= format("str w9, [sp, #%d]\n", stackOffset); break;
461+
case 8: output ~= format("str x9, [sp, #%d]\n", stackOffset); break;
462+
default: Error(node.error, "Invalid C function argument size");
463+
}
464+
}
465+
else {
466+
stackOffset -= 8;
467+
output ~= format("str x9, [sp, #%d]\n", stackOffset);
468+
}
469+
}
426470
}
427471

428-
for (auto i = 0; i < word.params.length; i++) {
429-
auto reg = word.params.length - i - 1;
430-
output ~= format("ldr x%d, [x19, #-8]!\n", reg);
472+
for (int i = cast(int) registerParams - 1; i >= 0; i--) {
473+
output ~= format("ldr x%d, [x19, #-8]!\n", i);
431474
}
432475

433-
output ~= "and sp, x20, ~0xf\n";
434476
output ~= format("bl %s\n", ExternSymbol(word.symbolName));
435477

436478
if (!word.isVoid) {
437479
output ~= "str x0, [x19], #8\n";
438480
}
481+
482+
output ~= "ldr x9, [x20], #8\n";
483+
output ~= "mov sp, x9\n";
439484
}
440485
else {
441486
if (word.error) {

0 commit comments

Comments
 (0)