kit

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

abi_aapcs64.c (3739B)


      1 /* AAPCS64 (AArch64 SysV) ABI dispatch.
      2  *
      3  * v1 covers the cases the cg test harness exercises:
      4  *   void          -> IGNORE
      5  *   integer ≤ 8B  -> DIRECT, one INT part in a register
      6  *   integer 16B   -> DIRECT, two INT parts (X0+X1)
      7  *   pointer       -> DIRECT, one INT part in a register
      8  *   float/double  -> DIRECT, one FP part in a register
      9  *   small struct  -> DIRECT, INT parts (HFA/HVA refinement: TODO)
     10  *   large struct  -> INDIRECT (sret for return; passed by reference)
     11  * Variadics, HFA classification, and split GPR+stack tail still
     12  * land with the parser. */
     13 
     14 #include <string.h>
     15 
     16 #include "abi/abi_internal.h"
     17 #include "cg/type.h"
     18 #include "core/arena.h"
     19 #include "core/core.h"
     20 
     21 static void classify_scalar(TargetABI* a, KitCgTypeId t, ABIArgInfo* out) {
     22   ABITypeInfo ti = abi_cg_type_info(a, t);
     23   if (ti.scalar_kind == ABI_SC_INT && ti.size == 16) {
     24     abi_classify_int128_pair(a, out);
     25     return;
     26   }
     27   abi_classify_scalar_reg_part(a, out, ti, ti.scalar_kind == ABI_SC_FLOAT);
     28 }
     29 
     30 static void classify_aggregate(TargetABI* a, KitCgTypeId t, ABIArgInfo* out,
     31                                int is_return) {
     32   ABITypeInfo ti = abi_cg_type_info(a, t);
     33   if (ti.size == 0) {
     34     abi_classify_void(out);
     35     return;
     36   }
     37   /* AAPCS64: aggregates ≤ 16 bytes pass in up to 2 GPRs (or HFA in FP regs;
     38    * v1 ignores HFA). Larger aggregates pass by reference (caller copy for
     39    * args, sret pointer for return). */
     40   if (ti.size <= 16) {
     41     u32 nparts = (ti.size + 7) / 8;
     42     ABIArgPart* parts = arena_array(a->c->tu, ABIArgPart, nparts);
     43     memset(parts, 0, sizeof(ABIArgPart) * nparts);
     44     u32 off = 0;
     45     for (u32 i = 0; i < nparts; ++i) {
     46       u32 chunk = (ti.size - off > 8) ? 8 : (ti.size - off);
     47       parts[i].cls = ABI_CLASS_INT;
     48       parts[i].loc = ABI_LOC_REG;
     49       parts[i].size = chunk;
     50       parts[i].align = 8;
     51       parts[i].src_offset = off;
     52       off += chunk;
     53     }
     54     out->kind = ABI_ARG_DIRECT;
     55     out->flags = ABI_AF_NONE;
     56     out->parts = parts;
     57     out->nparts = nparts;
     58     out->indirect_align = 0;
     59   } else {
     60     out->kind = ABI_ARG_INDIRECT;
     61     out->flags = is_return ? ABI_AF_SRET : ABI_AF_BYVAL;
     62     out->indirect_align = ti.align;
     63     out->parts = NULL;
     64     out->nparts = 0;
     65   }
     66 }
     67 
     68 static void classify_one(TargetABI* a, KitCgTypeId t, ABIArgInfo* out,
     69                          int is_return) {
     70   const CgType* ty = cg_type_get(a->c, t);
     71   if (!ty || ty->kind == KIT_CG_TYPE_VOID) {
     72     abi_classify_void(out);
     73     return;
     74   }
     75   switch (ty->kind) {
     76     case KIT_CG_TYPE_RECORD:
     77       classify_aggregate(a, t, out, is_return);
     78       return;
     79     default:
     80       classify_scalar(a, t, out);
     81       return;
     82   }
     83 }
     84 
     85 /* Non-static so apple_arm64_compute_func_info can delegate to it during
     86  * the Phase 1 alias period — see abi_apple_arm64.c. */
     87 ABIFuncInfo* aapcs64_compute_func_info(TargetABI* a, KitCgTypeId fn) {
     88   /* AArch64 returns the sret pointer in the dedicated x8 register, so it never
     89    * consumes an x0..x7 argument slot: sret_consumes_int_arg stays 0. */
     90   return abi_compute_func_info_generic(a, fn, classify_one,
     91                                        /*sret_consumes_int_arg=*/0);
     92 }
     93 
     94 const ABIVtable aapcs64_vtable = {
     95     .compute_func_info = aapcs64_compute_func_info,
     96     .va_list_info = {32, 8, ABI_SC_VOID, 0, 0, 0},
     97     .va_list_layout = {.kind = ABI_VA_LIST_AAPCS64,
     98                        .stack_offset = 0,
     99                        .gr_top_offset = 8,
    100                        .vr_top_offset = 16,
    101                        .gr_offs_offset = 24,
    102                        .vr_offs_offset = 28,
    103                        .gp_reg_count = 8,
    104                        .fp_reg_count = 8,
    105                        .gp_slot_size = 8,
    106                        .fp_slot_size = 16},
    107 };