abi_aapcs64_windows.c (3096B)
1 /* Windows-on-ARM64 ABI dispatch. 2 * 3 * Vtable selection keys on (target.arch, target.os); (ARM_64, WINDOWS) 4 * lands here instead of AAPCS64. The two ABIs diverge in: 5 * 6 * 1. va_list shape — Windows-ARM64 `__builtin_va_list` is plain 7 * `void*`; AAPCS64 is a five-field struct. 8 * 9 * 2. long double — 64-bit double on Windows-ARM64 (AAPCS64: 128-bit). 10 * Assumed lowered by the front end before classification. 11 * 12 * Variadics still use registers (NOT all-on-stack like Apple ARM64), but 13 * FP arguments to variadic functions are routed through integer slots so 14 * `va_list` can remain a plain pointer. 15 * 16 * Classification starts from aapcs64_compute_func_info, then adjusts FP 17 * parameter parts for variadic functions. */ 18 19 #include <string.h> 20 21 #include "abi/abi_internal.h" 22 #include "core/arena.h" 23 #include "core/core.h" 24 25 extern ABIFuncInfo* aapcs64_compute_func_info(TargetABI*, KitCgTypeId); 26 27 static void remap_fp_parts_to_int(TargetABI* a, ABIArgInfo* ai) { 28 if (!ai || ai->kind != ABI_ARG_DIRECT || ai->nparts == 0) return; 29 int needs_copy = 0; 30 for (u16 i = 0; i < ai->nparts; ++i) { 31 if (ai->parts[i].cls == ABI_CLASS_FP) { 32 needs_copy = 1; 33 break; 34 } 35 } 36 if (!needs_copy) return; 37 38 ABIArgPart* parts = arena_array(a->c->tu, ABIArgPart, ai->nparts); 39 memcpy(parts, ai->parts, sizeof(ABIArgPart) * ai->nparts); 40 for (u16 i = 0; i < ai->nparts; ++i) { 41 if (parts[i].cls == ABI_CLASS_FP) parts[i].cls = ABI_CLASS_INT; 42 } 43 ai->parts = parts; 44 } 45 46 static ABIFuncInfo* aapcs64_windows_compute_func_info(TargetABI* a, 47 KitCgTypeId fn) { 48 ABIFuncInfo* info = aapcs64_compute_func_info(a, fn); 49 /* vararg_on_stack stays 0 — Windows-ARM64 variadics use registers, 50 * unlike Apple. 51 * 52 * In a variadic function, Windows ARM64 routes floating-point arguments 53 * through the integer argument slots. That applies to named FP parameters 54 * too; trailing `...` arguments are handled by the call lowering path. */ 55 if (info && info->variadic) { 56 /* Trait the aarch64 backend reads instead of checking target.os; the 57 * named FP parameters are remapped here, trailing `...` FP args are 58 * handled by the call lowering path off the same flag. */ 59 info->vararg_fp_via_int = 1; 60 for (u16 i = 0; i < info->nparams; ++i) { 61 remap_fp_parts_to_int(a, (ABIArgInfo*)&info->params[i]); 62 } 63 } 64 return info; 65 } 66 67 const ABIVtable aapcs64_windows_vtable = { 68 .compute_func_info = aapcs64_windows_compute_func_info, 69 /* Windows commits stack one guard page at a time; large frames must be 70 * probed page-by-page before the single `sub sp`. See aa_words_stack_probe 71 * in src/arch/aa64/native.c. */ 72 .stack_probe_interval = 4096, 73 .va_list_info = {8, 8, ABI_SC_PTR, 0, 0, 0}, 74 .va_list_layout = {.type = {8, 8, ABI_SC_PTR, 0, 0, 0}, 75 .kind = ABI_VA_LIST_POINTER, 76 .gp_reg_count = 8, 77 .fp_reg_count = 0, 78 .gp_slot_size = 8, 79 .fp_slot_size = 0}, 80 };