kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 };