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