@@ -419,23 +419,68 @@ class BackendARM64 : CompilerBackend {
419
419
output ~= format(" bl %s\n " , ExternSymbol(node.name));
420
420
}
421
421
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;
423
435
424
436
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
+ }
426
470
}
427
471
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);
431
474
}
432
475
433
- output ~= " and sp, x20, ~0xf\n " ;
434
476
output ~= format(" bl %s\n " , ExternSymbol(word.symbolName));
435
477
436
478
if (! word.isVoid) {
437
479
output ~= " str x0, [x19], #8\n " ;
438
480
}
481
+
482
+ output ~= " ldr x9, [x20], #8\n " ;
483
+ output ~= " mov sp, x9\n " ;
439
484
}
440
485
else {
441
486
if (word.error) {
0 commit comments