kit

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

abi_internal.h (4978B)


      1 #ifndef KIT_ABI_INTERNAL_H
      2 #define KIT_ABI_INTERNAL_H
      3 
      4 #include "abi/abi.h"
      5 #include "core/hashmap.h"
      6 
      7 /* Internal: per-ABI dispatch table.
      8  *
      9  * Selected by abi_init based on (target.arch, target.os). The pieces here
     10  * are the parts that vary by ABI; the C-standard-driven scalar profile and
     11  * record layout live in abi.c and are shared. */
     12 
     13 typedef struct ABIVtable {
     14   /* Compute the ABIFuncInfo for a function type. The cache wrapper in
     15    * abi.c calls this once per CgTypeId and memoizes the result. */
     16   ABIFuncInfo* (*compute_func_info)(TargetABI*, KitCgTypeId fn);
     17   /* Optional. Return the byte width of each lane when a scalar has to be
     18    * lowered by generic CG as multiple addressable machine-word lanes, or 0
     19    * when the target ABI treats it as one scalar value. */
     20   u32 (*scalar_split_lane_size)(TargetABI*, KitCgTypeId);
     21   /* The single source of truth for the va_list ABITypeInfo. abi_va_list_layout
     22    * always derives ABIVaListInfo.type from this, so vtables leave
     23    * va_list_layout.type zero-initialized rather than restating it. */
     24   ABITypeInfo va_list_info;
     25   ABIVaListInfo va_list_layout;
     26   /* Stack-probe granularity. 0 = the target OS auto-grows the stack on any
     27    * access below SP, so no probe is needed (Linux/macOS/FreeBSD). Non-zero =
     28    * the page size the prologue must touch, in descending order, before a
     29    * single large `sub sp` jumps past uncommitted guard pages (Windows). */
     30   u32 stack_probe_interval;
     31 } ABIVtable;
     32 
     33 /* Per-ABI vtables exposed by their TUs. */
     34 extern const ABIVtable aapcs64_vtable;
     35 extern const ABIVtable sysv_x64_vtable;
     36 extern const ABIVtable rv64_vtable;
     37 extern const ABIVtable rv32_vtable;
     38 extern const ABIVtable aapcs32_vtable;
     39 extern const ABIVtable wasm32_vtable;
     40 /* Apple Darwin variants — selected when (arch, os) matches.  See
     41  * abi.c::select_vtable. */
     42 extern const ABIVtable apple_arm64_vtable;
     43 extern const ABIVtable apple_x64_vtable;
     44 /* Windows variants — selected when os == KIT_OS_WINDOWS. */
     45 extern const ABIVtable win64_x64_vtable;
     46 extern const ABIVtable aapcs64_windows_vtable;
     47 
     48 const ABIVtable* abi_vtable_lookup(KitArchKind arch, KitObjFmt obj);
     49 
     50 /* Shared TargetABI internals. The struct definition is here so each ABI
     51  * TU can reach into the per-TU caches via TargetABI*. abi.c owns the
     52  * cache plumbing; the per-ABI TUs only allocate ABIFuncInfo / record
     53  * builders out of c->tu. */
     54 
     55 /* Per-(function/record) ABI-info caches, keyed by the CgTypeId. A type id is
     56  * always nonzero for a real lookup (cg_type_get(0) fails before the cache), so
     57  * 0 is a safe empty-slot sentinel. O(1) probe replaces what were linearly
     58  * scanned linked lists — O(#distinct types) per query, i.e. O(n^2) over a
     59  * type-heavy TU. The cached values stay arena-allocated (per-TU lifetime); only
     60  * the index structure lives on the compiler heap and is freed at abi_fini. */
     61 KIT_HASHMAP_DEFINE(AbiFnInfoMap, u32, ABIFuncInfo*, hash_u32);
     62 KIT_HASHMAP_DEFINE(AbiRecLayoutMap, u32, ABIRecordLayout*, hash_u32);
     63 
     64 struct TargetABI {
     65   Compiler* c;
     66   const ABIVtable* vt;
     67   AbiFnInfoMap fn_cache;
     68   AbiRecLayoutMap rec_cache;
     69 };
     70 
     71 /* Shared classifier primitives implemented in abi.c. The byte-identical
     72  * building blocks the per-ABI classifiers (sysv_x64 / win64_x64 / aapcs64 /
     73  * rv64) reuse; ABI-specific scalar/aggregate rules stay in those TUs. */
     74 void abi_classify_void(ABIArgInfo* out);
     75 void abi_classify_int128_pair(TargetABI* a, ABIArgInfo* out);
     76 
     77 /* The single-register scalar tail shared by every per-ABI classify_scalar:
     78  * a DIRECT argument with one register part carrying the whole scalar. `is_fp`
     79  * selects ABI_CLASS_FP vs ABI_CLASS_INT for the part (the per-ABI caller has
     80  * already applied its own FP-eligibility rule). */
     81 void abi_classify_scalar_reg_part(TargetABI* a, ABIArgInfo* out, ABITypeInfo ti,
     82                                   int is_fp);
     83 
     84 /* The per-argument dispatch each ABI plugs into the generic driver: classify a
     85  * single function argument/result `t` into `out` (`is_return` chooses
     86  * sret vs byval for indirect aggregates). */
     87 typedef void (*ABIClassifyOneFn)(TargetABI* a, KitCgTypeId t, ABIArgInfo* out,
     88                                  int is_return);
     89 
     90 /* Generic compute_func_info scaffold shared by the per-ABI vtables: allocate
     91  * the ABIFuncInfo, classify the result and every parameter through
     92  * `classify_one`, and fill the shared has_sret / variadic / nparams fields.
     93  * `sret_consumes_int_arg` is stored verbatim into ABIFuncInfo.has_sret's
     94  * companion flag (ABIs that return the sret pointer in a dedicated register
     95  * pass 0; ABIs that consume the first integer arg slot pass has_sret-derived 1
     96  * by setting this to nonzero). The ABI-specific vararg metadata pass (SysV-x64)
     97  * runs in the caller on the returned info. */
     98 ABIFuncInfo* abi_compute_func_info_generic(TargetABI* a, KitCgTypeId fn,
     99                                            ABIClassifyOneFn classify_one,
    100                                            int sret_consumes_int_arg);
    101 
    102 #endif