kit

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

internal.h (34311B)


      1 #ifndef KIT_CG_INTERNAL_H
      2 #define KIT_CG_INTERNAL_H
      3 
      4 #include <kit/cg.h>
      5 #include <stdarg.h>
      6 #include <stdint.h>
      7 #include <stdio.h>
      8 #include <string.h>
      9 
     10 #include "abi/abi.h"
     11 #include "asm/asm.h"
     12 #include "cg/cgtarget.h"
     13 #include "cg/type.h"
     14 #include "core/arena.h"
     15 #include "core/heap.h"
     16 #include "core/pool.h"
     17 #include "core/segvec.h"
     18 #include "core/slice.h"
     19 #include "core/strbuf.h"
     20 #include "debug/debug.h"
     21 #include "obj/obj.h"
     22 
     23 typedef uint32_t ObjSymId;
     24 
     25 typedef enum SResidency {
     26   RES_INHERENT,
     27   RES_LOCAL,
     28   RES_FIXED_LOCAL,
     29 } SResidency;
     30 
     31 typedef enum ApiSValueKind {
     32   SV_OPERAND,
     33   SV_CMP,
     34   SV_ARITH,
     35 } ApiSValueKind;
     36 
     37 typedef enum ApiDelayedArithKind {
     38   API_DELAYED_UNOP,
     39   API_DELAYED_BINOP,
     40 } ApiDelayedArithKind;
     41 
     42 typedef struct ApiDelayedCmp {
     43   Operand a;
     44   Operand b;
     45   CmpOp op;
     46   u8 a_owned;
     47   u8 b_owned;
     48   u8 pad[2];
     49 } ApiDelayedCmp;
     50 
     51 typedef struct ApiDelayedArith {
     52   Operand a;
     53   Operand b;
     54   BinOp bin_op;
     55   UnOp un_op;
     56   u8 kind;
     57   u8 a_owned;
     58   u8 b_owned;
     59   u8 pad;
     60 } ApiDelayedArith;
     61 
     62 /* The delayed cmp/arith payload of an SV_CMP / SV_ARITH value. It is held off
     63  * the hot value-stack node (ApiSValue carries only an ApiDelayed*, NULL for the
     64  * common SV_OPERAND case) so the node stays small and its per-push construction
     65  * touches no delayed state. Payloads are pooled per function (api_delayed_alloc
     66  * / _free, arena-backed with a freelist; see fold.c). `next_free` overlays the
     67  * payload while it sits on the freelist. */
     68 typedef union ApiDelayed {
     69   ApiDelayedCmp cmp;
     70   ApiDelayedArith arith;
     71   union ApiDelayed* next_free;
     72 } ApiDelayed;
     73 
     74 /* The scalar wide-class tag (ApiWideKind) and the packed per-type
     75  * classification it feeds (api_type_class) live in cg/type.h, with the rest of
     76  * the type-property queries. The value stack only stores the result (the
     77  * one-byte tag below) and reads it back. */
     78 
     79 /* Bit-field geometry carried by a bit-field PLACE. `kit_cg_field` fills this
     80  * from the record layout when it projects to a bit-field; a plain load/store on
     81  * the carrying place then performs the extract/insert. The storage MemAccess is
     82  * rebuilt from the place operand + field type at load/store time, so only the
     83  * bit geometry needs to ride on the place. width == 0 means "not a bit-field".
     84  *
     85  * `wide_kind` (ApiWideKind) rides in this struct's trailing slack: it is the
     86  * only one-byte hole in the value-stack node, and keeping it here leaves the
     87  * node size unchanged (static_assert in value.c). It is node state, not bit
     88  * geometry, so kit_cg_field_bits writes only the bit_* members and leaves it
     89  * intact, and node copies (dup/swap/rot) carry it along with the type. */
     90 typedef struct ApiBitField {
     91   u16 bit_offset;       /* target-endian bit offset within the storage unit */
     92   u16 bit_width;        /* 0 => the place is not a bit-field place */
     93   u32 bit_storage_size; /* storage-unit size in bytes */
     94   u8 bit_signed;        /* signed extraction on load */
     95   u8 wide_kind;         /* ApiWideKind, cached at api_push (node slack) */
     96   u8 pad[2];
     97 } ApiBitField;
     98 
     99 typedef struct ApiSValue {
    100   Operand op;
    101   /* Pooled delayed cmp/arith payload, or NULL for the common SV_OPERAND value.
    102    * A pointer (not the 64-byte union inline) keeps the node small; only the
    103    * SV_CMP / SV_ARITH producers in fold.c allocate one. */
    104   ApiDelayed* delayed;
    105   const void* lang_type; /* opaque frontend-owned slot fact */
    106   KitCgTypeId type;
    107   KitCgLocal source_local;
    108   ApiBitField bitfield; /* bit_width != 0 marks a bit-field PLACE subkind */
    109   u16 lang_flags;       /* frontend-defined flags; CG only copies/clears */
    110   u16 flags;            /* packed ApiSValueKind/SResidency/pinned/lvalue */
    111 } ApiSValue;
    112 
    113 typedef struct ApiConstValue {
    114   KitCgConstInt value;
    115   KitCgTypeId type;
    116 } ApiConstValue;
    117 
    118 #define API_CG_STACK_INITIAL 16u
    119 
    120 #define API_SV_KIND_SHIFT 0u
    121 #define API_SV_RES_SHIFT 2u
    122 #define API_SV_PINNED_SHIFT 4u
    123 #define API_SV_LVALUE_SHIFT 5u
    124 #define API_SV_KIND_MASK 0x3u
    125 #define API_SV_RES_MASK 0x3u
    126 #define API_SV_BOOL_MASK 0x1u
    127 #define API_SV_PACK(kind_, res_, pinned_, lvalue_)                      \
    128   ((u16)((((u16)(kind_) & API_SV_KIND_MASK) << API_SV_KIND_SHIFT) |     \
    129          (((u16)(res_) & API_SV_RES_MASK) << API_SV_RES_SHIFT) |        \
    130          (((u16)(pinned_) & API_SV_BOOL_MASK) << API_SV_PINNED_SHIFT) | \
    131          (((u16)(lvalue_) & API_SV_BOOL_MASK) << API_SV_LVALUE_SHIFT)))
    132 
    133 static inline ApiSValueKind api_sv_kind(const ApiSValue* sv) {
    134   return (ApiSValueKind)((sv->flags >> API_SV_KIND_SHIFT) & API_SV_KIND_MASK);
    135 }
    136 
    137 static inline void api_sv_set_kind(ApiSValue* sv, ApiSValueKind kind) {
    138   sv->flags = (u16)((sv->flags & ~(API_SV_KIND_MASK << API_SV_KIND_SHIFT)) |
    139                     (((u16)kind & API_SV_KIND_MASK) << API_SV_KIND_SHIFT));
    140 }
    141 
    142 static inline SResidency api_sv_res(const ApiSValue* sv) {
    143   return (SResidency)((sv->flags >> API_SV_RES_SHIFT) & API_SV_RES_MASK);
    144 }
    145 
    146 static inline void api_sv_set_res(ApiSValue* sv, SResidency res) {
    147   sv->flags = (u16)((sv->flags & ~(API_SV_RES_MASK << API_SV_RES_SHIFT)) |
    148                     (((u16)res & API_SV_RES_MASK) << API_SV_RES_SHIFT));
    149 }
    150 
    151 static inline int api_sv_pinned(const ApiSValue* sv) {
    152   return (int)((sv->flags >> API_SV_PINNED_SHIFT) & API_SV_BOOL_MASK);
    153 }
    154 
    155 static inline void api_sv_set_pinned(ApiSValue* sv, int pinned) {
    156   sv->flags = (u16)((sv->flags & ~(API_SV_BOOL_MASK << API_SV_PINNED_SHIFT)) |
    157                     (((u16)pinned & API_SV_BOOL_MASK) << API_SV_PINNED_SHIFT));
    158 }
    159 
    160 static inline int api_sv_lvalue_flag(const ApiSValue* sv) {
    161   return (int)((sv->flags >> API_SV_LVALUE_SHIFT) & API_SV_BOOL_MASK);
    162 }
    163 
    164 static inline void api_sv_set_lvalue(ApiSValue* sv, int lvalue) {
    165   sv->flags = (u16)((sv->flags & ~(API_SV_BOOL_MASK << API_SV_LVALUE_SHIFT)) |
    166                     (((u16)lvalue & API_SV_BOOL_MASK) << API_SV_LVALUE_SHIFT));
    167 }
    168 
    169 /* Largest scalar the codegen lowers as a native (lock-free) atomic. All
    170  * current targets — aa64, x64, rv64, wasm32 — provide 8-byte (i64-width)
    171  * atomics, so this is both the legality ceiling and the lock-free ceiling.
    172  * Note it is NOT the pointer width: wasm32 has 4-byte pointers but 8-byte
    173  * atomics. */
    174 #define CG_MAX_ATOMIC_SIZE 8u
    175 
    176 /* Arity that fits inline in an ApiCgScope without a heap allocation. The common
    177  * void/single-result scope (every C/toy statement) stays inline; a multi-value
    178  * block whose param or result count exceeds this spills its carry-local vectors
    179  * to one heap block (see api_scope_setup_sig), freed at scope_end. */
    180 #define API_CG_SCOPE_SIG_INLINE 4u
    181 
    182 typedef struct ApiCgScope {
    183   Label break_lbl;
    184   Label continue_lbl;
    185   CGScope target_scope;
    186   /* The carry locals (and their resolved types) that move the scope's results
    187    * across its exit edges and — for a loop — its params across back edges. A
    188    * value is stored into result_locals[i] before a break/end and reloaded after
    189    * the break label; loop params are snapshotted into param_locals[i] and
    190    * reloaded after the continue label. The pointers target the inline buffers
    191    * for small arity (no heap) or one heap block for larger; nresults<=1 and
    192    * nparams==0 reproduces the old single-result path byte-for-byte. */
    193   CGLocal* result_locals;
    194   KitCgTypeId* result_types;
    195   const void** result_lang_types;
    196   u16* result_lang_flags;
    197   CGLocal* param_locals;
    198   KitCgTypeId* param_types;
    199   const void** param_lang_types;
    200   u16* param_lang_flags;
    201   u32 nresults;
    202   u32 nparams;
    203   CGLocal result_locals_inl[API_CG_SCOPE_SIG_INLINE];
    204   KitCgTypeId result_types_inl[API_CG_SCOPE_SIG_INLINE];
    205   const void* result_lang_types_inl[API_CG_SCOPE_SIG_INLINE];
    206   u16 result_lang_flags_inl[API_CG_SCOPE_SIG_INLINE];
    207   CGLocal param_locals_inl[API_CG_SCOPE_SIG_INLINE];
    208   KitCgTypeId param_types_inl[API_CG_SCOPE_SIG_INLINE];
    209   const void* param_lang_types_inl[API_CG_SCOPE_SIG_INLINE];
    210   u16 param_lang_flags_inl[API_CG_SCOPE_SIG_INLINE];
    211   u32* heap_block; /* non-NULL when u32 arity vectors spilled to heap */
    212   const void** heap_lang_types_block;
    213   u16* heap_lang_flags_block;
    214   u32 generation;
    215   u8 active;
    216   u8 pad[3];
    217 } ApiCgScope;
    218 
    219 /* Upper bound on live (LIFO-nested) control scopes. This is the limit the
    220  * scope handle can encode, not a preallocated size: g->scopes grows on
    221  * demand (api_grow_scopes). The handle packs the 1-based scope index into
    222  * its low 16 bits (api_scope_handle), so a depth of 0xffff is the most that
    223  * remains addressable. Real translation units nest a few hundred deep at
    224  * most; this ceiling exists only to keep the handle representable. */
    225 #define API_CG_MAX_SCOPES 0xffffu
    226 
    227 typedef enum ApiSourceLocalKind {
    228   API_SOURCE_LOCAL_AUTO,
    229   API_SOURCE_LOCAL_PARAM,
    230 } ApiSourceLocalKind;
    231 
    232 typedef struct ApiSourceLocal {
    233   KitCgTypeId type;
    234   KitSym name;
    235   KitCgLocalAttrs attrs;
    236   SrcLoc loc;
    237   CGLocalDesc desc;
    238   CGLocal storage;
    239   i64 const_value;
    240   /* Intrusive link for the const-active list (KitCg.const_head; see fold.c).
    241    * KIT_CG_LOCAL_NONE terminates. const_listed marks membership so a re-store
    242    * does not double-link; it stays set (the entry lingers as a cleared no-op)
    243    * until the next boundary drains the list. */
    244   KitCgLocal const_next;
    245   u32 param_index;
    246   u8 kind;
    247   u8 const_valid;
    248   u8 const_listed;
    249   u8 pad[1];
    250 } ApiSourceLocal;
    251 
    252 struct KitCg {
    253   Compiler* c;
    254   ObjBuilder* obj;
    255   CgTarget* target;
    256   Debug* debug;
    257   KitCgUnitOptions cur_unit;
    258   u32 nsource_units;
    259   /* Monotonic, nonzero per source unit (set at kit_cg_begin_unit). Used to tell
    260    * a same-TU re-definition (legal tentative-definition coalescing) apart from
    261    * a genuine cross-TU contribution that must go through symresolve_merge. */
    262   u32 cur_unit_seq;
    263   u8 unit_active;
    264   u8 finished;
    265   u8 lifecycle_pad[2];
    266 
    267   ApiSValue* stack;
    268   ApiConstValue* const_stack;
    269   u32 sp;
    270   u32 cap;
    271   u32 unevaluated_depth;
    272 
    273   /* -O0 transient liveness. local_refs[h] = number of live value-stack entries
    274    * that reference CGLocal handle h (maintained at api_push/api_pop, plus a
    275    * pointer-range-guarded reseat at in-place operand changes). local_is_temp[h]
    276    * marks an api_alloc_temp_local transient — the only locals the single-pass
    277    * backend recycles (Fix A) or coalesces. The count is used only as a
    278    * fast-reject prefilter: a transient is treated as dead solely when the count
    279    * reads 0 AND a confirming stack scan (api_temp_dead) agrees, so any reseat
    280    * gap costs at most a missed optimization, never a miscompile. Sized on
    281    * demand by handle; cleared per function. NULL/0 until first use. */
    282   u32* local_refs;     /* live value-stack reference count per handle */
    283   u32* local_temp_gen; /* == func_gen iff the handle is this function's temp */
    284   u32 local_track_cap;
    285   u32 func_gen; /* bumped each function; stamps temps without O(cap) clears */
    286   u8 coalesce;  /* -O0 copy/dup coalescing + finer reclaim enabled */
    287   u8 coalesce_known; /* coalesce resolved from env (once) */
    288   u8 coalesce_pad[2];
    289 
    290   /* Off-node pool for SV_CMP / SV_ARITH delayed payloads. The arena is reset
    291    * per function (api_delayed_reset at func_begin, where the stack is also
    292    * dropped); delayed_free is an intrusive freelist that reuses payloads within
    293    * a function so the arena only grows to the live delayed-value working set.
    294    */
    295   Arena delayed_arena;
    296   ApiDelayed* delayed_free;
    297   u8 delayed_arena_init;
    298   u8 delayed_pad[3];
    299 
    300   ApiSourceLocal* locals;
    301   u32 nlocals;
    302   u32 locals_cap;
    303   /* Head of the const-active list threaded through ApiSourceLocal.const_next:
    304    * the locals that currently hold (or recently held, pending a boundary) a
    305    * forwardable constant. Lets the const-tracker clear in O(#tracked) rather
    306    * than scanning all nlocals on every store/call/branch/address-of. */
    307   KitCgLocal const_head;
    308 
    309   KitCgTypeId fn_ret_type; /* KIT_CG_TYPE_NONE/void == no result */
    310   SrcLoc cur_loc;
    311 
    312   CGFuncDesc fn_desc;
    313   CGParamDesc fn_params[64];
    314 
    315   KitCgTypeId* sym_types;
    316   KitCgDecl* sym_attrs;
    317   u32 sym_cap;
    318 
    319   DebugTypeId* debug_type_cache; /* indexed by KitCgTypeId */
    320   u8* debug_type_state;          /* 0 empty, 1 building, 2 complete */
    321   u32 debug_type_cap;
    322 
    323   /* Per-ObjSymId: the cur_unit_seq of the unit that last *defined* this symbol
    324    * (0 = not defined by any unit yet). Distinct from sym_attrs, which is reset
    325    * on every decl; this is written only when a definition is emitted. */
    326   u32* sym_def_seq;
    327   u32 sym_def_seq_cap;
    328 
    329   ApiCgScope* scopes; /* grows on demand; see api_grow_scopes */
    330   u32 nscopes;
    331   u32 scopes_cap;
    332   u32 scope_generation;
    333 
    334   u32 rodata_counter;
    335   int opt_level;
    336   u8 check_only;
    337   u8 function_sections;
    338   u8 data_sections;
    339   u8 stack_protector_mode; /* KitStackProtectorMode */
    340   u8 stack_protected;
    341   u8 stack_guard_tls;
    342   u8 stack_protector_pad[1];
    343   KitCgTypeId stack_guard_type;
    344   KitCgLocal stack_guard_local;
    345   KitCgSym stack_guard_sym;
    346   KitCgSym stack_fail_sym;
    347 
    348   ObjSecId data_sec;
    349   ObjSymId data_sym;
    350   u32 data_base;
    351   u64 data_size;
    352   u8 data_local_static_target;
    353   u8 data_atomize;
    354   u8 data_retain;
    355   u8 data_discard;
    356   u8 data_tls_collect;
    357   u8 data_tls_zero_fill;
    358   u8 data_tls_pad[2];
    359   u32 data_tls_align;
    360   Buf data_tls_bytes;
    361   ObjTlsReloc* data_tls_relocs;
    362   u32 data_tls_nrelocs;
    363   u32 data_tls_relocs_cap;
    364 };
    365 
    366 /* ------------------------------------------------------------------
    367  * API-misuse / invariant checks (debug-only)
    368  *
    369  * The cg.h contract treats a frontend that drives the value stack, scope
    370  * handles, or operand kinds incorrectly as a kit bug, not a recoverable
    371  * condition. CG_REQUIRE / CG_BUG state those invariants: in a debug build they
    372  * fire the same rich FATAL diagnostic + longjmp as a hand-written
    373  * compiler_panic, but under NDEBUG the whole check -- condition, message, and
    374  * argument evaluation -- is elided, so the release hot path pays nothing.
    375  *
    376  *   CG_REQUIRE(g, cond, fmt, ...)  assert the OK condition `cond` holds
    377  *   CG_BUG(g, fmt, ...)            mark an unreachable else/default arm
    378  *
    379  * Use ONLY for invariants a correct caller can never violate. Genuine resource
    380  * failures (OOM, object-emission failures), unsupported-operation guards whose
    381  * elision would silently miscompile, size/truncation limits, and configuration
    382  * errors stay as unconditional compiler_panic so they trap in every build.
    383  * ------------------------------------------------------------------ */
    384 #ifdef NDEBUG
    385 /* Elided: the sizeof keeps every operand in an unevaluated context so a value
    386  * or `who`-style diagnostic argument used only by the check does not become an
    387  * unused variable/parameter under -Werror, while emitting no runtime code. */
    388 #define CG_REQUIRE(g, cond, ...) ((void)sizeof((g), (cond), __VA_ARGS__, 0))
    389 #define CG_BUG(g, ...) ((void)sizeof((g), __VA_ARGS__, 0))
    390 #else
    391 #define CG_REQUIRE(g, cond, ...) \
    392   ((cond) ? (void)0 : compiler_panic((g)->c, (g)->cur_loc, __VA_ARGS__))
    393 #define CG_BUG(g, ...) compiler_panic((g)->c, (g)->cur_loc, __VA_ARGS__)
    394 #endif
    395 
    396 void cg_api_fini(Compiler*);
    397 
    398 void api_cg_binop(KitCg* g, BinOp iop, u32 flags);
    399 void api_cg_unop(KitCg* g, UnOp iop, u32 flags);
    400 void api_cg_cmp(KitCg* g, CmpOp cop);
    401 void api_cg_convert_kind(KitCg* g, KitCgTypeId dst_type, ConvKind ck);
    402 void kit_cg_int_binop(KitCg* g, KitCgIntBinOp op, uint32_t flags);
    403 void kit_cg_int_unop(KitCg* g, KitCgIntUnOp op, uint32_t flags);
    404 void kit_cg_int_cmp(KitCg* g, KitCgIntCmpOp op);
    405 const char* api_i128_binop_helper(BinOp op);
    406 int api_i128_cmp_is_unsigned(CmpOp op);
    407 const char* api_f128_binop_helper(KitCgFpBinOp op);
    408 int api_f128_stack_top(KitCg* g, u32 depth);
    409 void api_f128_call_unary(KitCg* g, const char* name, KitCgTypeId ret,
    410                          KitCgTypeId param);
    411 void kit_cg_fp_binop(KitCg* g, KitCgFpBinOp op, uint32_t flags);
    412 void kit_cg_fp_unop(KitCg* g, KitCgFpUnOp op, uint32_t flags);
    413 void kit_cg_fp_cmp(KitCg* g, KitCgFpCmpOp op);
    414 void kit_cg_sext(KitCg* g, KitCgTypeId dst);
    415 void kit_cg_zext(KitCg* g, KitCgTypeId dst);
    416 void kit_cg_trunc(KitCg* g, KitCgTypeId dst);
    417 void kit_cg_ptr_to_int(KitCg* g, KitCgTypeId dst);
    418 void kit_cg_int_to_ptr(KitCg* g, KitCgTypeId dst);
    419 void kit_cg_bitcast(KitCg* g, KitCgTypeId dst);
    420 void kit_cg_fpext(KitCg* g, KitCgTypeId dst);
    421 void kit_cg_fptrunc(KitCg* g, KitCgTypeId dst);
    422 void kit_cg_sint_to_float(KitCg* g, KitCgTypeId dst, KitCgRounding rounding);
    423 void kit_cg_uint_to_float(KitCg* g, KitCgTypeId dst, KitCgRounding rounding);
    424 void kit_cg_float_to_sint(KitCg* g, KitCgTypeId dst, KitCgRounding rounding);
    425 void kit_cg_float_to_uint(KitCg* g, KitCgTypeId dst, KitCgRounding rounding);
    426 IntrinKind api_map_intrinsic(KitCg* g, KitCgIntrinsic intrin,
    427                              KitCgTypeId result_type);
    428 int api_intrinsic_is_void(KitCgIntrinsic intrin);
    429 int api_intrinsic_is_overflow(KitCgIntrinsic intrin);
    430 const char* api_intrinsic_name(KitCgIntrinsic intrin);
    431 void kit_cg_intrinsic(KitCg* g, KitCgIntrinsic intrin, uint32_t nargs,
    432                       KitCgTypeId result_type);
    433 KitCgTypeId api_atomic_pointee(KitCg* g, KitCgTypeId pty, const char* who);
    434 const char* api_sym_cstr(KitCg* g, KitSym sym);
    435 int api_asm_parse_match_index(const char* s);
    436 const char* api_asm_constraint_body(const char* s);
    437 int api_asm_is_early_clobber(const char* s);
    438 int api_asm_is_reg_constraint(char c);
    439 void api_asm_memory_clobber_sv(KitCg* g, ApiSValue* sv, CGLocal local);
    440 void kit_cg_inline_asm(KitCg* g, KitCgInlineAsm asm_block);
    441 void kit_cg_file_scope_asm(KitCg* g, KitSlice asm_source);
    442 MemAccess api_mem_for_atomic(KitCg* g, KitCgTypeId val_ty);
    443 int kit_cg_atomic_is_legal(KitCompiler* c, KitCgMemAccess access,
    444                            KitCgMemOrder order);
    445 int kit_cg_atomic_is_lock_free(KitCompiler* c, KitCgMemAccess access);
    446 void kit_cg_atomic_load(KitCg* g, KitCgMemAccess access, KitCgMemOrder order);
    447 void kit_cg_atomic_store(KitCg* g, KitCgMemAccess access, KitCgMemOrder order);
    448 void kit_cg_atomic_rmw(KitCg* g, KitCgMemAccess access, KitCgAtomicOp op,
    449                        KitCgMemOrder order);
    450 void kit_cg_atomic_cmpxchg(KitCg* g, KitCgMemAccess access,
    451                            KitCgMemOrder success, KitCgMemOrder failure,
    452                            int weak);
    453 void kit_cg_atomic_fence(KitCg* g, KitCgMemOrder order);
    454 CGLocal* api_alloc_call_args(KitCg* g, u32 nargs);
    455 void api_pack_call_arg(KitCg* g, CGLocal* out, KitCgTypeId fty, u32 idx);
    456 CGLocal api_alloc_call_result(KitCg* g, KitCgTypeId ret_ty);
    457 void api_push_call_result(KitCg* g, CGLocal result, KitCgTypeId ret_ty);
    458 void kit_cg_call(KitCg* g, uint32_t nargs, KitCgTypeId fn_type,
    459                  KitCgCallAttrs attrs);
    460 void api_call_symbol_common(KitCg* g, KitCgSym sym, uint32_t nargs,
    461                             KitCgCallAttrs attrs);
    462 void kit_cg_call_symbol(KitCg* g, KitCgSym sym, uint32_t nargs,
    463                         KitCgCallAttrs attrs);
    464 void kit_cg_ret(KitCg* g);
    465 void api_stack_protector_check(KitCg* g);
    466 KitCgLabel kit_cg_label_new(KitCg* g);
    467 void kit_cg_label_place(KitCg* g, KitCgLabel label);
    468 void kit_cg_jump(KitCg* g, KitCgLabel label);
    469 void api_branch_if(KitCg* g, ApiSValue* v, int branch_when_true, Label label);
    470 void kit_cg_branch_true(KitCg* g, KitCgLabel label);
    471 void kit_cg_branch_false(KitCg* g, KitCgLabel label);
    472 void kit_cg_switch(KitCg* g, KitCgSwitch sw);
    473 void kit_cg_push_label_addr(KitCg* g, KitCgLabel label, KitCgTypeId ptr_type);
    474 void kit_cg_computed_goto(KitCg* g, const KitCgLabel* valid_targets,
    475                           uint32_t ntargets);
    476 
    477 void kit_cg_field_bits(KitCg* g, uint16_t bit_offset, uint16_t bit_width,
    478                        uint32_t bit_storage_size, int bit_signed);
    479 void kit_cg_unreachable(KitCg* g);
    480 KitCgScope api_scope_handle(u32 idx, u32 generation);
    481 ApiCgScope* api_scope_from_handle(KitCg* g, KitCgScope scope, int require_top,
    482                                   const char* who);
    483 int api_scope_has_result(const ApiCgScope* s);
    484 void api_scope_store_results(KitCg* g, ApiCgScope* s);
    485 void api_scope_push_results(KitCg* g, ApiCgScope* s);
    486 KitCgScope kit_cg_scope_begin(KitCg* g);
    487 KitCgScope kit_cg_scope_begin_value(KitCg* g, KitCgTypeId result_type);
    488 KitCgScope kit_cg_block_begin(KitCg* g);
    489 KitCgScope kit_cg_block_begin_value(KitCg* g, KitCgTypeId result_type);
    490 KitCgScope kit_cg_scope_begin_sig(KitCg* g, const KitCgScopeSig* sig);
    491 KitCgScope kit_cg_block_begin_sig(KitCg* g, const KitCgScopeSig* sig);
    492 void kit_cg_scope_store_params(KitCg* g, KitCgScope scope);
    493 void kit_cg_scope_end(KitCg* g, KitCgScope scope);
    494 void kit_cg_scope_end_unreachable(KitCg* g, KitCgScope scope);
    495 void kit_cg_break(KitCg* g, KitCgScope scope);
    496 void kit_cg_break_true(KitCg* g, KitCgScope scope);
    497 void kit_cg_break_false(KitCg* g, KitCgScope scope);
    498 void kit_cg_continue(KitCg* g, KitCgScope scope);
    499 void kit_cg_continue_true(KitCg* g, KitCgScope scope);
    500 void kit_cg_continue_false(KitCg* g, KitCgScope scope);
    501 void kit_cg_alloca(KitCg* g, uint32_t align, KitCgTypeId result_ptr_type);
    502 void kit_cg_vararg_start(KitCg* g);
    503 void kit_cg_vararg_next(KitCg* g, KitCgTypeId type);
    504 void kit_cg_vararg_end(KitCg* g);
    505 void kit_cg_vararg_copy(KitCg* g);
    506 void kit_cg_memcpy(KitCg* g, uint64_t size, KitCgMemAccess dst_access,
    507                    KitCgMemAccess src_access);
    508 void kit_cg_memmove(KitCg* g, uint64_t size, KitCgMemAccess dst_access,
    509                     KitCgMemAccess src_access);
    510 void kit_cg_memset(KitCg* g, uint8_t val, uint64_t size,
    511                    KitCgMemAccess dst_access);
    512 void kit_cg_data_begin(KitCg* g, KitCgSym cg_sym, KitCgDataDefAttrs attrs);
    513 void kit_cg_data_common(KitCg* g, KitCgSym cg_sym, uint64_t size,
    514                         uint32_t align);
    515 void kit_cg_data_align(KitCg* g, uint32_t align);
    516 void kit_cg_data_pad(KitCg* g, uint64_t size, uint8_t value);
    517 void kit_cg_data_int(KitCg* g, uint64_t value, KitCgTypeId type);
    518 void kit_cg_data_float(KitCg* g, double value, KitCgTypeId type);
    519 void kit_cg_data_bytes(KitCg* g, const uint8_t* data, size_t len);
    520 void kit_cg_data_zero(KitCg* g, uint64_t size);
    521 void api_cg_data_reloc(KitCg* g, KitCgSym target, int64_t addend,
    522                        uint32_t width, int pcrel);
    523 void kit_cg_data_addr(KitCg* g, KitCgSym target, int64_t addend, uint32_t width,
    524                       uint32_t address_space);
    525 void kit_cg_data_label_addr(KitCg* g, KitCgLabel target, int64_t addend,
    526                             uint32_t width, uint32_t address_space);
    527 void kit_cg_data_pcrel(KitCg* g, KitCgSym target, int64_t addend,
    528                        uint32_t width);
    529 void kit_cg_data_symdiff(KitCg* g, KitCgSym lhs, KitCgSym rhs, int64_t addend,
    530                          uint32_t width);
    531 void kit_cg_data_end(KitCg* g);
    532 ObjSymId api_emit_label_table(KitCg* g, const Label* labels, u32 n);
    533 DebugTypeId api_debug_type(KitCg* g, KitCgDebugType debug_type,
    534                            KitCgTypeId fallback_type);
    535 int api_local_requires_memory(KitCg* g, KitCgTypeId ty, KitCgLocalAttrs attrs);
    536 KitCgLocal api_local_handle(u32 index);
    537 int api_grow_locals(KitCg* g, u32 want);
    538 int api_grow_scopes(KitCg* g, u32 want);
    539 ApiSourceLocal* api_local_from_handle(KitCg* g, KitCgLocal local);
    540 CGLocal api_frame_local_storage(KitCg* g, const CGLocalDesc* d);
    541 KitCgLocal kit_cg_local(KitCg* g, KitCgTypeId type, KitCgLocalAttrs attrs);
    542 KitCgLocal kit_cg_param(KitCg* g, uint32_t index, KitCgTypeId type,
    543                         KitCgLocalAttrs attrs);
    544 void kit_cg_push_int(KitCg* g, uint64_t value, KitCgTypeId type);
    545 void kit_cg_push_float(KitCg* g, double value, KitCgTypeId type);
    546 void kit_cg_push_null(KitCg* g, KitCgTypeId ptr_type);
    547 KitCgSym kit_cg_const_data(KitCg* g, const uint8_t* data, size_t len,
    548                            uint32_t align, KitCgTypeId pointee_type);
    549 void api_push_local_lvalue(KitCg* g, CGLocal local, KitCgTypeId type);
    550 void api_push_source_local_lvalue(KitCg* g, KitCgLocal local, CGLocal storage,
    551                                   KitCgTypeId type);
    552 void kit_cg_push_local(KitCg* g, KitCgLocal local);
    553 void kit_cg_push_local_addr(KitCg* g, KitCgLocal local);
    554 void kit_cg_push_symbol_addr(KitCg* g, KitCgSym sym, int64_t addend);
    555 void kit_cg_load(KitCg* g, KitCgMemAccess access);
    556 void kit_cg_addr(KitCg* g);
    557 void kit_cg_deref(KitCg* g, int64_t offset);
    558 void kit_cg_store(KitCg* g, KitCgMemAccess access);
    559 void kit_cg_store_keep(KitCg* g, KitCgMemAccess access);
    560 void kit_cg_field_at(KitCg* g, int64_t byte_offset, KitCgTypeId field_type);
    561 void kit_cg_dup(KitCg* g);
    562 void kit_cg_dup2(KitCg* g);
    563 void kit_cg_swap(KitCg* g);
    564 void kit_cg_drop(KitCg* g);
    565 KitCgSlotInfo kit_cg_slot_info(KitCg* g, uint32_t depth_from_top);
    566 KitCgTypeId kit_cg_slot_cg_type(KitCg* g, uint32_t depth_from_top);
    567 const void* kit_cg_slot_lang_type(KitCg* g, uint32_t depth_from_top);
    568 uint16_t kit_cg_slot_lang_flags(KitCg* g, uint32_t depth_from_top);
    569 void kit_cg_retag_top(KitCg* g, const void* lang_type, uint16_t lang_flags);
    570 void kit_cg_retag_at(KitCg* g, uint32_t depth_from_top, const void* lang_type,
    571                      uint16_t lang_flags);
    572 void kit_cg_set_top_flags(KitCg* g, uint16_t set, uint16_t clear);
    573 uint32_t kit_cg_stack_depth(KitCg* g);
    574 int kit_cg_top_const_int(KitCg* g, int64_t* out_value);
    575 void kit_cg_rot3(KitCg* g);
    576 KitStatus kit_cg_new(KitCompiler* c, KitCg** cg_out);
    577 KitStatus kit_cg_begin(KitCg* g, KitObjBuilder* out,
    578                        const KitCodeOptions* opts);
    579 KitStatus kit_cg_begin_unit(KitCg* g, const KitCgUnitOptions* opts);
    580 KitStatus kit_cg_end_unit(KitCg* g);
    581 KitStatus kit_cg_finish(KitCg* g, const KitCgFinishOptions* opts);
    582 KitStatus kit_cg_detach(KitCg* g);
    583 KitStatus kit_cg_abort(KitCg* g);
    584 void kit_cg_free(KitCg* g);
    585 void kit_cg_set_loc(KitCg* g, KitSrcLoc loc);
    586 KitCgSym kit_cg_decl(KitCg* g, KitCgDecl decl);
    587 KitCgSym kit_cg_alias(KitCg* g, KitCgAlias alias);
    588 void kit_cg_func_begin(KitCg* g, KitCgSym cg_sym);
    589 void kit_cg_func_begin_attrs(KitCg* g, KitCgSym cg_sym, KitCgFuncAttrs attrs);
    590 void kit_cg_func_end(KitCg* g);
    591 SymBind api_map_bind(KitSymBind b);
    592 SymVis api_map_vis(KitCgVisibility v);
    593 SymKind api_decl_sym_kind(KitCgDecl decl);
    594 Sym api_cg_symbol_section_name(KitCg* g, Slice base, KitSym linkage_name);
    595 void api_remember_sym(KitCg* g, ObjSymId sym, KitCgTypeId ty, KitCgDecl decl);
    596 KitCgTypeId api_sym_type(KitCg* g, KitCgSym sym);
    597 KitCgDecl api_sym_attrs(KitCg* g, KitCgSym sym);
    598 int api_sym_is_tls(KitCg* g, KitCgSym sym);
    599 RelocKind api_data_reloc_kind(int pcrel, uint32_t width);
    600 SrcLoc api_no_loc(void);
    601 /* Type-property predicates (api_type_is_float / api_is_*_type) and the type
    602  * classification (api_type_class) are declared in cg/type.h. */
    603 
    604 /* Delayed cmp/arith payload pool (fold.c). alloc returns a payload from the
    605  * per-function freelist or the arena; free returns it for reuse; reset drops
    606  * the whole pool at a function boundary. */
    607 ApiDelayed* api_delayed_alloc(KitCg* g);
    608 void api_delayed_free(KitCg* g, ApiDelayed* d);
    609 void api_delayed_reset(KitCg* g);
    610 Operand api_op_imm(i64 v, KitCgTypeId ty);
    611 Operand api_op_local(CGLocal r, KitCgTypeId ty);
    612 Operand api_op_global(ObjSymId sym, i64 addend, KitCgTypeId ty);
    613 Operand api_op_indirect(CGLocal base, i32 ofs, KitCgTypeId ty);
    614 Operand api_op_indirect_indexed(CGLocal base, CGLocal index, u8 log2_scale,
    615                                 i32 ofs, KitCgTypeId ty);
    616 u8 api_residency_for(const Operand* o);
    617 ApiSValue api_make_sv(Operand op, KitCgTypeId ty);
    618 ApiSValue api_make_lv(Operand op, KitCgTypeId ty);
    619 ApiSValue api_make_sv_with_local_ownership(Operand op, KitCgTypeId ty,
    620                                            int owned);
    621 KitCgTypeId api_sv_type(const ApiSValue* sv);
    622 int api_operand_can_address(const Operand* o);
    623 int api_sv_op_is(const ApiSValue* sv, OpKind kind);
    624 int api_sv_op_is_local_or_imm(const ApiSValue* sv);
    625 int api_is_lvalue_sv(const ApiSValue* sv);
    626 int api_sv_is_bitfield(const ApiSValue* sv);
    627 MemAccess api_mem_for_bitfield(KitCg* g, const ApiSValue* sv,
    628                                const Operand* storage, KitCgTypeId field_ty);
    629 void api_stack_grow(KitCg* g, u32 want);
    630 void api_push(KitCg* g, ApiSValue v);
    631 ApiSValue api_pop(KitCg* g);
    632 int api_unevaluated(KitCg* g);
    633 ApiSValue api_uneval_value(KitCg* g, KitCgTypeId type);
    634 ApiSValue api_uneval_place(KitCg* g, KitCgTypeId type);
    635 ApiConstValue api_const_unknown(KitCgTypeId type);
    636 ApiConstValue api_const_from_sv(KitCg* g, const ApiSValue* sv);
    637 ApiConstValue api_const_at(KitCg* g, u32 depth);
    638 void api_const_set_top(KitCg* g, ApiConstValue value);
    639 void api_const_set_at(KitCg* g, u32 depth, ApiConstValue value);
    640 void api_const_copy_top_from(KitCg* g, ApiConstValue value);
    641 ApiConstValue api_const_for_push(KitCg* g, KitCgTypeId type,
    642                                  const KitCgConstInt* value);
    643 int api_const_fold_binop(KitCg* g, BinOp op, KitCgTypeId type, ApiConstValue a,
    644                          ApiConstValue b, u32 flags, ApiConstValue* out);
    645 int api_const_fold_unop(KitCg* g, UnOp op, KitCgTypeId type, ApiConstValue a,
    646                         u32 flags, ApiConstValue* out);
    647 int api_const_fold_cmp(KitCg* g, CmpOp op, ApiConstValue a, ApiConstValue b,
    648                        ApiConstValue* out);
    649 int api_const_fold_convert(KitCg* g, ConvKind ck, KitCgTypeId src_type,
    650                            KitCgTypeId dst_type, ApiConstValue in,
    651                            ApiConstValue* out);
    652 ApiConstValue api_const_int_result(KitCg* g, KitCgTypeId type, u64 lo, u64 hi,
    653                                    int is_signed);
    654 CGLocal api_local_of_sv(const ApiSValue* sv);
    655 void api_set_owned_local(ApiSValue* sv, CGLocal r);
    656 KitCgTypeId api_owned_local_type(KitCg* g, const ApiSValue* sv);
    657 CGLocal api_alloc_temp_local(KitCg* g, KitCgTypeId ty);
    658 MemAccess api_mem_for_lvalue(KitCg* g, const Operand* lv, KitCgTypeId ty);
    659 MemAccess api_mem_from_access_resolved(KitCg* g, const Operand* lv,
    660                                        KitCgMemAccess access, KitCgTypeId ty);
    661 MemAccess api_mem_from_access(KitCg* g, const Operand* lv,
    662                               KitCgMemAccess access);
    663 KitCgTypeId api_mem_access_type(KitCg* g, KitCgMemAccess access,
    664                                 KitCgTypeId fallback, const char* who);
    665 u32 api_mem_type_size_resolved(KitCg* g, KitCgTypeId ty, const char* who);
    666 u32 api_mem_type_size(KitCg* g, KitCgTypeId ty, const char* who);
    667 u32 api_require_scalar_mem_type_resolved(KitCg* g, const char* who,
    668                                          KitCgTypeId ty);
    669 void api_require_scalar_mem_type(KitCg* g, const char* who, KitCgTypeId ty);
    670 void api_require_pointer_value(KitCg* g, const char* who, KitCgTypeId ty);
    671 void api_validate_memory_value_resolved(KitCg* g, const char* who,
    672                                         KitCgTypeId access_ty,
    673                                         KitCgTypeId value_ty);
    674 void api_validate_memory_value(KitCg* g, const char* who, KitCgTypeId access_ty,
    675                                KitCgTypeId value_ty);
    676 int api_sv_owns_operand_local(const ApiSValue* sv, const Operand* op);
    677 void api_ensure_local(KitCg* g, ApiSValue* sv);
    678 Operand api_force_local(KitCg* g, ApiSValue* v, KitCgTypeId ty);
    679 Operand api_force_local_unless_imm(KitCg* g, ApiSValue* v, KitCgTypeId ty);
    680 void api_release(KitCg* g, ApiSValue* sv);
    681 
    682 /* -O0 transient liveness (see KitCg.local_refs). api_coalesce_on returns
    683  * whether the copy/dup coalescing + finer-reclaim mechanisms are enabled this
    684  * run. api_temp_dead reports whether transient `local` is provably dead right
    685  * now (no live value-stack entry references it): count==0 confirmed by a stack
    686  * scan. api_reseat_{begin,end} bracket an in-place change to a stack entry's
    687  * operand so its references are re-accounted. */
    688 int api_coalesce_on(KitCg* g);
    689 int api_temp_dead(KitCg* g, CGLocal local);
    690 /* Flag OP for the -O0 backend's eager dead-operand drop: when coalescing is on
    691  * and OP names a transient that api_temp_dead confirms is dead after the
    692  * consuming op, AND OP is distinct from that op's destination DST (so it is not
    693  * the result being written), return OP with OPK_FLAG_KILL set; otherwise return
    694  * OP unchanged. The NativeDirectTarget then drops OP's live cache register
    695  * after the op (no spill, no reload) instead of leaving it resident to be
    696  * flush-stored at the next barrier. Pass a non-OPK_LOCAL operand for DST (e.g.
    697  * the store's memory place) when the op has no local destination — the
    698  * self-guard is then a no-op. */
    699 Operand api_op_kill_if_dead(KitCg* g, Operand op, Operand dst);
    700 void api_reseat_begin(KitCg* g, const ApiSValue* sv);
    701 void api_reseat_end(KitCg* g, const ApiSValue* sv);
    702 
    703 BinOp api_map_int_binop(KitCgIntBinOp op);
    704 BinOp api_map_fp_binop(KitCgFpBinOp op);
    705 UnOp api_map_int_unop(KitCgIntUnOp op);
    706 CmpOp api_map_int_cmp(KitCgIntCmpOp op);
    707 CmpOp api_map_fp_cmp(KitCgFpCmpOp op);
    708 Operand api_lvalue_addr(KitCg* g, ApiSValue* v, KitCgTypeId pty);
    709 CGLocal api_f128_temp_local(KitCg* g, KitCgTypeId ty);
    710 u64 api_u64_from_target_bytes(KitCg* g, const u8* bytes);
    711 void api_store_f128_bytes(KitCg* g, CGLocal local, KitCgTypeId ty,
    712                           const u8 bytes[16]);
    713 void api_wide16_sext_imm_bytes(KitCg* g, i64 imm, u8 bytes[16]);
    714 ApiSValue api_make_wide16_int_const(KitCg* g, i64 value, KitCgTypeId ty);
    715 ApiSValue api_make_wide16_int_const_bits(KitCg* g, u64 lo, u64 hi,
    716                                          KitCgTypeId ty);
    717 void api_encode_binary128_from_double(KitCg* g, double value, u8 out[16]);
    718 ApiSValue api_make_f128_const(KitCg* g, double value, KitCgTypeId ty);
    719 ApiSValue api_wide16_materialize_lvalue(KitCg* g, ApiSValue* v, KitCgTypeId ty);
    720 CGLocal api_wide8_temp_local(KitCg* g, KitCgTypeId ty);
    721 ApiSValue api_make_wide8_const_bits(KitCg* g, u64 bits, KitCgTypeId ty);
    722 ApiSValue api_make_wide8_int_const(KitCg* g, i64 value, KitCgTypeId ty);
    723 Operand api_wide8_addr(KitCg* g, ApiSValue* v, KitCgTypeId ty);
    724 Operand api_wide8_load_lane(KitCg* g, Operand addr, i32 off);
    725 void api_wide8_store_lane(KitCg* g, Operand addr, i32 off, Operand val);
    726 Operand api_wide8_or_lanes(KitCg* g, ApiSValue* v, KitCgTypeId ty);
    727 KitCgSym api_runtime_helper(KitCg* g, const char* name, KitCgTypeId ret,
    728                             const KitCgTypeId* params, u32 nparams);
    729 void api_runtime_call_values(KitCg* g, const char* name, KitCgTypeId ret,
    730                              const KitCgTypeId* params, u32 nparams,
    731                              ApiSValue* args);
    732 
    733 /* The semantic-layer peephole optimizer: constant folding, the delayed
    734  * compare/arith forms, and const-local store-to-load forwarding. Included here,
    735  * after the operand and value types above, so its declarations can name
    736  * ApiSValue / ApiSourceLocal / Operand. */
    737 #include "cg/fold.h"
    738 
    739 #endif