kit

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

abi_aapcs64.c (5440B)


      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_internal_type_info(a, t);
     23   if (ti.scalar_kind == ABI_SC_INT && ti.size == 16) {
     24     ABIArgPart* parts = arena_array(a->c->tu, ABIArgPart, 2);
     25     memset(parts, 0, sizeof(ABIArgPart) * 2);
     26     for (u32 i = 0; i < 2; ++i) {
     27       parts[i].cls = ABI_CLASS_INT;
     28       parts[i].loc = ABI_LOC_REG;
     29       parts[i].size = 8;
     30       parts[i].align = 8;
     31       parts[i].src_offset = i * 8;
     32     }
     33     out->kind = ABI_ARG_DIRECT;
     34     out->flags = ABI_AF_NONE;
     35     out->parts = parts;
     36     out->nparts = 2;
     37     out->indirect_align = 0;
     38     return;
     39   }
     40   out->kind = ABI_ARG_DIRECT;
     41   out->flags = ABI_AF_NONE;
     42   out->indirect_align = 0;
     43 
     44   ABIArgPart* parts = arena_new(a->c->tu, ABIArgPart);
     45   memset(parts, 0, sizeof *parts);
     46   parts->cls = (ti.scalar_kind == ABI_SC_FLOAT) ? ABI_CLASS_FP : ABI_CLASS_INT;
     47   parts->loc = ABI_LOC_REG;
     48   parts->size = ti.size;
     49   parts->align = ti.align;
     50   parts->src_offset = 0;
     51 
     52   out->parts = parts;
     53   out->nparts = 1;
     54 }
     55 
     56 static void classify_void(ABIArgInfo* out) {
     57   memset(out, 0, sizeof *out);
     58   out->kind = ABI_ARG_IGNORE;
     59 }
     60 
     61 static void classify_aggregate(TargetABI* a, KitCgTypeId t, ABIArgInfo* out,
     62                                int is_return) {
     63   ABITypeInfo ti = abi_internal_type_info(a, t);
     64   if (ti.size == 0) {
     65     classify_void(out);
     66     return;
     67   }
     68   /* AAPCS64: aggregates ≤ 16 bytes pass in up to 2 GPRs (or HFA in FP regs;
     69    * v1 ignores HFA). Larger aggregates pass by reference (caller copy for
     70    * args, sret pointer for return). */
     71   if (ti.size <= 16) {
     72     u32 nparts = (ti.size + 7) / 8;
     73     ABIArgPart* parts = arena_array(a->c->tu, ABIArgPart, nparts);
     74     memset(parts, 0, sizeof(ABIArgPart) * nparts);
     75     u32 off = 0;
     76     for (u32 i = 0; i < nparts; ++i) {
     77       u32 chunk = (ti.size - off > 8) ? 8 : (ti.size - off);
     78       parts[i].cls = ABI_CLASS_INT;
     79       parts[i].loc = ABI_LOC_REG;
     80       parts[i].size = chunk;
     81       parts[i].align = 8;
     82       parts[i].src_offset = off;
     83       off += chunk;
     84     }
     85     out->kind = ABI_ARG_DIRECT;
     86     out->flags = ABI_AF_NONE;
     87     out->parts = parts;
     88     out->nparts = (u16)nparts;
     89     out->indirect_align = 0;
     90   } else {
     91     out->kind = ABI_ARG_INDIRECT;
     92     out->flags = is_return ? ABI_AF_SRET : ABI_AF_BYVAL;
     93     out->indirect_align = ti.align;
     94     out->parts = NULL;
     95     out->nparts = 0;
     96   }
     97 }
     98 
     99 static void classify_one(TargetABI* a, KitCgTypeId t, ABIArgInfo* out,
    100                          int is_return) {
    101   const CgType* ty = cg_type_get(a->c, t);
    102   if (!ty || ty->kind == KIT_CG_TYPE_VOID) {
    103     classify_void(out);
    104     return;
    105   }
    106   switch (ty->kind) {
    107     case KIT_CG_TYPE_RECORD:
    108       classify_aggregate(a, t, out, is_return);
    109       return;
    110     case KIT_CG_TYPE_ALIAS:
    111       classify_one(a, ty->alias.base, out, is_return);
    112       return;
    113     default:
    114       classify_scalar(a, t, out);
    115       return;
    116   }
    117 }
    118 
    119 /* Non-static so apple_arm64_compute_func_info can delegate to it during
    120  * the Phase 1 alias period — see abi_apple_arm64.c. */
    121 ABIFuncInfo* aapcs64_compute_func_info(TargetABI* a, KitCgTypeId fn) {
    122   ABIFuncInfo* info = arena_new(a->c->tu, ABIFuncInfo);
    123   const CgType* fnty = cg_type_get(a->c, fn);
    124   memset(info, 0, sizeof *info);
    125 
    126   classify_one(a, cg_func_ret_type(fnty), &info->ret, /*is_return=*/1);
    127   info->has_sret = (info->ret.kind == ABI_ARG_INDIRECT) ? 1 : 0;
    128   /* AArch64 returns the sret pointer in the dedicated x8 register, so it never
    129    * consumes an x0..x7 argument slot. (memset above already cleared the field;
    130    * set explicitly for documentation.) */
    131   info->sret_consumes_int_arg = 0;
    132   info->variadic = fnty->func.abi_variadic;
    133 
    134   info->nparams = (u16)fnty->func.nparams;
    135   if (fnty->func.nparams) {
    136     ABIArgInfo* arr = arena_array(a->c->tu, ABIArgInfo, fnty->func.nparams);
    137     memset(arr, 0, sizeof(ABIArgInfo) * fnty->func.nparams);
    138     for (u32 i = 0; i < fnty->func.nparams; ++i) {
    139       classify_one(a, fnty->func.params[i].type, &arr[i], /*is_return=*/0);
    140     }
    141     info->params = arr;
    142   } else {
    143     info->params = NULL;
    144   }
    145   return info;
    146 }
    147 
    148 const ABIVtable aapcs64_vtable = {
    149     .compute_func_info = aapcs64_compute_func_info,
    150     .va_list_info = {32, 8, ABI_SC_VOID, 0, 0, 0},
    151     .va_list_layout = {.type = {32, 8, ABI_SC_VOID, 0, 0, 0},
    152                        .kind = ABI_VA_LIST_AAPCS64,
    153                        .stack_offset = 0,
    154                        .gr_top_offset = 8,
    155                        .vr_top_offset = 16,
    156                        .gr_offs_offset = 24,
    157                        .vr_offs_offset = 28,
    158                        .gp_reg_count = 8,
    159                        .fp_reg_count = 8,
    160                        .gp_slot_size = 8,
    161                        .fp_slot_size = 16},
    162 };