kit

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

cg.h (58952B)


      1 #ifndef KIT_PUBLIC_CG_H
      2 #define KIT_PUBLIC_CG_H
      3 
      4 #include <kit/core.h>
      5 #include <kit/object.h>
      6 
      7 /* ============================================================
      8  * Handles
      9  * ============================================================ */
     10 
     11 typedef struct KitCg KitCg;
     12 
     13 typedef uint32_t KitCgLabel;
     14 typedef uint32_t KitCgLocal;
     15 typedef uint32_t KitCgScope;
     16 typedef uint32_t KitCgSym;
     17 typedef uint32_t KitCgTypeId;
     18 
     19 #define KIT_CG_LABEL_NONE 0u
     20 #define KIT_CG_LOCAL_NONE 0u
     21 #define KIT_CG_SCOPE_NONE 0u
     22 #define KIT_CG_SYM_NONE 0u
     23 #define KIT_CG_TYPE_NONE 0u
     24 
     25 /* ============================================================
     26  * Types, ABI, and Target Capabilities
     27  * ============================================================ */
     28 
     29 typedef enum KitCgBuiltinType {
     30   KIT_CG_BUILTIN_VOID,
     31   KIT_CG_BUILTIN_BOOL, /* i1: compare result and branch condition */
     32   KIT_CG_BUILTIN_I8,
     33   KIT_CG_BUILTIN_I16,
     34   KIT_CG_BUILTIN_I32,
     35   KIT_CG_BUILTIN_I64,
     36   KIT_CG_BUILTIN_I128,
     37   KIT_CG_BUILTIN_F32,
     38   KIT_CG_BUILTIN_F64,
     39   KIT_CG_BUILTIN_F128,
     40   KIT_CG_BUILTIN_VARARG_STATE,
     41   KIT_CG_BUILTIN_COUNT,
     42 } KitCgBuiltinType;
     43 
     44 typedef struct KitCgBuiltinTypes {
     45   KitCgTypeId id[KIT_CG_BUILTIN_COUNT];
     46 } KitCgBuiltinTypes;
     47 
     48 typedef enum KitCgTypeKind {
     49   KIT_CG_TYPE_VOID,
     50   KIT_CG_TYPE_BOOL,
     51   KIT_CG_TYPE_INT,
     52   KIT_CG_TYPE_FLOAT,
     53   KIT_CG_TYPE_PTR,
     54   KIT_CG_TYPE_ARRAY,
     55   KIT_CG_TYPE_FUNC,
     56   KIT_CG_TYPE_RECORD,
     57   KIT_CG_TYPE_ENUM,
     58   KIT_CG_TYPE_ALIAS,
     59   KIT_CG_TYPE_VARARG_STATE,
     60 } KitCgTypeKind;
     61 
     62 typedef enum KitCgCallConv {
     63   /* Backend-selected C ABI for the target triple. Frontends should use this
     64    * unless source semantics or ABI interop explicitly require another
     65    * convention. Non-default values are requests that must be supported by the
     66    * selected backend or diagnosed. */
     67   KIT_CG_CC_TARGET_C,
     68   KIT_CG_CC_SYSV,
     69   KIT_CG_CC_WIN64,
     70   KIT_CG_CC_AAPCS,
     71   KIT_CG_CC_WASM,
     72   KIT_CG_CC_INTERRUPT,
     73 } KitCgCallConv;
     74 
     75 typedef enum KitCgAbiAttrFlag {
     76   KIT_CG_ABI_NONE = 0,
     77   KIT_CG_ABI_SIGNEXT = 1u << 0,
     78   KIT_CG_ABI_ZEROEXT = 1u << 1,
     79   KIT_CG_ABI_SRET = 1u << 2,
     80   KIT_CG_ABI_BYVAL = 1u << 3,
     81   KIT_CG_ABI_BYREF = 1u << 4,
     82   KIT_CG_ABI_INREG = 1u << 5,
     83   KIT_CG_ABI_NOALIAS = 1u << 6,
     84   KIT_CG_ABI_READONLY = 1u << 7,
     85   KIT_CG_ABI_WRITEONLY = 1u << 8,
     86   KIT_CG_ABI_NONNULL = 1u << 9,
     87   KIT_CG_ABI_NEST = 1u << 10,
     88 } KitCgAbiAttrFlag;
     89 
     90 typedef struct KitCgAbiAttrs {
     91   uint32_t flags; /* KitCgAbiAttrFlag */
     92   uint32_t align; /* 0 = ABI default */
     93   uint64_t dereferenceable_size;
     94 } KitCgAbiAttrs;
     95 
     96 typedef struct KitCgFuncParam {
     97   KitCgTypeId type;
     98   KitCgAbiAttrs attrs;
     99 } KitCgFuncParam;
    100 
    101 /* Symmetric with KitCgFuncParam. A function returns a single value or nothing;
    102  * result.type == KIT_CG_TYPE_NONE means void. */
    103 typedef struct KitCgFuncResult {
    104   KitCgTypeId type;
    105   KitCgAbiAttrs attrs;
    106 } KitCgFuncResult;
    107 
    108 typedef struct KitCgFuncSig {
    109   KitCgFuncResult result; /* result.type == KIT_CG_TYPE_NONE == void */
    110   const KitCgFuncParam* params;
    111   uint32_t nparams;
    112   KitCgCallConv call_conv;
    113   bool abi_variadic;
    114 } KitCgFuncSig;
    115 
    116 typedef struct KitCgField {
    117   KitSym name; /* 0 for anonymous fields/tuple elements */
    118   KitCgTypeId type;
    119   uint32_t align_override;   /* 0 = natural, 1 = packed, >1 explicit align */
    120   uint32_t max_align;        /* 0 = natural, otherwise cap field alignment */
    121   uint32_t flags;            /* KitCgFieldFlag */
    122   uint16_t bit_width;        /* valid for bit-fields, may be 0 for barriers */
    123   uint16_t bit_offset;       /* filled by record-field queries */
    124   uint32_t bit_storage_size; /* bytes, filled by record-field queries */
    125   int bit_signed;            /* signed extraction for bit-field loads */
    126 } KitCgField;
    127 
    128 typedef enum KitCgFieldFlag {
    129   KIT_CG_FIELD_BITFIELD = 1u << 0,
    130   KIT_CG_FIELD_ZERO_WIDTH = 1u << 1,
    131 } KitCgFieldFlag;
    132 
    133 typedef struct KitCgEnumValue {
    134   KitSym name;
    135   uint64_t value; /* bit pattern interpreted using the enum's integer base */
    136 } KitCgEnumValue;
    137 
    138 typedef struct KitCgRecordDesc {
    139   KitSym tag;
    140   const KitCgField* fields;
    141   uint32_t nfields;
    142   int is_union;
    143   uint32_t align_override; /* 0 = natural, >0 explicit record alignment */
    144 } KitCgRecordDesc;
    145 
    146 /* Builtin ids are stable for the compiler. Pointer, array, and function
    147  * constructors return a stable id for the same shape within one compiler;
    148  * aliases, records, and enums allocate fresh user-facing identities.
    149  *
    150  * Integer types are width-only storage types. Signedness is carried by
    151  * operations, comparisons, conversions, and ABI extension attributes. */
    152 KIT_API KitCgBuiltinTypes kit_cg_builtin_types(KitCompiler*);
    153 
    154 /* Interned structural types. Address space 0 is the normal target data
    155  * address space. */
    156 KIT_API KitCgTypeId kit_cg_type_func(KitCompiler*, KitCgFuncSig sig);
    157 KIT_API KitCgTypeId kit_cg_type_ptr(KitCompiler*, KitCgTypeId pointee,
    158                                     uint32_t address_space);
    159 KIT_API KitCgTypeId kit_cg_type_array(KitCompiler*, KitCgTypeId elem,
    160                                       uint64_t count);
    161 
    162 /* Fresh nominal/source-facing types. Enums use a width-only integer base. */
    163 KIT_API KitCgTypeId kit_cg_type_alias(KitCompiler*, KitSym name,
    164                                       KitCgTypeId base);
    165 KIT_API KitCgTypeId kit_cg_type_record(KitCompiler*, KitSym tag,
    166                                        const KitCgField* fields,
    167                                        uint32_t nfields);
    168 KIT_API KitCgTypeId kit_cg_type_record_ex(KitCompiler*, const KitCgRecordDesc*);
    169 KIT_API KitCgTypeId kit_cg_type_enum(KitCompiler*, KitSym tag, KitCgTypeId base,
    170                                      const KitCgEnumValue* values,
    171                                      uint32_t nvalues);
    172 
    173 /* Type queries. These report codegen storage, ABI, and target layout facts. */
    174 KIT_API KitCgTypeKind kit_cg_type_kind(KitCompiler*, KitCgTypeId);
    175 KIT_API uint64_t kit_cg_type_size(KitCompiler*, KitCgTypeId);
    176 KIT_API uint32_t kit_cg_type_align(KitCompiler*, KitCgTypeId);
    177 KIT_API uint32_t kit_cg_type_int_width(KitCompiler*, KitCgTypeId);
    178 KIT_API uint32_t kit_cg_type_float_width(KitCompiler*, KitCgTypeId);
    179 
    180 KIT_API KitCgTypeId kit_cg_type_ptr_pointee(KitCompiler*, KitCgTypeId);
    181 KIT_API uint32_t kit_cg_type_ptr_address_space(KitCompiler*, KitCgTypeId);
    182 KIT_API KitCgTypeId kit_cg_type_array_elem(KitCompiler*, KitCgTypeId);
    183 KIT_API uint64_t kit_cg_type_array_count(KitCompiler*, KitCgTypeId);
    184 
    185 /* The function's result; result.type == KIT_CG_TYPE_NONE for a void function. */
    186 KIT_API KitCgFuncResult kit_cg_type_func_result(KitCompiler*, KitCgTypeId);
    187 KIT_API uint32_t kit_cg_type_func_nparams(KitCompiler*, KitCgTypeId);
    188 KIT_API KitCgFuncParam kit_cg_type_func_param(KitCompiler*, KitCgTypeId,
    189                                               uint32_t index);
    190 KIT_API KitCgCallConv kit_cg_type_func_call_conv(KitCompiler*, KitCgTypeId);
    191 KIT_API int kit_cg_type_func_is_variadic(KitCompiler*, KitCgTypeId);
    192 
    193 KIT_API uint32_t kit_cg_type_record_nfields(KitCompiler*, KitCgTypeId);
    194 /* Returns KIT_OK and fills any non-NULL out parameters on success. */
    195 KIT_API KitStatus kit_cg_type_record_field(KitCompiler*, KitCgTypeId,
    196                                            uint32_t index, KitCgField* out,
    197                                            uint64_t* offset_out);
    198 
    199 typedef enum KitCgSymbolFeature {
    200   KIT_CG_SYMFEAT_WEAK,
    201   KIT_CG_SYMFEAT_PROTECTED_VISIBILITY,
    202   KIT_CG_SYMFEAT_DLLIMPORT,
    203   KIT_CG_SYMFEAT_DLLEXPORT,
    204   KIT_CG_SYMFEAT_COMDAT,
    205   KIT_CG_SYMFEAT_COMMON,
    206   KIT_CG_SYMFEAT_MERGE_SECTIONS,
    207   KIT_CG_SYMFEAT_CONSTRUCTOR_PRIORITY,
    208   KIT_CG_SYMFEAT_TLS_LOCAL_EXEC,
    209   KIT_CG_SYMFEAT_TLS_INITIAL_EXEC,
    210   KIT_CG_SYMFEAT_TLS_LOCAL_DYNAMIC,
    211   KIT_CG_SYMFEAT_TLS_GENERAL_DYNAMIC,
    212 } KitCgSymbolFeature;
    213 
    214 typedef enum KitCgBackendFeatureFlag {
    215   KIT_CG_BACKEND_UNALIGNED_MEMORY = 1ull << 0,
    216   KIT_CG_BACKEND_STRICT_ALIGNMENT = 1ull << 1,
    217   KIT_CG_BACKEND_RED_ZONE = 1ull << 2,
    218   KIT_CG_BACKEND_SIMD = 1ull << 3,
    219   KIT_CG_BACKEND_POINTER_AUTH = 1ull << 4,
    220   KIT_CG_BACKEND_BRANCH_PROTECTION = 1ull << 5,
    221   /* Instruction and data caches are coherent: freshly written code is
    222    * executable without an explicit cache-flush / instruction-sync sequence.
    223    * Set for x86 (snooping I-cache) and wasm (no hardware cache model). Not set
    224    * for aarch64 / RISC-V, where JITs and self-modifying code must issue an
    225    * explicit __clear_cache (IC/DC maintenance + ISB; fence.i) before running
    226    * newly emitted instructions. */
    227   KIT_CG_BACKEND_ICACHE_COHERENT = 1ull << 6,
    228 } KitCgBackendFeatureFlag;
    229 
    230 /* Capability queries answer whether the selected target/API can lower the
    231  * requested feature correctly, not whether it is fast. These are target
    232  * facts, not knobs: frontends use them to choose a legal lowering or to emit
    233  * an unsupported-feature diagnostic before asking CG to produce output. */
    234 KIT_API int kit_cg_target_supports_call_conv(KitCompiler*, KitCgCallConv);
    235 KIT_API int kit_cg_target_supports_symbol_feature(KitCompiler*,
    236                                                   KitCgSymbolFeature);
    237 /* kit_cg_target_supports_intrinsic is declared after KitCgIntrinsic. */
    238 KIT_API uint64_t kit_cg_target_backend_features(KitCompiler*);
    239 
    240 /* Shape of the target's `va_list` object, as an ABI fact. Frontends that
    241  * lower <stdarg.h> consult this to pick the right va_list representation
    242  * without reaching into libkit-internal ABI tables:
    243  *   KIT_CG_VALIST_OPAQUE  : implementation-private blob.
    244  *   KIT_CG_VALIST_POINTER : a single pointer that walks the arg area.
    245  *   KIT_CG_VALIST_AAPCS64 : the AArch64 __va_list register-save record.
    246  *   KIT_CG_VALIST_SYSV_X64: the System V x86-64 register-save record. */
    247 typedef enum KitCgVaListKind {
    248   KIT_CG_VALIST_OPAQUE,
    249   KIT_CG_VALIST_POINTER,
    250   KIT_CG_VALIST_AAPCS64,
    251   KIT_CG_VALIST_SYSV_X64,
    252 } KitCgVaListKind;
    253 KIT_API KitCgVaListKind kit_cg_target_va_list_kind(const KitCompiler*);
    254 
    255 /* The C source-level symbol prefix the active object format prepends on
    256  * disk: "_" for Mach-O, "" for ELF / COFF / Wasm. Never NULL. Drives the
    257  * preprocessor's __USER_LABEL_PREFIX__. */
    258 KIT_API const char* kit_cg_target_c_label_prefix(const KitCompiler*);
    259 
    260 /* Pointer width in bytes for an architecture, as a target fact independent of
    261  * any constructed KitTarget. Single source of truth for the byte-aligned
    262  * pointer size, so the object-format detector, the driver triple parser, and
    263  * any internal CG/link code agree on one mapping. Header-only (no KIT_API TU)
    264  * so it links anywhere the public headers reach — including arches that have no
    265  * codegen backend (x86_32 / arm32 / arm64 are still ABI-classifiable here).
    266  * wasm reports 4 (wasm32; wasm64's 8-byte width is carried on the target spec,
    267  * not the arch kind). Returns 0 for an unknown KitArchKind. */
    268 static inline uint8_t kit_arch_ptr_size(KitArchKind arch) {
    269   switch (arch) {
    270     case KIT_ARCH_X86_32:
    271     case KIT_ARCH_ARM_32:
    272     case KIT_ARCH_RV32:
    273     case KIT_ARCH_WASM:
    274       return 4u;
    275     case KIT_ARCH_X86_64:
    276     case KIT_ARCH_ARM_64:
    277     case KIT_ARCH_RV64:
    278       return 8u;
    279   }
    280   return 0u;
    281 }
    282 
    283 /* ============================================================
    284  * Memory Access
    285  * ============================================================ */
    286 
    287 typedef enum KitCgMemAccessFlag {
    288   KIT_CG_MEM_NONE = 0,
    289   /* Access is an externally observable side effect and must not be merged,
    290    * removed, or reordered across other volatile accesses. */
    291   KIT_CG_MEM_VOLATILE = 1u << 0,
    292 } KitCgMemAccessFlag;
    293 
    294 typedef struct KitCgMemAccess {
    295   KitCgTypeId type;       /* value type loaded/stored, or element type */
    296   uint32_t align;         /* 0 = natural for type */
    297   uint32_t address_space; /* normally inherited from pointer type */
    298   uint32_t flags;         /* KitCgMemAccessFlag */
    299 } KitCgMemAccess;
    300 
    301 /* ============================================================
    302  * Declarations and Symbols
    303  * ============================================================ */
    304 
    305 typedef enum KitCgVisibility {
    306   /* Externally visible, object-format-default visibility. On ELF this maps to
    307    * STV_DEFAULT and remains preemptible when bind/output mode allow it. On
    308    * formats without an equivalent visibility field, this is the normal visible
    309    * symbol state. Local-bind symbols are still local. */
    310   KIT_CG_VIS_DEFAULT,
    311   KIT_CG_VIS_HIDDEN,
    312   KIT_CG_VIS_PROTECTED,
    313 } KitCgVisibility;
    314 
    315 typedef enum KitCgSymbolFlag {
    316   KIT_CG_SYMFLAG_NONE = 0,
    317   KIT_CG_SYM_USED = 1u << 0,
    318   KIT_CG_SYM_DLLIMPORT = 1u << 1,
    319   KIT_CG_SYM_DLLEXPORT = 1u << 2,
    320 } KitCgSymbolFlag;
    321 
    322 typedef struct KitCgSymbolAttrs {
    323   KitSymBind bind;
    324   KitCgVisibility visibility;
    325   uint32_t flags; /* KitCgSymbolFlag */
    326 } KitCgSymbolAttrs;
    327 
    328 typedef enum KitCgFuncFlag {
    329   KIT_CG_FUNC_NONE = 0,
    330   KIT_CG_FUNC_NORETURN = 1u << 0,
    331   KIT_CG_FUNC_IFUNC = 1u << 1,
    332   KIT_CG_FUNC_COLD = 1u << 2,
    333   KIT_CG_FUNC_HOT = 1u << 3,
    334   KIT_CG_FUNC_NAKED = 1u << 4,
    335   KIT_CG_FUNC_INTERRUPT = 1u << 5,
    336   KIT_CG_FUNC_NO_RED_ZONE = 1u << 6,
    337 } KitCgFuncFlag;
    338 
    339 typedef enum KitCgInlinePolicy {
    340   KIT_CG_INLINE_DEFAULT,
    341   KIT_CG_INLINE_HINT,
    342   KIT_CG_INLINE_ALWAYS,
    343   KIT_CG_INLINE_NEVER,
    344 } KitCgInlinePolicy;
    345 
    346 typedef struct KitCgFuncAttrs {
    347   uint32_t flags;       /* KitCgFuncFlag */
    348   uint32_t stack_align; /* 0 = ABI default */
    349   KitSym section;       /* 0 = target default */
    350   KitSym target_features;
    351   KitCgInlinePolicy inline_policy;
    352   /* Wasm-target import descriptor. Honored only by the wasm backend, ignored
    353    * by other targets. Promotes an undefined function symbol into a wasm
    354    * `(import "<module>" "<name>" ...)` entry instead of a missing definition.
    355    * Both 0 leaves the backend to fall back to module="env", name=<sym name>
    356    * when an undefined function is referenced. */
    357   KitSym wasm_import_module;
    358   KitSym wasm_import_name;
    359 } KitCgFuncAttrs;
    360 
    361 typedef enum KitCgTlsModel {
    362   /* Let the target/backend choose from the symbol properties, visibility,
    363    * output mode, and object format. Non-AUTO values are frontend requests
    364    * from source attributes or driver options; unsupported requests should be
    365    * diagnosed or conservatively widened. Object-format mechanisms such as
    366    * Mach-O TLVP are target-selected implementation details. */
    367   KIT_CG_TLS_AUTO,
    368   KIT_CG_TLS_LOCAL_EXEC,
    369   KIT_CG_TLS_INITIAL_EXEC,
    370   KIT_CG_TLS_LOCAL_DYNAMIC,
    371   KIT_CG_TLS_GENERAL_DYNAMIC,
    372 } KitCgTlsModel;
    373 
    374 typedef enum KitCgObjectFlag {
    375   KIT_CG_OBJ_NONE = 0,
    376   KIT_CG_OBJ_READONLY = 1u << 0,
    377   KIT_CG_OBJ_TLS = 1u << 1,
    378 } KitCgObjectFlag;
    379 
    380 typedef struct KitCgObjectAttrs {
    381   KitCgTlsModel tls_model;
    382   uint32_t flags; /* KitCgObjectFlag */
    383   KitSym section; /* 0 = target default */
    384   uint32_t align; /* 0 = natural */
    385 } KitCgObjectAttrs;
    386 
    387 typedef enum KitCgDeclKind {
    388   KIT_CG_DECL_FUNC,
    389   KIT_CG_DECL_OBJECT,
    390 } KitCgDeclKind;
    391 
    392 typedef struct KitCgDecl {
    393   KitCgDeclKind kind;
    394   KitSym linkage_name; /* exact linker-visible spelling */
    395   KitSym display_name; /* optional source/debug spelling; 0 = linkage_name */
    396   KitCgTypeId type;
    397   KitCgSymbolAttrs sym;
    398   union {
    399     KitCgFuncAttrs func;
    400     KitCgObjectAttrs object;
    401   } as;
    402 } KitCgDecl;
    403 
    404 typedef struct KitCgAlias {
    405   KitSym linkage_name;
    406   KitSym display_name; /* optional source/debug spelling; 0 = linkage_name */
    407   KitCgSym target;
    408   KitCgSymbolAttrs sym;
    409 } KitCgAlias;
    410 
    411 /* The declared type is the function type for function declarations and the
    412  * object type for object declarations. linkage_name is already mangled and
    413  * object-format decorated as desired by the frontend; CG does not apply a
    414  * C-language name policy.
    415  *
    416  * Undefined weak references are ordinary declarations with sym.bind =
    417  * KIT_SB_WEAK and no definition. Weak aliases are aliases whose attrs bind
    418  * is KIT_SB_WEAK. */
    419 KIT_API KitCgSym kit_cg_decl(KitCg*, KitCgDecl decl);
    420 
    421 /* Defines alias.linkage_name as another symbol for alias.target. */
    422 KIT_API KitCgSym kit_cg_alias(KitCg*, KitCgAlias alias);
    423 
    424 /* Converts a source-level C ABI symbol spelling to the exact object/linker
    425  * spelling for the selected target. This is object-format decoration only
    426  * (for example Mach-O's leading underscore); language-specific mangling
    427  * remains the frontend's responsibility. Use this when filling
    428  * KitCgDecl.linkage_name for symbols that should interoperate with C entry
    429  * names, libc symbols, and linker entry lookup. */
    430 KIT_API KitSym kit_cg_c_linkage_name(KitCompiler*, KitSym source_name);
    431 
    432 /* ============================================================
    433  * Lifecycle and Source Locations
    434  * ============================================================ */
    435 
    436 KIT_API KitStatus kit_cg_new(KitCompiler*, KitCg** cg_out);
    437 
    438 typedef struct KitCgUnitOptions {
    439   KitSlice source_name; /* diagnostic/provenance label; may be empty */
    440   uint32_t source_id;   /* 0 means "unspecified" */
    441   uint32_t flags;       /* reserved; must be 0 */
    442 } KitCgUnitOptions;
    443 
    444 typedef enum KitCgOutputKind {
    445   KIT_CG_OUTPUT_RELOCATABLE = 0,
    446   KIT_CG_OUTPUT_EXECUTABLE = 1,
    447   KIT_CG_OUTPUT_SHARED = 2,
    448   KIT_CG_OUTPUT_ARCHIVE_MEMBER = 3,
    449 } KitCgOutputKind;
    450 
    451 typedef enum KitCgInterpositionPolicy {
    452   KIT_CG_INTERPOSITION_DEFAULT = 0,
    453   KIT_CG_INTERPOSITION_NONE = 1,
    454   KIT_CG_INTERPOSITION_DEFAULT_VISIBILITY = 2,
    455 } KitCgInterpositionPolicy;
    456 
    457 typedef struct KitCgFinishOptions {
    458   uint8_t output_kind;          /* KitCgOutputKind */
    459   uint8_t interposition_policy; /* KitCgInterpositionPolicy */
    460   uint8_t pad[2];
    461   const KitCgSym* preserved_symbols;
    462   uint32_t npreserved_symbols;
    463 } KitCgFinishOptions;
    464 
    465 KIT_API KitStatus kit_cg_begin(KitCg*, KitObjBuilder* out,
    466                                const KitCodeOptions*);
    467 KIT_API KitStatus kit_cg_begin_unit(KitCg*, const KitCgUnitOptions*);
    468 KIT_API KitStatus kit_cg_end_unit(KitCg*);
    469 KIT_API KitStatus kit_cg_finish(KitCg*, const KitCgFinishOptions*);
    470 KIT_API KitStatus kit_cg_detach(KitCg*);
    471 KIT_API KitStatus kit_cg_abort(KitCg*);
    472 KIT_API void kit_cg_free(KitCg*);
    473 
    474 /* Sticky source location. Function, scope, local, param, instruction, and
    475  * data-definition debug records use the current location. */
    476 KIT_API void kit_cg_set_loc(KitCg*, KitSrcLoc);
    477 
    478 /* ============================================================
    479  * Function Bodies and Locals
    480  * ============================================================ */
    481 
    482 KIT_API void kit_cg_func_begin(KitCg*, KitCgSym sym);
    483 KIT_API void kit_cg_func_begin_attrs(KitCg*, KitCgSym sym,
    484                                      KitCgFuncAttrs attrs);
    485 KIT_API void kit_cg_func_end(KitCg*);
    486 
    487 typedef enum KitCgLocalFlag {
    488   KIT_CG_LOCALFLAG_NONE = 0,
    489   KIT_CG_LOCAL_ARTIFICIAL = 1u << 1,
    490   KIT_CG_LOCAL_OPTIMIZED_OUT = 1u << 2,
    491   KIT_CG_LOCAL_COMPILER_TEMP = 1u << 3,
    492   /* Force an addressable storage home even when the type is scalar. Frontends
    493    * use this for source objects whose accesses must remain memory operations
    494    * (for example C volatile automatic objects). */
    495   KIT_CG_LOCAL_MEMORY_REQUIRED = 1u << 4,
    496 } KitCgLocalFlag;
    497 
    498 typedef struct KitCgLocalAttrs {
    499   KitSym name;
    500   uint32_t align; /* 0 = natural */
    501   uint32_t flags; /* KitCgLocalFlag */
    502 } KitCgLocalAttrs;
    503 
    504 KIT_API KitCgLocal kit_cg_local(KitCg*, KitCgTypeId type,
    505                                 KitCgLocalAttrs attrs);
    506 /* Declares a source parameter as a local handle. Parameters must be declared
    507  * in order before ordinary locals; therefore the first n parameter handles in
    508  * a function are also the first n local ids. */
    509 KIT_API KitCgLocal kit_cg_param(KitCg*, uint32_t index, KitCgTypeId type,
    510                                 KitCgLocalAttrs attrs);
    511 
    512 /* Pops a byte size and pushes a pointer to stack storage with at least align
    513  * alignment. The allocation lifetime is the current function activation. */
    514 KIT_API void kit_cg_alloca(KitCg*, uint32_t align, KitCgTypeId result_ptr_type);
    515 
    516 /* ============================================================
    517  * Control flow
    518  * ============================================================ */
    519 
    520 /* Structured control flow scopes.
    521  *
    522  * result_type determines whether the scope carries a value:
    523  *   KIT_CG_TYPE_NONE - statement scope, no result.
    524  *   otherwise          - expression scope; break carries a result.
    525  *
    526  * Stack effects when result_type != NONE:
    527  *   break(scope)       -> pop result, exit scope
    528  *   break_true(scope)  -> stack is [result, bool]; pop bool; if true, pop
    529  *                         result and exit; otherwise pop result
    530  *   break_false(scope) -> same but exit on false
    531  *   scope_end(scope)   -> TOS is the fallthrough result
    532  *
    533  * continue/continue_true/continue_false never carry a result; they jump to
    534  * the loop header, not the scope exit. */
    535 KIT_API KitCgScope kit_cg_scope_begin(KitCg*, KitCgTypeId result_type);
    536 
    537 /* Like kit_cg_scope_begin but opens a forward-only block: break exits past
    538  * the scope; continue is not legal. This is the natural shape for `if`/
    539  * `if-else` (a wrapping block whose break is "skip the rest"), and lets
    540  * backends with structured control flow (Wasm) emit `block`/`end` directly
    541  * instead of recognizing arbitrary forward-only label-and-jump patterns. */
    542 KIT_API KitCgScope kit_cg_block_begin(KitCg*, KitCgTypeId result_type);
    543 KIT_API void kit_cg_scope_end(KitCg*, KitCgScope);
    544 /* Expose the labels CG minted for this scope. Frontends that emit
    545  * unstructured `jump`/`branch` ops (rather than going through the
    546  * scope_break/scope_continue helpers) can use these to land control at
    547  * the scope's break/continue points — handy when the same backend needs
    548  * to translate label-targeted jumps back into structured `break;`/
    549  * `continue;` later (the C source target does this). */
    550 KIT_API KitCgLabel kit_cg_scope_break_label(KitCg*, KitCgScope);
    551 KIT_API KitCgLabel kit_cg_scope_continue_label(KitCg*, KitCgScope);
    552 KIT_API void kit_cg_break(KitCg*, KitCgScope);
    553 KIT_API void kit_cg_break_true(KitCg*, KitCgScope);
    554 KIT_API void kit_cg_break_false(KitCg*, KitCgScope);
    555 KIT_API void kit_cg_continue(KitCg*, KitCgScope);
    556 KIT_API void kit_cg_continue_true(KitCg*, KitCgScope);
    557 KIT_API void kit_cg_continue_false(KitCg*, KitCgScope);
    558 
    559 /* Unstructured labels and jumps. */
    560 KIT_API KitCgLabel kit_cg_label_new(KitCg*);
    561 KIT_API void kit_cg_label_place(KitCg*, KitCgLabel);
    562 KIT_API void kit_cg_jump(KitCg*, KitCgLabel);
    563 KIT_API void kit_cg_branch_true(KitCg*, KitCgLabel);
    564 KIT_API void kit_cg_branch_false(KitCg*, KitCgLabel);
    565 
    566 typedef struct KitCgSwitchCase {
    567   uint64_t value; /* bit pattern interpreted using selector_type */
    568   KitCgLabel label;
    569 } KitCgSwitchCase;
    570 
    571 typedef enum KitCgSwitchHint {
    572   KIT_CG_SWITCH_TARGET_DEFAULT,
    573   KIT_CG_SWITCH_BRANCH_CHAIN,
    574   KIT_CG_SWITCH_JUMP_TABLE,
    575 } KitCgSwitchHint;
    576 
    577 typedef struct KitCgSwitch {
    578   KitCgTypeId selector_type;
    579   KitCgLabel default_label;
    580   const KitCgSwitchCase* cases;
    581   uint32_t ncases;
    582   KitCgSwitchHint hint;
    583 } KitCgSwitch;
    584 
    585 /* Pops an integer selector and branches to the case whose value matches
    586  * it, or to default_label if none does. Mirrors the shape of C's
    587  * `switch (val) { case V1: ...; default: ...; }`. Frontends that want
    588  * jump-table dispatch (wasm br_table, computed-goto-style direct
    589  * threading) pass dense case values 0..N-1 — backends can detect the
    590  * shape and emit a real table; the C target lets the host compiler
    591  * decide. The hint is advisory; targets may ignore it. */
    592 KIT_API void kit_cg_switch(KitCg*, KitCgSwitch sw);
    593 
    594 /* Pushes the address of a label in the current function. Label addresses are
    595  * first-class pointer values for direct-threaded interpreters: they may be
    596  * stored, loaded, selected from tables, compared for equality, and consumed by
    597  * kit_cg_computed_goto. They are only valid within the defining function's
    598  * dynamic activation and must not be called or dereferenced as data. */
    599 KIT_API void kit_cg_push_label_addr(KitCg*, KitCgLabel, KitCgTypeId ptr_type);
    600 
    601 /* Pops a label address and branches to it. valid_targets must name the
    602  * non-empty closed set of labels the target may resolve to; targets use it
    603  * for validation, CFG construction, and branch-protection lowering. */
    604 KIT_API void kit_cg_computed_goto(KitCg*, const KitCgLabel* valid_targets,
    605                                   uint32_t ntargets);
    606 
    607 /* Terminates the current block with unreachable code. This is a real
    608  * terminator, not a side-effect intrinsic. */
    609 KIT_API void kit_cg_unreachable(KitCg*);
    610 
    611 /* ============================================================
    612  * Value stack: PLACES and VALUES
    613  * ============================================================
    614  *
    615  * Every stack entry is exactly one of two kinds, and each op below declares the
    616  * kinds it consumes and produces. The op enforces this: handing an op the wrong
    617  * kind is a usage error and panics. CG never *infers* the kind of a stack entry
    618  * or silently inserts a dereference — addressing is always built explicitly.
    619  *
    620  *   PLACE  — an addressable, typed location of an object (a local's storage, a
    621  *            global, or a computed `[base + index*scale + offset]`). Produced
    622  * by push_local / deref / field / elem; consumed by load / store / addr.
    623  *
    624  *   VALUE  — a scalar rvalue: an integer, float, pointer, or 128-bit scalar.
    625  *            Produced by push_int/float/null, push_symbol_addr,
    626  * push_local_addr, addr, and load; consumed by the arithmetic / call / branch
    627  * ops.
    628  *
    629  * Aggregates (records, arrays) are ALWAYS a PLACE — there is no aggregate
    630  * VALUE. Copying an aggregate is an explicit store/memcpy between places.
    631  *
    632  * The four building blocks of addressing:
    633  *   - push_local l : —            -> PLACE          (the local's storage)
    634  *   - addr         : PLACE        -> VALUE(ptr)     (address of the place)
    635  *   - deref        : VALUE(ptr)   -> PLACE          (the place the ptr names)
    636  *   - field i      : PLACE(record)-> PLACE(field)   (sub-object, by layout)
    637  *   - elem         : VALUE(ptr),index VALUE -> PLACE (element of an array/ptr)
    638  * From these, `*p` is `deref`, `p->f` is `deref; field`, `s.f` is `field`,
    639  * `a[i]` is `addr; <decay to *elem>; elem`, and `&x` is `addr`. */
    640 
    641 KIT_API void kit_cg_dup(KitCg*);
    642 KIT_API void kit_cg_dup2(KitCg*); /* duplicates the top two slots */
    643 KIT_API void kit_cg_swap(KitCg*);
    644 KIT_API void kit_cg_drop(KitCg*);
    645 KIT_API void kit_cg_rot3(KitCg*); /* [..., a, b, c] -> [..., b, c, a] */
    646 
    647 /* Returns nonzero when the current top-of-stack value is a compile-time known
    648  * integer-like immediate VALUE. The value is not popped. */
    649 KIT_API int kit_cg_top_const_int(KitCg*, int64_t* out_value);
    650 
    651 /* Push a scalar VALUE. */
    652 KIT_API void kit_cg_push_int(KitCg*, uint64_t value, KitCgTypeId type);
    653 KIT_API void kit_cg_push_float(KitCg*, double value, KitCgTypeId type);
    654 KIT_API void kit_cg_push_null(KitCg*, KitCgTypeId ptr_type);
    655 /* Push the PLACE that is the local's storage. Stack: [] -> [place]. */
    656 KIT_API void kit_cg_push_local(KitCg*, KitCgLocal local);
    657 /* Push the local's address as a pointer VALUE (sugar for push_local; addr).
    658  * Stack: [] -> [ptr]. */
    659 KIT_API void kit_cg_push_local_addr(KitCg*, KitCgLocal local);
    660 
    661 /* Anonymous immutable data. Returns a local readonly object symbol; callers
    662  * can materialize its address (a VALUE) with push_symbol_addr. pointee_type
    663  * describes the logical value at that address, enabling const_data +
    664  * push_symbol_addr + deref + load to materialize arbitrary-width constants. */
    665 KIT_API KitCgSym kit_cg_const_data(KitCg*, const uint8_t* data, size_t len,
    666                                    uint32_t align, KitCgTypeId pointee_type);
    667 
    668 /* Push &sym + addend as a pointer VALUE. For TLS objects this means the address
    669  * of the current thread's instance; the target chooses LE/IE/GD/TLVP or
    670  * equivalent lowering from the symbol attrs and output mode. Stack: [] ->
    671  * [ptr].
    672  */
    673 KIT_API void kit_cg_push_symbol_addr(KitCg*, KitCgSym sym, int64_t addend);
    674 
    675 /* PLACE -> VALUE(ptr): the address of the place (e.g. `&x`, or to pass/escape).
    676  * Stack: [place] -> [ptr]. Errors if TOS is not a PLACE. */
    677 KIT_API void kit_cg_addr(KitCg*);
    678 
    679 /* VALUE(ptr) -> PLACE: the explicit pointer->place transition. The produced
    680  * place is `*(ptr + offset bytes)`; `offset` is a byte displacement folded into
    681  * the addressing mode (0 for a plain `*p`). Stack: [ptr] -> [place]. Errors if
    682  * TOS is not a pointer VALUE — a PLACE must be turned into a pointer with
    683  * `addr` first; the op never guesses. */
    684 KIT_API void kit_cg_deref(KitCg*, int64_t offset);
    685 
    686 /* PLACE(record) -> PLACE(field): project a record place to one of its fields by
    687  * index; the byte offset and field type come from the record's layout (CG owns
    688  * layout). Stack: [place] -> [place]. Errors if TOS is not a record PLACE — for
    689  * `p->f` the frontend does `deref; field`, not `field` on a pointer.
    690  *
    691  * Bit-field PLACE subkind: when field_index names a bit-field, `field` projects
    692  * to a *bit-field place* — a PLACE that addresses the field's storage unit and
    693  * additionally carries the bit-field descriptor (bit offset/width, storage-unit
    694  * size, signedness) from the record layout. A bit-field place is a place like
    695  * any other: a plain `load` reads the field (extract + sign/zero-extend) and a
    696  * plain `store` writes it (read-modify-write insert). There is no separate
    697  * bit-field memop and no bit-field rider on KitCgMemAccess; the place is the
    698  * one and only carrier of bit-field geometry. `addr` and aggregate access on a
    699  * bit-field place are not legal (a bit-field has no addressable byte location);
    700  * the frontend rejects `&` / `sizeof` on a bit-field before reaching CG. */
    701 KIT_API void kit_cg_field(KitCg*, uint32_t field_index);
    702 
    703 /* PLACE -> PLACE(bit-field): tag the TOS place as a bit-field place carrying
    704  * the given bit geometry. This is the manual-addressing counterpart to the
    705  * implicit bit-field projection `field` performs: a frontend that builds the
    706  * storage-unit place itself (deref/elem onto the storage unit) calls this to
    707  * attach the descriptor, after which a plain load/store extracts/inserts the
    708  * field. The place must address the field's storage unit. bit_storage_size is
    709  * the storage- unit size in bytes; bit_signed selects signed extraction on
    710  * load. Stack: [place] -> [place]. There is no separate bit-field memop — the
    711  * place is the one carrier of bit-field geometry. */
    712 KIT_API void kit_cg_field_bits(KitCg*, uint16_t bit_offset, uint16_t bit_width,
    713                                uint32_t bit_storage_size, int bit_signed);
    714 
    715 /* (VALUE(ptr to T), index VALUE) -> PLACE(T): the element at `*(base +
    716  * index*sizeof(T) + offset)`. The index is scaled by sizeof(T) (the pointer's
    717  * pointee) and the constant `offset` byte displacement is folded in, so the
    718  * place is a single `[base + index*scale + offset]` addressing mode (base and
    719  * index dynamic; scale and offset constant). The base is a pointer VALUE; an
    720  * array is decayed to a pointer (`addr` + cast to *T) by the frontend first.
    721  * Stack: [base, index] -> [place]. Errors if the base is not a pointer VALUE.
    722  */
    723 KIT_API void kit_cg_elem(KitCg*, int64_t offset);
    724 
    725 /* Load a VALUE from a PLACE / store a VALUE into a PLACE. The PLACE carries all
    726  * addressing (built via push_local / deref / field / elem); the memop takes no
    727  * effective-address rider. When the PLACE is a bit-field place (produced by
    728  * `field` on a bit-field), the load/store extract/insert the field per the
    729  * descriptor the place carries — `access` then describes only the access type,
    730  * alignment, and volatility, never bit geometry. Both error if the addressed
    731  * operand is not a PLACE — a pointer VALUE must be `deref`'d first.
    732  *
    733  * Stack effects:
    734  *   load:  [place]        -> [value]
    735  *   store: [place, value] -> [] */
    736 KIT_API void kit_cg_load(KitCg*, KitCgMemAccess access);
    737 KIT_API void kit_cg_store(KitCg*, KitCgMemAccess access);
    738 
    739 /* ============================================================
    740  * ABI variadic argument access
    741  * ============================================================ */
    742 
    743 /* This models only target calling-convention varargs; higher-level rest
    744  * parameters should lower to explicit aggregate parameters before reaching CG.
    745  *
    746  * The frontend allocates a local of KIT_CG_BUILTIN_VARARG_STATE and pushes
    747  * that local's address before each operation. The implementation reads and
    748  * writes the state in memory according to the target ABI. */
    749 KIT_API void kit_cg_vararg_start(KitCg*); /* pop &state */
    750 KIT_API void kit_cg_vararg_next(KitCg*,
    751                                 KitCgTypeId type); /* pop &state; push value */
    752 KIT_API void kit_cg_vararg_end(KitCg*);            /* pop &state             */
    753 KIT_API void kit_cg_vararg_copy(KitCg*);           /* pop &dst, &src         */
    754 
    755 /* ============================================================
    756  * Integer Operations
    757  * ============================================================ */
    758 
    759 typedef enum KitCgIntBinOp {
    760   KIT_CG_INT_ADD,
    761   KIT_CG_INT_SUB,
    762   KIT_CG_INT_MUL,
    763   KIT_CG_INT_SDIV,
    764   KIT_CG_INT_UDIV,
    765   KIT_CG_INT_SREM,
    766   KIT_CG_INT_UREM,
    767   KIT_CG_INT_AND,
    768   KIT_CG_INT_OR,
    769   KIT_CG_INT_XOR,
    770   KIT_CG_INT_SHL,
    771   KIT_CG_INT_LSHR,
    772   KIT_CG_INT_ASHR,
    773 } KitCgIntBinOp;
    774 
    775 typedef enum KitCgIntOpFlag {
    776   KIT_CG_INTOP_NONE = 0,
    777   KIT_CG_INTOP_NSW = 1u << 0,
    778   KIT_CG_INTOP_NUW = 1u << 1,
    779   KIT_CG_INTOP_EXACT = 1u << 2,
    780   /* Overflow semantics are explicit because integer types are width-only.
    781    * Signed and unsigned trap/saturate flags are mutually exclusive. */
    782   KIT_CG_INTOP_TRAP_SIGNED_OVERFLOW = 1u << 3,
    783   KIT_CG_INTOP_TRAP_UNSIGNED_OVERFLOW = 1u << 4,
    784   KIT_CG_INTOP_SATURATE_SIGNED = 1u << 5,
    785   KIT_CG_INTOP_SATURATE_UNSIGNED = 1u << 6,
    786 } KitCgIntOpFlag;
    787 
    788 typedef enum KitCgIntCmpOp {
    789   KIT_CG_INT_EQ,
    790   KIT_CG_INT_NE,
    791   KIT_CG_INT_LT_S,
    792   KIT_CG_INT_LE_S,
    793   KIT_CG_INT_GT_S,
    794   KIT_CG_INT_GE_S,
    795   KIT_CG_INT_LT_U,
    796   KIT_CG_INT_LE_U,
    797   KIT_CG_INT_GT_U,
    798   KIT_CG_INT_GE_U,
    799 } KitCgIntCmpOp;
    800 
    801 typedef enum KitCgIntUnOp {
    802   KIT_CG_INT_NEG,
    803   KIT_CG_INT_NOT,
    804   KIT_CG_INT_BNOT,
    805 } KitCgIntUnOp;
    806 
    807 KIT_API void kit_cg_int_binop(KitCg*, KitCgIntBinOp, uint32_t flags);
    808 KIT_API void kit_cg_int_unop(KitCg*, KitCgIntUnOp, uint32_t flags);
    809 KIT_API void kit_cg_int_cmp(KitCg*, KitCgIntCmpOp);
    810 
    811 /* ============================================================
    812  * Floating-Point Operations
    813  * ============================================================ */
    814 
    815 typedef enum KitCgFpBinOp {
    816   KIT_CG_FP_ADD,
    817   KIT_CG_FP_SUB,
    818   KIT_CG_FP_MUL,
    819   KIT_CG_FP_DIV,
    820   /* No FP remainder: it is a libcall (fmod/fmodf/fmodl), which the frontend
    821    * emits directly. */
    822 } KitCgFpBinOp;
    823 
    824 typedef enum KitCgFpCmpOp {
    825   KIT_CG_FP_OEQ,
    826   KIT_CG_FP_ONE,
    827   KIT_CG_FP_OLT,
    828   KIT_CG_FP_OLE,
    829   KIT_CG_FP_OGT,
    830   KIT_CG_FP_OGE,
    831   KIT_CG_FP_UEQ,
    832   KIT_CG_FP_UNE,
    833   KIT_CG_FP_ULT,
    834   KIT_CG_FP_ULE,
    835   KIT_CG_FP_UGT,
    836   KIT_CG_FP_UGE,
    837 } KitCgFpCmpOp;
    838 
    839 typedef enum KitCgFpUnOp {
    840   KIT_CG_FP_NEG,
    841 } KitCgFpUnOp;
    842 
    843 typedef enum KitCgFpFlag {
    844   KIT_CG_FP_NONE = 0,
    845   KIT_CG_FP_REASSOC = 1u << 0,
    846   KIT_CG_FP_NO_NANS = 1u << 1,
    847   KIT_CG_FP_NO_INFS = 1u << 2,
    848   KIT_CG_FP_NO_SIGNED_ZEROS = 1u << 3,
    849   KIT_CG_FP_ALLOW_RECIP = 1u << 4,
    850   KIT_CG_FP_APPROX = 1u << 5,
    851 } KitCgFpFlag;
    852 
    853 KIT_API void kit_cg_fp_binop(KitCg*, KitCgFpBinOp, uint32_t flags);
    854 KIT_API void kit_cg_fp_unop(KitCg*, KitCgFpUnOp, uint32_t flags);
    855 KIT_API void kit_cg_fp_cmp(KitCg*, KitCgFpCmpOp);
    856 
    857 /* ============================================================
    858  * Conversions
    859  * ============================================================ */
    860 
    861 typedef enum KitCgRounding {
    862   KIT_CG_ROUND_DEFAULT,
    863   KIT_CG_ROUND_NEAREST_EVEN,
    864   KIT_CG_ROUND_TOWARD_ZERO,
    865   KIT_CG_ROUND_DOWN,
    866   KIT_CG_ROUND_UP,
    867 } KitCgRounding;
    868 
    869 KIT_API void kit_cg_sext(KitCg*, KitCgTypeId dst);
    870 KIT_API void kit_cg_zext(KitCg*, KitCgTypeId dst);
    871 KIT_API void kit_cg_trunc(KitCg*, KitCgTypeId dst);
    872 KIT_API void kit_cg_ptr_to_int(KitCg*, KitCgTypeId dst);
    873 KIT_API void kit_cg_int_to_ptr(KitCg*, KitCgTypeId dst);
    874 KIT_API void kit_cg_bitcast(KitCg*, KitCgTypeId dst);
    875 KIT_API void kit_cg_fpext(KitCg*, KitCgTypeId dst);
    876 KIT_API void kit_cg_fptrunc(KitCg*, KitCgTypeId dst);
    877 KIT_API void kit_cg_sint_to_float(KitCg*, KitCgTypeId dst,
    878                                   KitCgRounding rounding);
    879 KIT_API void kit_cg_uint_to_float(KitCg*, KitCgTypeId dst,
    880                                   KitCgRounding rounding);
    881 KIT_API void kit_cg_float_to_sint(KitCg*, KitCgTypeId dst,
    882                                   KitCgRounding rounding);
    883 KIT_API void kit_cg_float_to_uint(KitCg*, KitCgTypeId dst,
    884                                   KitCgRounding rounding);
    885 
    886 /* ============================================================
    887  * Calls and Returns
    888  * ============================================================ */
    889 
    890 /* Tail-call policy for a call site.
    891  *
    892  * A tail call is a TERMINATOR: it ends the current function. It pushes no
    893  * result onto the value stack, and the caller must not emit kit_cg_ret
    894  * after it — the call is the return.
    895  *
    896  * Two distinct conditions govern whether a tail call is legal:
    897  *
    898  *  - Signature match is a PRECONDITION the frontend must guarantee: the
    899  *    callee's return type must be ABI-compatible with the enclosing
    900  *    function's declared return type, and the call must sit in return
    901  *    position. A violation is a frontend bug; CG aborts (compiler_panic)
    902  *    regardless of policy — it is never treated as a fallback case.
    903  *
    904  *  - ABI realizability is DISCOVERED during emission and is target-specific:
    905  *    can control transfer to the callee while reusing (and tearing down) the
    906  *    current frame, with the callee's outgoing argument area and return
    907  *    mechanism fitting the space the caller itself received? sret and
    908  *    variadic are NOT inherent blockers — an sret return is forwarded via the
    909  *    function's own incoming sret pointer, and a variadic callee is fine when
    910  *    its argument area fits the caller's incoming area. The usual blocker is
    911  *    an outgoing argument area that exceeds that space; some are arch-specific
    912  *    (e.g. wasm packs varargs into a caller-frame buffer that a sibling call
    913  *    would dangle). This is what ALLOWED vs MUST governs.
    914  */
    915 typedef enum KitCgTailPolicy {
    916   /* Ordinary call. Result is pushed; not a terminator. */
    917   KIT_CG_TAIL_DEFAULT,
    918   /* Tail-call (terminator) if ABI-realizable; otherwise silently emit an
    919    * ordinary call and synthesize the caller's return of the result. Never
    920    * fails for realizability. */
    921   KIT_CG_TAIL_ALLOWED,
    922   /* Tail-call (terminator); if not ABI-realizable, CG fails with a
    923    * diagnostic naming the reason. Never silently degrades to an ordinary
    924    * call. */
    925   KIT_CG_TAIL_MUST,
    926 } KitCgTailPolicy;
    927 
    928 typedef enum KitCgCallFlag {
    929   KIT_CG_CALL_NONE = 0,
    930   KIT_CG_CALL_COLD = 1u << 0,
    931 } KitCgCallFlag;
    932 
    933 typedef struct KitCgCallAttrs {
    934   KitCgTailPolicy tail;
    935   uint32_t flags; /* KitCgCallFlag */
    936   KitCgInlinePolicy inline_policy;
    937 } KitCgCallAttrs;
    938 
    939 /* kit_cg_call pops a computed function pointer plus nargs arguments.
    940  * kit_cg_call_symbol emits a direct call to the declared function symbol,
    941  * allowing the backend/linker to choose PLT/stub/IAT/direct/IFUNC handling.
    942  *
    943  * For tail policies (see KitCgTailPolicy): the call is a terminator that
    944  * pushes no result. A MUST tail call that is not ABI-realizable fails with a
    945  * diagnostic; an ALLOWED tail call that is not realizable silently degrades
    946  * to an ordinary call followed by a synthesized return of the result. A
    947  * tail call whose callee return type is incompatible with the enclosing
    948  * function's return type is a frontend bug and aborts under any policy.
    949  *
    950  * Results: a non-tail call to a value-returning callee pushes the callee's
    951  * single result onto the stack (TOS). A void callee pushes nothing. */
    952 KIT_API void kit_cg_call(KitCg*, uint32_t nargs, KitCgTypeId fn_type,
    953                          KitCgCallAttrs attrs);
    954 KIT_API void kit_cg_call_symbol(KitCg*, KitCgSym sym, uint32_t nargs,
    955                                 KitCgCallAttrs attrs);
    956 /* Returns from the current function. Pops the enclosing function's single
    957  * result value from TOS, or nothing for a void function. This is the single
    958  * return entry point. */
    959 KIT_API void kit_cg_ret(KitCg*);
    960 
    961 /* ============================================================
    962  * Intrinsics
    963  * ============================================================ */
    964 
    965 typedef enum KitCgIntrinsic {
    966   KIT_CG_INTRIN_TRAP,
    967   KIT_CG_INTRIN_CLZ, /* zero input returns bit width     */
    968   KIT_CG_INTRIN_CTZ, /* zero input returns bit width     */
    969   KIT_CG_INTRIN_POPCOUNT,
    970   KIT_CG_INTRIN_BSWAP,
    971   KIT_CG_INTRIN_SETJMP,         /* pop &buf; push i32              */
    972   KIT_CG_INTRIN_LONGJMP,        /* pop &buf, val; no return        */
    973   KIT_CG_INTRIN_SADD_OVERFLOW,  /* pop a, b; push result, overflow */
    974   KIT_CG_INTRIN_UADD_OVERFLOW,  /* pop a, b; push result, overflow */
    975   KIT_CG_INTRIN_SSUB_OVERFLOW,  /* pop a, b; push result, overflow */
    976   KIT_CG_INTRIN_USUB_OVERFLOW,  /* pop a, b; push result, overflow */
    977   KIT_CG_INTRIN_SMUL_OVERFLOW,  /* pop a, b; push result, overflow */
    978   KIT_CG_INTRIN_UMUL_OVERFLOW,  /* pop a, b; push result, overflow */
    979   KIT_CG_INTRIN_FMA,            /* pop a, b, c; push a * b + c     */
    980   KIT_CG_INTRIN_PREFETCH,       /* pop addr; no result             */
    981   KIT_CG_INTRIN_EXPECT,         /* pop val, expected; push val     */
    982   KIT_CG_INTRIN_ASSUME_ALIGNED, /* pop ptr; push aligned ptr       */
    983   KIT_CG_INTRIN_SYSCALL,        /* pop nr, args...; push long      */
    984   KIT_CG_INTRIN_IRQ_SAVE,       /* push unsigned long              */
    985   KIT_CG_INTRIN_IRQ_RESTORE,    /* pop prev                        */
    986   KIT_CG_INTRIN_IRQ_DISABLE,
    987   KIT_CG_INTRIN_IRQ_ENABLE,
    988   KIT_CG_INTRIN_DMB, /* pop KitCgBarrierScope         */
    989   KIT_CG_INTRIN_DSB, /* pop KitCgBarrierScope         */
    990   KIT_CG_INTRIN_ISB,
    991   KIT_CG_INTRIN_DCACHE_CLEAN, /* pop ptr, size                   */
    992   KIT_CG_INTRIN_DCACHE_INVALIDATE,
    993   KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE,
    994   KIT_CG_INTRIN_ICACHE_INVALIDATE,
    995   KIT_CG_INTRIN_CPU_NOP,
    996   KIT_CG_INTRIN_CPU_YIELD,
    997   KIT_CG_INTRIN_WFI,
    998   KIT_CG_INTRIN_WFE,         /* arm/aarch64 only                */
    999   KIT_CG_INTRIN_SEV,         /* arm/aarch64 only                */
   1000   KIT_CG_INTRIN_CORO_SWITCH, /* pop from, to, value; push value */
   1001   /* Frame-pointer-chain introspection (GCC __builtin_frame_address /
   1002    * __builtin_return_address). The level is a compile-time constant passed as a
   1003    * single immediate operand (nargs == 1); level 0 names the current frame.
   1004    * Both push a void*. Lowered as an unrolled FP walk; targets with no frame
   1005    * pointer (wasm) report unsupported. */
   1006   KIT_CG_INTRIN_FRAME_ADDRESS,  /* pop level(u32 const); push void* */
   1007   KIT_CG_INTRIN_RETURN_ADDRESS, /* pop level(u32 const); push void* */
   1008 } KitCgIntrinsic;
   1009 
   1010 typedef enum KitCgBarrierScope {
   1011   KIT_CG_BARRIER_FULL,
   1012   KIT_CG_BARRIER_INNER,
   1013   KIT_CG_BARRIER_INNER_STORE,
   1014   KIT_CG_BARRIER_OUTER,
   1015   KIT_CG_BARRIER_OUTER_STORE,
   1016   KIT_CG_BARRIER_NON_SHARE,
   1017 } KitCgBarrierScope;
   1018 
   1019 /* Pops nargs operands. Pushes result_type unless result_type is
   1020  * KIT_CG_TYPE_NONE or void. Overflow intrinsics push two values:
   1021  * result, overflow_bool regardless of result_type. Syscall uses nargs = argc +
   1022  * 1: the syscall number plus 0..6 long arguments. Runtime-extension intrinsics
   1023  * mirror rt/include/kit/{syscall,baremetal,coro}.h and must diagnose targets
   1024  * where the primitive has no legal lowering. */
   1025 KIT_API void kit_cg_intrinsic(KitCg*, KitCgIntrinsic, uint32_t nargs,
   1026                               KitCgTypeId result_type);
   1027 
   1028 /* Capability query for kit_cg_intrinsic: true when the selected target has a
   1029  * legal lowering for this intrinsic (see kit_cg_target_supports_call_conv for
   1030  * the contract). Frontends test this before requesting a baremetal/CPU
   1031  * intrinsic so they can emit their own unsupported-feature diagnostic instead
   1032  * of tripping the CG fatal. */
   1033 KIT_API int kit_cg_target_supports_intrinsic(KitCompiler*, KitCgIntrinsic);
   1034 
   1035 /* ============================================================
   1036  * Fixed-Sized Memory Operations
   1037  * ============================================================ */
   1038 
   1039 /* Stack:
   1040  *   memcpy/memmove: [dst, src] -> []
   1041  *   memset:         [dst]      -> [] */
   1042 KIT_API void kit_cg_memcpy(KitCg*, uint64_t size, KitCgMemAccess dst,
   1043                            KitCgMemAccess src);
   1044 KIT_API void kit_cg_memmove(KitCg*, uint64_t size, KitCgMemAccess dst,
   1045                             KitCgMemAccess src);
   1046 KIT_API void kit_cg_memset(KitCg*, uint8_t val, uint64_t size,
   1047                            KitCgMemAccess dst);
   1048 
   1049 /* ============================================================
   1050  * Atomics
   1051  * ============================================================ */
   1052 
   1053 typedef enum KitCgAtomicOp {
   1054   KIT_CG_ATOMIC_XCHG,
   1055   KIT_CG_ATOMIC_ADD,
   1056   KIT_CG_ATOMIC_SUB,
   1057   KIT_CG_ATOMIC_AND,
   1058   KIT_CG_ATOMIC_OR,
   1059   KIT_CG_ATOMIC_XOR,
   1060   KIT_CG_ATOMIC_NAND,
   1061 } KitCgAtomicOp;
   1062 
   1063 typedef enum KitCgMemOrder {
   1064   KIT_CG_MO_RELAXED,
   1065   KIT_CG_MO_CONSUME,
   1066   KIT_CG_MO_ACQUIRE,
   1067   KIT_CG_MO_RELEASE,
   1068   KIT_CG_MO_ACQ_REL,
   1069   KIT_CG_MO_SEQ_CST,
   1070 } KitCgMemOrder;
   1071 
   1072 KIT_API int kit_cg_atomic_is_legal(KitCompiler*, KitCgMemAccess access,
   1073                                    KitCgMemOrder order);
   1074 KIT_API int kit_cg_atomic_is_lock_free(KitCompiler*, KitCgMemAccess access);
   1075 KIT_API void kit_cg_atomic_load(KitCg*, KitCgMemAccess access,
   1076                                 KitCgMemOrder order);
   1077 KIT_API void kit_cg_atomic_store(KitCg*, KitCgMemAccess access,
   1078                                  KitCgMemOrder order);
   1079 KIT_API void kit_cg_atomic_rmw(KitCg*, KitCgMemAccess access, KitCgAtomicOp,
   1080                                KitCgMemOrder order);
   1081 /* Stack: [ptr, expected, desired] -> [prior, ok_bool]. */
   1082 KIT_API void kit_cg_atomic_cmpxchg(KitCg*, KitCgMemAccess access,
   1083                                    KitCgMemOrder success, KitCgMemOrder failure,
   1084                                    int weak);
   1085 KIT_API void kit_cg_atomic_fence(KitCg*, KitCgMemOrder);
   1086 
   1087 /* ============================================================
   1088  * Inline Assembly
   1089  * ============================================================ */
   1090 
   1091 typedef enum KitCgAsmDir {
   1092   KIT_CG_ASM_IN,
   1093   KIT_CG_ASM_OUT,
   1094   KIT_CG_ASM_INOUT,
   1095 } KitCgAsmDir;
   1096 
   1097 typedef enum KitCgAsmFlag {
   1098   KIT_CG_ASM_NONE = 0,
   1099   KIT_CG_ASM_VOLATILE = 1u << 0,
   1100   KIT_CG_ASM_PURE = 1u << 1,
   1101   KIT_CG_ASM_NOMEM = 1u << 2,
   1102   KIT_CG_ASM_READONLY = 1u << 3,
   1103   KIT_CG_ASM_PRESERVES_FLAGS = 1u << 4,
   1104   KIT_CG_ASM_NOSTACK = 1u << 5,
   1105   KIT_CG_ASM_NORETURN = 1u << 6,
   1106 } KitCgAsmFlag;
   1107 
   1108 typedef enum KitCgAsmClobberAbiSet {
   1109   KIT_CG_ASM_CLOBBER_ABI_NONE = 0,
   1110   KIT_CG_ASM_CLOBBER_ABI_CALLER_SAVED = 1u << 0,
   1111   /* Every callee-saved register of the target ABI. The compiler preserves them
   1112    * across the asm block (prologue/epilogue save on the optimizer path, a
   1113    * per-block spill on the single-pass path) just as it would for named
   1114    * callee-saved clobbers — an arch-neutral way to say "this asm trashes the
   1115    * callee-saved register file". */
   1116   KIT_CG_ASM_CLOBBER_ABI_CALLEE_SAVED = 1u << 1,
   1117 } KitCgAsmClobberAbiSet;
   1118 
   1119 typedef struct KitCgAsmOperand {
   1120   KitSym constraint; /* interned target constraint string */
   1121   KitSym name;       /* interned symbolic operand name; 0 if absent */
   1122   KitCgTypeId type;
   1123   /* Explicit hard register this operand must occupy, named by its target
   1124    * spelling ("r10", "x8", "a7", ...); 0 when unconstrained. Set by a frontend
   1125    * for a GNU local register variable (`register T x __asm__("r10")`) used as
   1126    * an operand. The name is opaque to the frontend and CG — only the target's
   1127    * register file resolves it to a physical register. */
   1128   KitSym reg;
   1129   uint8_t dir; /* KitCgAsmDir */
   1130   uint8_t pad[3];
   1131 } KitCgAsmOperand;
   1132 
   1133 typedef struct KitCgInlineAsm {
   1134   KitSym tmpl;
   1135   const KitCgAsmOperand* outputs;
   1136   uint32_t noutputs;
   1137   const KitCgAsmOperand* inputs;
   1138   uint32_t ninputs;
   1139   const KitSym* clobbers;
   1140   uint32_t nclobbers;
   1141   uint32_t flags;            /* KitCgAsmFlag */
   1142   uint32_t clobber_abi_sets; /* KitCgAsmClobberAbiSet */
   1143 } KitCgInlineAsm;
   1144 
   1145 /* Inputs are popped in declaration order. Outputs are pushed in declaration
   1146  * order as fresh values after the asm block. INOUT outputs consume one
   1147  * initial value each after the explicit inputs, in output declaration order;
   1148  * tied operands, earlyclobber, register classes, explicit registers,
   1149  * immediates, memory operands, and target-specific alternatives are expressed
   1150  * in the per-operand constraint string. Template, constraints, and clobbers
   1151  * are pre-interned strings. clobber_abi_sets names target-defined ABI register
   1152  * sets such as all caller-saved registers. */
   1153 KIT_API void kit_cg_inline_asm(KitCg*, KitCgInlineAsm asm_block);
   1154 KIT_API void kit_cg_file_scope_asm(KitCg*, KitSlice asm_source);
   1155 
   1156 /* ============================================================
   1157  * Data Definitions
   1158  * ============================================================ */
   1159 
   1160 typedef enum KitCgDataDefFlag {
   1161   KIT_CG_DATADEF_NONE = 0,
   1162   KIT_CG_DATADEF_RETAIN = 1u << 0,
   1163   KIT_CG_DATADEF_MERGE = 1u << 1,
   1164   KIT_CG_DATADEF_STRINGS = 1u << 2,
   1165   KIT_CG_DATADEF_READONLY = 1u << 3,
   1166   KIT_CG_DATADEF_ZERO_FILL = 1u << 4,
   1167   /* Static storage with function/block scope for source backends. Native
   1168    * object backends may still emit ordinary private data. */
   1169   KIT_CG_DATADEF_FUNCTION_LOCAL = 1u << 5,
   1170 } KitCgDataDefFlag;
   1171 
   1172 typedef struct KitCgDataDefAttrs {
   1173   KitSym section;   /* 0 = target default for the symbol */
   1174   uint32_t align;   /* 0 = natural */
   1175   uint32_t entsize; /* 0 = target default; used by merge/string data */
   1176   uint32_t flags;   /* KitCgDataDefFlag */
   1177 } KitCgDataDefAttrs;
   1178 
   1179 /* data_begin defines storage for an already-declared object symbol.
   1180  * data_common defines tentative/common zero-initialized storage when the
   1181  * target format supports it.
   1182  *
   1183  * Data definitions may be emitted while a function body is open. The current
   1184  * function remains open across data_begin/data_end so frontends can define
   1185  * block-scope statics and computed-goto dispatch tables that need function
   1186  * label context. */
   1187 KIT_API void kit_cg_data_begin(KitCg*, KitCgSym sym, KitCgDataDefAttrs attrs);
   1188 KIT_API void kit_cg_data_common(KitCg*, KitCgSym sym, uint64_t size,
   1189                                 uint32_t align);
   1190 KIT_API void kit_cg_data_end(KitCg*);
   1191 
   1192 /* Appends to the currently open data definition. */
   1193 KIT_API void kit_cg_data_align(KitCg*, uint32_t align);
   1194 KIT_API void kit_cg_data_pad(KitCg*, uint64_t size, uint8_t value);
   1195 KIT_API void kit_cg_data_int(KitCg*, uint64_t value, KitCgTypeId type);
   1196 KIT_API void kit_cg_data_float(KitCg*, double value, KitCgTypeId type);
   1197 KIT_API void kit_cg_data_bytes(KitCg*, const uint8_t* data, size_t len);
   1198 KIT_API void kit_cg_data_zero(KitCg*, uint64_t size);
   1199 
   1200 /* Relocatable data expressions. These describe the value encoded in the data
   1201  * stream; they do not request a lowering strategy such as GOT, PLT, TLVP, or
   1202  * a TLS access model. width is the encoded field width in bytes. address_space
   1203  * is the pointer address space of address constants; use 0 for the target data
   1204  * address space. */
   1205 KIT_API void kit_cg_data_addr(KitCg*, KitCgSym target, int64_t addend,
   1206                               uint32_t width, uint32_t address_space);
   1207 /* Encodes a function-local label address for direct-threaded dispatch tables.
   1208  * The target label must have been created by kit_cg_label_new; it does not
   1209  * need to be placed yet, and the containing function must still be open so the
   1210  * label-address object can be tied to that function's label namespace. This
   1211  * supports the normal direct-threaded lowering: declare a dispatch-table
   1212  * symbol, begin the function, create labels, emit the table as data while the
   1213  * function is open, then resume code emission. The resulting value is an opaque
   1214  * label-address pointer: it may be loaded, stored, compared for equality,
   1215  * selected from tables, and consumed by kit_cg_computed_goto in the label's
   1216  * defining function. It must not be called, dereferenced as data, or used by
   1217  * another function's computed goto. */
   1218 KIT_API void kit_cg_data_label_addr(KitCg*, KitCgLabel target, int64_t addend,
   1219                                     uint32_t width, uint32_t address_space);
   1220 KIT_API void kit_cg_data_pcrel(KitCg*, KitCgSym target, int64_t addend,
   1221                                uint32_t width);
   1222 KIT_API void kit_cg_data_symdiff(KitCg*, KitCgSym lhs, KitCgSym rhs,
   1223                                  int64_t addend, uint32_t width);
   1224 
   1225 /* ============================================================
   1226  * Static Inline Convenience Operations
   1227  * ============================================================ */
   1228 
   1229 static inline void kit_cg_push_bytes(KitCg* cg, const uint8_t* data, size_t len,
   1230                                      KitCgTypeId pointee_type) {
   1231   KitCgSym sym = kit_cg_const_data(cg, data, len, 0, pointee_type);
   1232   kit_cg_push_symbol_addr(cg, sym, 0);
   1233 }
   1234 
   1235 static inline void kit_cg_call_default(KitCg* cg, uint32_t nargs,
   1236                                        KitCgTypeId fn_type) {
   1237   KitCgCallAttrs attrs;
   1238   attrs.tail = KIT_CG_TAIL_DEFAULT;
   1239   attrs.flags = 0;
   1240   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1241   kit_cg_call(cg, nargs, fn_type, attrs);
   1242 }
   1243 
   1244 static inline void kit_cg_call_symbol_default(KitCg* cg, KitCgSym sym,
   1245                                               uint32_t nargs) {
   1246   KitCgCallAttrs attrs;
   1247   attrs.tail = KIT_CG_TAIL_DEFAULT;
   1248   attrs.flags = 0;
   1249   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1250   kit_cg_call_symbol(cg, sym, nargs, attrs);
   1251 }
   1252 
   1253 static inline void kit_cg_tail_call(KitCg* cg, uint32_t nargs,
   1254                                     KitCgTypeId fn_type) {
   1255   KitCgCallAttrs attrs;
   1256   attrs.tail = KIT_CG_TAIL_ALLOWED;
   1257   attrs.flags = 0;
   1258   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1259   kit_cg_call(cg, nargs, fn_type, attrs);
   1260 }
   1261 
   1262 static inline void kit_cg_tail_call_symbol(KitCg* cg, KitCgSym sym,
   1263                                            uint32_t nargs) {
   1264   KitCgCallAttrs attrs;
   1265   attrs.tail = KIT_CG_TAIL_ALLOWED;
   1266   attrs.flags = 0;
   1267   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1268   kit_cg_call_symbol(cg, sym, nargs, attrs);
   1269 }
   1270 
   1271 static inline void kit_cg_musttail_call(KitCg* cg, uint32_t nargs,
   1272                                         KitCgTypeId fn_type) {
   1273   KitCgCallAttrs attrs;
   1274   attrs.tail = KIT_CG_TAIL_MUST;
   1275   attrs.flags = 0;
   1276   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1277   kit_cg_call(cg, nargs, fn_type, attrs);
   1278 }
   1279 
   1280 static inline void kit_cg_musttail_call_symbol(KitCg* cg, KitCgSym sym,
   1281                                                uint32_t nargs) {
   1282   KitCgCallAttrs attrs;
   1283   attrs.tail = KIT_CG_TAIL_MUST;
   1284   attrs.flags = 0;
   1285   attrs.inline_policy = KIT_CG_INLINE_DEFAULT;
   1286   kit_cg_call_symbol(cg, sym, nargs, attrs);
   1287 }
   1288 
   1289 /* Read the scalar value of a local. Stack: [] -> [value]. */
   1290 static inline void kit_cg_local_read(KitCg* cg, KitCgLocal local,
   1291                                      KitCgMemAccess access) {
   1292   kit_cg_push_local(cg, local);
   1293   kit_cg_load(cg, access);
   1294 }
   1295 
   1296 /* Write the scalar value on TOS into a local. Stack: [value] -> []. */
   1297 static inline void kit_cg_local_write(KitCg* cg, KitCgLocal local,
   1298                                       KitCgMemAccess access) {
   1299   kit_cg_push_local(cg, local); /* [value, lv] */
   1300   kit_cg_swap(cg);              /* [lv, value] */
   1301   kit_cg_store(cg, access);
   1302 }
   1303 
   1304 /* Increment/decrement an lvalue in place. Stack: [lv] -> [result].
   1305  * post=1 pushes the old value; post=0 pushes the new value.
   1306  * op is KIT_CG_INT_ADD or KIT_CG_INT_SUB. ty is the promoted integer type
   1307  * of the lvalue. */
   1308 static inline void kit_cg_inc_dec(KitCg* cg, KitCgIntBinOp op, int post,
   1309                                   KitCgTypeId ty, KitCgMemAccess access) {
   1310   kit_cg_dup(cg);          /* [lv, lv] */
   1311   kit_cg_load(cg, access); /* [lv, old] */
   1312   if (post) {
   1313     kit_cg_dup(cg);              /* [lv, old, old] */
   1314     kit_cg_push_int(cg, 1, ty);  /* [lv, old, old, 1] */
   1315     kit_cg_int_binop(cg, op, 0); /* [lv, old, new] */
   1316     kit_cg_rot3(cg);             /* [old, new, lv] */
   1317     kit_cg_swap(cg);             /* [old, lv, new] */
   1318     kit_cg_store(cg, access);    /* [old] */
   1319   } else {
   1320     kit_cg_push_int(cg, 1, ty);  /* [lv, old, 1] */
   1321     kit_cg_int_binop(cg, op, 0); /* [lv, new] */
   1322     kit_cg_dup(cg);              /* [lv, new, new] */
   1323     kit_cg_rot3(cg);             /* [new, new, lv] */
   1324     kit_cg_swap(cg);             /* [new, lv, new] */
   1325     kit_cg_store(cg, access);    /* [new] */
   1326   }
   1327 }
   1328 
   1329 /* `if (cond) then [else else_body]` lowering via two nested forward blocks.
   1330  *
   1331  *   outer = block_begin             (break = "end of if")
   1332  *     inner = block_begin           (break = "else entry point")
   1333  *       break_false(inner)          ; pop cond, skip then-body if false
   1334  *       then-body
   1335  *     if_else: break(outer); end inner
   1336  *     [optional else-body]
   1337  *   if_end: end outer
   1338  *
   1339  * Frontends must call kit_cg_if_else exactly once after the then-body
   1340  * (even if there is no else clause — the call closes the inner block so
   1341  * if_end can close only the outer). Using structured scopes means backends
   1342  * that already lower BLOCK + break natively (every native arch and the Wasm
   1343  * target) handle `if`/`if-else` without a CFG-to-structured pass. */
   1344 typedef struct KitCgIf {
   1345   KitCgScope outer;
   1346   KitCgScope inner;
   1347 } KitCgIf;
   1348 
   1349 static inline KitCgIf kit_cg_if_begin(KitCg* cg) {
   1350   KitCgIf it;
   1351   it.outer = kit_cg_block_begin(cg, KIT_CG_TYPE_NONE);
   1352   it.inner = kit_cg_block_begin(cg, KIT_CG_TYPE_NONE);
   1353   kit_cg_break_false(cg, it.inner);
   1354   return it;
   1355 }
   1356 
   1357 static inline void kit_cg_if_else(KitCg* cg, KitCgIf it) {
   1358   kit_cg_break(cg, it.outer);
   1359   kit_cg_scope_end(cg, it.inner);
   1360 }
   1361 
   1362 static inline void kit_cg_if_end(KitCg* cg, KitCgIf it) {
   1363   kit_cg_scope_end(cg, it.outer);
   1364 }
   1365 
   1366 /* Extract bits [lo, lo+width) from TOS as an unsigned value.
   1367  * Stack: [value] -> [field]. ty is the integer type of the value.
   1368  * width < 64 masks with (1<<width)-1; width == 64 keeps all bits. */
   1369 static inline void kit_cg_bitget(KitCg* cg, KitCgTypeId ty, uint32_t lo,
   1370                                  uint32_t width) {
   1371   if (lo > 0) {
   1372     kit_cg_push_int(cg, lo, ty);
   1373     kit_cg_int_binop(cg, KIT_CG_INT_LSHR, 0);
   1374   }
   1375   if (width < 64) {
   1376     kit_cg_push_int(cg, (1ULL << width) - 1, ty);
   1377     kit_cg_int_binop(cg, KIT_CG_INT_AND, 0);
   1378   }
   1379 }
   1380 
   1381 /* Insert the low width bits of src into dst at bit position lo.
   1382  * Stack: [dst, src] -> [result]. ty is the integer type.
   1383  * result = (dst & ~field_mask) | ((src << lo) & field_mask)
   1384  * where field_mask = ((1<<width)-1) << lo. width < 64; for width == 64 use
   1385  * bitget + shift + or directly. */
   1386 static inline void kit_cg_bitset(KitCg* cg, KitCgTypeId ty, uint32_t lo,
   1387                                  uint32_t width) {
   1388   uint64_t field_mask = ((1ULL << width) - 1) << lo;
   1389   uint64_t clear_mask = ~field_mask;
   1390   kit_cg_swap(cg); /* [src, dst] */
   1391   kit_cg_dup(cg);  /* [src, dst, dst] */
   1392   kit_cg_push_int(cg, clear_mask, ty);
   1393   kit_cg_int_binop(cg, KIT_CG_INT_AND, 0); /* [src, dst, dst_cleared] */
   1394   kit_cg_rot3(cg);                         /* [dst, dst_cleared, src] */
   1395   if (lo > 0) {
   1396     kit_cg_push_int(cg, lo, ty);
   1397     kit_cg_int_binop(cg, KIT_CG_INT_SHL, 0); /* [dst, dst_cleared, src<<lo] */
   1398   }
   1399   kit_cg_push_int(cg, field_mask, ty);
   1400   kit_cg_int_binop(cg, KIT_CG_INT_AND, 0); /* [dst, dst_cleared, bits] */
   1401   kit_cg_rot3(cg);                         /* [dst_cleared, bits, dst] */
   1402   kit_cg_drop(cg);                         /* [dst_cleared, bits] */
   1403   kit_cg_int_binop(cg, KIT_CG_INT_OR, 0);  /* [result] */
   1404 }
   1405 
   1406 #endif