kit

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

cg_type_test.c (70466B)


      1 #include <kit/cg.h>
      2 #include <kit/compile.h>
      3 #include <kit/core.h>
      4 #include <kit/dwarf.h>
      5 #include <kit/frontend.h>
      6 #include <kit/object.h>
      7 #include <kit/source.h>
      8 #include <stdarg.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #include "lib/kit_unit.h"
     14 
     15 /* One shared test context replaces the per-file heap/diag/counter globals.
     16  * EXPECT is aliased to CU_EXPECT so the call sites below are unchanged; the
     17  * expected-panic helper uses g_u.suppress_fatal + g_u.last_diag. */
     18 static KitUnit g_u;
     19 #define EXPECT(cond, ...) CU_EXPECT(&g_u, cond, __VA_ARGS__)
     20 
     21 static KitObjBuilder* new_obj(KitCompiler* c) {
     22   KitObjBuilder* ob = NULL;
     23   if (kit_obj_builder_new(c, &ob) != KIT_OK) return NULL;
     24   return ob;
     25 }
     26 
     27 static int open_emitted_obj(KitCompiler* c, KitObjBuilder* ob,
     28                             KitWriter** writer_out, KitObjFile** file_out) {
     29   KitWriter* w = NULL;
     30   KitObjFile* f = NULL;
     31   KitSlice bytes;
     32   size_t len = 0;
     33   const KitContext* ctx;
     34 
     35   if (!writer_out || !file_out) return 0;
     36   *writer_out = NULL;
     37   *file_out = NULL;
     38   if (kit_writer_mem(&g_u.heap, &w) != KIT_OK || !w) return 0;
     39   if (kit_obj_builder_emit(ob, w) != KIT_OK) {
     40     kit_writer_close(w);
     41     return 0;
     42   }
     43   bytes.data = kit_writer_mem_bytes(w, &len);
     44   bytes.len = len;
     45   ctx = kit_compiler_context(c);
     46   if (kit_obj_open(ctx, KIT_SLICE_LIT("<cg-api-test>"), &bytes, &f) != KIT_OK) {
     47     kit_writer_close(w);
     48     return 0;
     49   }
     50   *writer_out = w;
     51   *file_out = f;
     52   return 1;
     53 }
     54 
     55 static void finish_cg(KitCg* cg, const char* tag) {
     56   EXPECT(kit_cg_finish(cg, NULL) == KIT_OK, "%s cg finish failed", tag);
     57   EXPECT(kit_cg_detach(cg) == KIT_OK, "%s cg detach failed", tag);
     58 }
     59 
     60 typedef struct PanicRunCtx {
     61   void (*fn)(void*);
     62   void* arg;
     63 } PanicRunCtx;
     64 
     65 static KitStatus run_expected_panic(KitCompiler* c, void* arg) {
     66   PanicRunCtx* ctx = (PanicRunCtx*)arg;
     67   (void)c;
     68   ctx->fn(ctx->arg);
     69   return KIT_OK;
     70 }
     71 
     72 static int expect_panic_contains(KitCompiler* c, void (*fn)(void*), void* arg,
     73                                  const char* expected) {
     74   PanicRunCtx ctx;
     75   KitStatus st;
     76   ctx.fn = fn;
     77   ctx.arg = arg;
     78   g_u.last_diag[0] = '\0';
     79   g_u.suppress_fatal++;
     80   st = kit_frontend_run(c, run_expected_panic, &ctx);
     81   g_u.suppress_fatal--;
     82   return st == KIT_ERR && strstr(g_u.last_diag, expected) != NULL;
     83 }
     84 
     85 static void exercise_cg_handles(KitCompiler* c, KitCgTypeId i32_ty,
     86                                 int opt_level) {
     87   char name_buf[32];
     88   KitCodeOptions opts;
     89   KitObjBuilder* ob;
     90   KitCg* cg;
     91   KitCgFuncParam param_desc;
     92   KitCgFuncSig sig;
     93   KitCgDecl decl;
     94   KitCgSym sym;
     95   KitCgLocalAttrs attrs;
     96   KitCgLocal local;
     97   KitCgLocal param;
     98   KitCgMemAccess mem;
     99 
    100   memset(&opts, 0, sizeof(opts));
    101   opts.opt_level = opt_level;
    102   ob = new_obj(c);
    103   EXPECT(ob != NULL, "obj builder allocation failed");
    104   if (!ob) return;
    105   cg = NULL;
    106   (void)kit_cg_new(c, &cg);
    107   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    108   EXPECT(cg != NULL, "cg allocation failed");
    109   if (!cg) {
    110     kit_obj_builder_free(ob);
    111     return;
    112   }
    113 
    114   memset(&param_desc, 0, sizeof(param_desc));
    115   param_desc.type = i32_ty;
    116   memset(&sig, 0, sizeof(sig));
    117   KitCgFuncResult sig_result;
    118   memset(&sig_result, 0, sizeof sig_result);
    119   sig_result.type = i32_ty;
    120   sig.result = sig_result;
    121   sig.params = &param_desc;
    122   sig.nparams = 1;
    123   sig.call_conv = KIT_CG_CC_TARGET_C;
    124 
    125   snprintf(name_buf, sizeof(name_buf), "cg_handles_o%d", opt_level);
    126   memset(&decl, 0, sizeof(decl));
    127   decl.kind = KIT_CG_DECL_FUNC;
    128   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name_buf));
    129   decl.display_name = decl.linkage_name;
    130   decl.type = kit_cg_type_func(c, sig);
    131   decl.sym.bind = KIT_SB_GLOBAL;
    132   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    133   sym = kit_cg_decl(cg, decl);
    134   EXPECT(sym != KIT_CG_SYM_NONE, "function decl failed");
    135 
    136   kit_cg_func_begin(cg, sym);
    137   memset(&attrs, 0, sizeof(attrs));
    138   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("p"));
    139   param = kit_cg_param(cg, 0, i32_ty, attrs);
    140   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
    141   local = kit_cg_local(cg, i32_ty, attrs);
    142   EXPECT(local != KIT_CG_LOCAL_NONE, "local handle is none");
    143   EXPECT(param != KIT_CG_LOCAL_NONE, "param handle is none");
    144   EXPECT((uint32_t)param == 1u, "first local id should be param");
    145   EXPECT((uint32_t)local == 2u, "local id should follow param");
    146   EXPECT((uint32_t)local != (uint32_t)param, "local and param handles collide");
    147 
    148   memset(&mem, 0, sizeof(mem));
    149   mem.type = i32_ty;
    150   mem.align = kit_cg_type_align(c, i32_ty);
    151 
    152   kit_cg_push_local(cg, local);
    153   kit_cg_push_local_addr(cg, param);
    154   kit_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
    155   kit_cg_load(cg, mem);
    156   kit_cg_store(cg, mem);
    157 
    158   kit_cg_push_local_addr(cg, local);
    159   kit_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
    160   kit_cg_load(cg, mem);
    161   kit_cg_ret(cg);
    162   kit_cg_func_end(cg);
    163 
    164   kit_cg_free(cg);
    165   kit_obj_builder_free(ob);
    166 }
    167 
    168 static void exercise_cg_scalar_local(KitCompiler* c, KitCgTypeId i32_ty,
    169                                      int opt_level) {
    170   char name_buf[40];
    171   KitCodeOptions opts;
    172   KitObjBuilder* ob;
    173   KitCg* cg;
    174   KitCgFuncSig sig;
    175   KitCgDecl decl;
    176   KitCgSym sym;
    177   KitCgLocalAttrs attrs;
    178   KitCgLocal local;
    179   KitCgMemAccess mem;
    180 
    181   memset(&opts, 0, sizeof opts);
    182   opts.opt_level = opt_level;
    183   ob = new_obj(c);
    184   EXPECT(ob != NULL, "obj builder allocation failed");
    185   if (!ob) return;
    186   cg = NULL;
    187   (void)kit_cg_new(c, &cg);
    188   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    189   EXPECT(cg != NULL, "cg allocation failed");
    190   if (!cg) {
    191     kit_obj_builder_free(ob);
    192     return;
    193   }
    194 
    195   memset(&sig, 0, sizeof sig);
    196   KitCgFuncResult sig_result;
    197   memset(&sig_result, 0, sizeof sig_result);
    198   sig_result.type = i32_ty;
    199   sig.result = sig_result;
    200   sig.call_conv = KIT_CG_CC_TARGET_C;
    201 
    202   snprintf(name_buf, sizeof name_buf, "cg_scalar_local_o%d", opt_level);
    203   memset(&decl, 0, sizeof decl);
    204   decl.kind = KIT_CG_DECL_FUNC;
    205   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name_buf));
    206   decl.display_name = decl.linkage_name;
    207   decl.type = kit_cg_type_func(c, sig);
    208   decl.sym.bind = KIT_SB_GLOBAL;
    209   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    210   sym = kit_cg_decl(cg, decl);
    211   EXPECT(sym != KIT_CG_SYM_NONE, "scalar local decl failed");
    212 
    213   kit_cg_func_begin(cg, sym);
    214   memset(&attrs, 0, sizeof attrs);
    215   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
    216   local = kit_cg_local(cg, i32_ty, attrs);
    217   EXPECT(local != KIT_CG_LOCAL_NONE, "scalar local handle is none");
    218 
    219   memset(&mem, 0, sizeof mem);
    220   mem.type = i32_ty;
    221   mem.align = kit_cg_type_align(c, i32_ty);
    222 
    223   kit_cg_push_local(cg, local);
    224   kit_cg_push_int(cg, 40, i32_ty);
    225   kit_cg_store(cg, mem);
    226   kit_cg_push_local(cg, local);
    227   kit_cg_load(cg, mem);
    228   kit_cg_push_int(cg, 2, i32_ty);
    229   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    230   kit_cg_ret(cg);
    231   kit_cg_func_end(cg);
    232 
    233   kit_cg_free(cg);
    234   kit_obj_builder_free(ob);
    235 }
    236 
    237 static void exercise_cg_late_local_addr(KitCompiler* c, KitCgTypeId i32_ty,
    238                                         int opt_level) {
    239   char name_buf[40];
    240   KitCodeOptions opts;
    241   KitObjBuilder* ob;
    242   KitCg* cg;
    243   KitCgFuncSig sig;
    244   KitCgDecl decl;
    245   KitCgSym sym;
    246   KitCgLocalAttrs attrs;
    247   KitCgLocal local;
    248   KitCgMemAccess mem;
    249 
    250   memset(&opts, 0, sizeof opts);
    251   opts.opt_level = opt_level;
    252   ob = new_obj(c);
    253   EXPECT(ob != NULL, "obj builder allocation failed");
    254   if (!ob) return;
    255   cg = NULL;
    256   (void)kit_cg_new(c, &cg);
    257   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    258   EXPECT(cg != NULL, "cg allocation failed");
    259   if (!cg) {
    260     kit_obj_builder_free(ob);
    261     return;
    262   }
    263 
    264   memset(&sig, 0, sizeof sig);
    265   KitCgFuncResult sig_result;
    266   memset(&sig_result, 0, sizeof sig_result);
    267   sig_result.type = i32_ty;
    268   sig.result = sig_result;
    269   sig.call_conv = KIT_CG_CC_TARGET_C;
    270 
    271   snprintf(name_buf, sizeof name_buf, "cg_late_local_addr_o%d", opt_level);
    272   memset(&decl, 0, sizeof decl);
    273   decl.kind = KIT_CG_DECL_FUNC;
    274   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name_buf));
    275   decl.display_name = decl.linkage_name;
    276   decl.type = kit_cg_type_func(c, sig);
    277   decl.sym.bind = KIT_SB_GLOBAL;
    278   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    279   sym = kit_cg_decl(cg, decl);
    280   EXPECT(sym != KIT_CG_SYM_NONE, "late local addr decl failed");
    281 
    282   kit_cg_func_begin(cg, sym);
    283   memset(&attrs, 0, sizeof attrs);
    284   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
    285   local = kit_cg_local(cg, i32_ty, attrs);
    286   EXPECT(local != KIT_CG_LOCAL_NONE, "late addr local handle is none");
    287 
    288   memset(&mem, 0, sizeof mem);
    289   mem.type = i32_ty;
    290   mem.align = kit_cg_type_align(c, i32_ty);
    291 
    292   kit_cg_push_local(cg, local);
    293   kit_cg_push_int(cg, 41, i32_ty);
    294   kit_cg_store(cg, mem);
    295   kit_cg_push_local_addr(cg, local);
    296   kit_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
    297   kit_cg_load(cg, mem);
    298   kit_cg_push_int(cg, 1, i32_ty);
    299   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    300   kit_cg_ret(cg);
    301   kit_cg_func_end(cg);
    302 
    303   kit_cg_free(cg);
    304   kit_obj_builder_free(ob);
    305 }
    306 
    307 static uint32_t text_size(KitCompiler* c, KitObjBuilder* ob) {
    308   uint32_t total = 0;
    309   KitWriter* w = NULL;
    310   KitObjFile* f = NULL;
    311   uint32_t n;
    312   if (!open_emitted_obj(c, ob, &w, &f)) {
    313     EXPECT(0, "failed to inspect emitted object");
    314     return 0;
    315   }
    316   n = kit_obj_nsections(f);
    317   for (uint32_t i = 0; i < n; ++i) {
    318     KitObjSecInfo sec;
    319     if (kit_obj_section(f, i, &sec) != KIT_OK) continue;
    320     if (sec.kind == KIT_SEC_TEXT) total += (uint32_t)sec.size;
    321   }
    322   kit_obj_free(f);
    323   kit_writer_close(w);
    324   return total;
    325 }
    326 
    327 static void exercise_cg_data_entsize(KitCompiler* c, KitCgTypeId i8_ty) {
    328   static const uint8_t bytes[] = {'t', 'o', 'y', '\0'};
    329   KitCodeOptions opts;
    330   KitObjBuilder* ob;
    331   KitCg* cg;
    332   KitCgDecl decl;
    333   KitCgSym sym;
    334   KitCgDataDefAttrs data_attrs;
    335   KitCgTypeId array_ty;
    336   int found = 0;
    337 
    338   memset(&opts, 0, sizeof opts);
    339   ob = new_obj(c);
    340   EXPECT(ob != NULL, "entsize obj builder allocation failed");
    341   if (!ob) return;
    342   cg = NULL;
    343   (void)kit_cg_new(c, &cg);
    344   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    345   EXPECT(cg != NULL, "entsize cg allocation failed");
    346   if (!cg) {
    347     kit_obj_builder_free(ob);
    348     return;
    349   }
    350 
    351   array_ty = kit_cg_type_array(c, i8_ty, sizeof bytes);
    352   EXPECT(array_ty != KIT_CG_TYPE_NONE, "entsize array type failed");
    353 
    354   memset(&decl, 0, sizeof decl);
    355   decl.kind = KIT_CG_DECL_OBJECT;
    356   decl.linkage_name = kit_sym_intern(c, KIT_SLICE_LIT("cg_entsize_string"));
    357   decl.display_name = decl.linkage_name;
    358   decl.type = array_ty;
    359   decl.sym.bind = KIT_SB_GLOBAL;
    360   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    361   decl.as.object.flags = KIT_CG_OBJ_READONLY;
    362   decl.as.object.align = 1;
    363   sym = kit_cg_decl(cg, decl);
    364   EXPECT(sym != KIT_CG_SYM_NONE, "entsize object decl failed");
    365 
    366   memset(&data_attrs, 0, sizeof data_attrs);
    367   data_attrs.section = kit_sym_intern(c, KIT_SLICE_LIT(".rodata.kit.merge"));
    368   data_attrs.align = 1;
    369   data_attrs.entsize = 1;
    370   data_attrs.flags =
    371       KIT_CG_DATADEF_READONLY | KIT_CG_DATADEF_MERGE | KIT_CG_DATADEF_STRINGS;
    372   kit_cg_data_begin(cg, sym, data_attrs);
    373   kit_cg_data_bytes(cg, bytes, sizeof bytes);
    374   kit_cg_data_end(cg);
    375   finish_cg(cg, "entsize");
    376   kit_cg_free(cg);
    377 
    378   {
    379     KitWriter* w = NULL;
    380     KitObjFile* f = NULL;
    381     uint32_t n;
    382     if (!open_emitted_obj(c, ob, &w, &f)) {
    383       EXPECT(0, "failed to inspect entsize object");
    384       kit_obj_builder_free(ob);
    385       return;
    386     }
    387     n = kit_obj_nsections(f);
    388     for (uint32_t i = 0; i < n; ++i) {
    389       KitObjSecInfo sec;
    390       if (kit_obj_section(f, i, &sec) != KIT_OK) continue;
    391       if ((sec.flags & (KIT_SF_MERGE | KIT_SF_STRINGS)) ==
    392           (KIT_SF_MERGE | KIT_SF_STRINGS)) {
    393         found = 1;
    394         EXPECT(sec.entsize == 1,
    395                "merge string section entsize should be 1, got %u", sec.entsize);
    396       }
    397     }
    398     kit_obj_free(f);
    399     kit_writer_close(w);
    400   }
    401   EXPECT(found, "expected merge string data section");
    402 
    403   kit_obj_builder_free(ob);
    404 }
    405 
    406 static void exercise_cg_debug_global_object(KitCompiler* c,
    407                                             KitCgTypeId i32_ty) {
    408   KitCodeOptions opts;
    409   KitObjBuilder* ob;
    410   KitCg* cg;
    411   KitCgDecl decl;
    412   KitCgSym sym;
    413   KitCgDataDefAttrs data_attrs;
    414   KitSrcLoc loc;
    415   uint32_t file_id = 0;
    416 
    417   memset(&opts, 0, sizeof opts);
    418   opts.debug_info = true;
    419   ob = new_obj(c);
    420   EXPECT(ob != NULL, "debug global obj builder allocation failed");
    421   if (!ob) return;
    422   cg = NULL;
    423   EXPECT(kit_cg_new(c, &cg) == KIT_OK && cg != NULL,
    424          "debug global cg allocation failed");
    425   if (!cg) {
    426     kit_obj_builder_free(ob);
    427     return;
    428   }
    429   EXPECT(kit_cg_begin(cg, ob, &opts) == KIT_OK, "debug global cg begin failed");
    430 
    431   EXPECT(kit_source_add_memory(c, KIT_SLICE_LIT("cg_debug_global.c"),
    432                                &file_id) == KIT_OK,
    433          "debug global source file add failed");
    434   loc.file_id = file_id;
    435   loc.line = 7;
    436   loc.col = 3;
    437   kit_cg_set_loc(cg, loc);
    438 
    439   memset(&decl, 0, sizeof decl);
    440   decl.kind = KIT_CG_DECL_OBJECT;
    441   decl.linkage_name = kit_sym_intern(c, KIT_SLICE_LIT("cg_dbg_global_link"));
    442   decl.display_name = kit_sym_intern(c, KIT_SLICE_LIT("cg_dbg_global"));
    443   decl.type = i32_ty;
    444   decl.sym.bind = KIT_SB_GLOBAL;
    445   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    446   sym = kit_cg_decl(cg, decl);
    447   EXPECT(sym != KIT_CG_SYM_NONE, "debug global object decl failed");
    448 
    449   memset(&data_attrs, 0, sizeof data_attrs);
    450   data_attrs.align = kit_cg_type_align(c, i32_ty);
    451   kit_cg_data_begin(cg, sym, data_attrs);
    452   kit_cg_data_int(cg, 42, i32_ty);
    453   kit_cg_data_end(cg);
    454   finish_cg(cg, "debug global");
    455   kit_cg_free(cg);
    456 
    457   {
    458     KitWriter* w = NULL;
    459     KitObjFile* f = NULL;
    460     KitDebugInfo* di = NULL;
    461     KitDwarfVarLoc vloc;
    462     KitDwarfVarIter* vit = NULL;
    463     KitDwarfVar var;
    464     int iter_found = 0;
    465 
    466     if (!open_emitted_obj(c, ob, &w, &f)) {
    467       EXPECT(0, "failed to inspect debug global object");
    468       kit_obj_builder_free(ob);
    469       return;
    470     }
    471     EXPECT(
    472         kit_dwarf_open(kit_compiler_context(c), f, &di) == KIT_OK && di != NULL,
    473         "debug global dwarf open failed");
    474     if (di) {
    475       EXPECT(kit_dwarf_var_at(di, 0, KIT_SLICE_LIT("cg_dbg_global"), &vloc) ==
    476                  KIT_OK,
    477              "debug global variable not found by display name");
    478       EXPECT(vloc.kind == KIT_DLOC_GLOBAL,
    479              "debug global location kind %d, expected global", (int)vloc.kind);
    480       EXPECT(vloc.byte_size == 4, "debug global byte size %u, expected 4",
    481              vloc.byte_size);
    482       EXPECT(vloc.type != NULL, "debug global type missing");
    483 
    484       EXPECT(kit_dwarf_vars_at_new(di, 0, KIT_DVRM_GLOBAL, &vit) == KIT_OK &&
    485                  vit != NULL,
    486              "debug global iterator allocation failed");
    487       if (vit) {
    488         while (kit_dwarf_vars_at_next(vit, &var) == KIT_ITER_ITEM) {
    489           if (kit_slice_eq_cstr(var.name, "cg_dbg_global") &&
    490               var.role == KIT_DVR_GLOBAL) {
    491             iter_found = 1;
    492             EXPECT(var.loc.kind == KIT_DLOC_GLOBAL,
    493                    "debug global iterator location kind %d", (int)var.loc.kind);
    494           }
    495         }
    496         kit_dwarf_vars_at_free(vit);
    497       }
    498       EXPECT(iter_found, "debug global iterator did not report global");
    499       kit_dwarf_free(di);
    500     }
    501     kit_obj_free(f);
    502     kit_writer_close(w);
    503   }
    504 
    505   kit_obj_builder_free(ob);
    506 }
    507 
    508 static KitCgSym begin_i32_func(KitCompiler* c, KitCg* cg, KitCgTypeId i32_ty,
    509                                const char* name) {
    510   KitCgFuncSig sig;
    511   KitCgDecl decl;
    512   memset(&sig, 0, sizeof sig);
    513   KitCgFuncResult sig_result;
    514   memset(&sig_result, 0, sizeof sig_result);
    515   sig_result.type = i32_ty;
    516   sig.result = sig_result;
    517   sig.call_conv = KIT_CG_CC_TARGET_C;
    518 
    519   memset(&decl, 0, sizeof decl);
    520   decl.kind = KIT_CG_DECL_FUNC;
    521   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    522   decl.display_name = decl.linkage_name;
    523   decl.type = kit_cg_type_func(c, sig);
    524   decl.sym.bind = KIT_SB_GLOBAL;
    525   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    526   return kit_cg_decl(cg, decl);
    527 }
    528 
    529 static void exercise_cg_literal_folds(KitCompiler* c, KitCgTypeId i32_ty) {
    530   static const char* names[] = {
    531       "cg_fold_add_o1",
    532       "cg_fold_shift_or_o1",
    533       "cg_fold_cmp_o1",
    534       "cg_fold_unop_o1",
    535   };
    536   KitCodeOptions opts;
    537   KitObjBuilder* ob;
    538   KitCg* cg;
    539 
    540   memset(&opts, 0, sizeof opts);
    541   opts.opt_level = 1;
    542   ob = new_obj(c);
    543   EXPECT(ob != NULL, "literal fold obj builder allocation failed");
    544   if (!ob) return;
    545   cg = NULL;
    546   (void)kit_cg_new(c, &cg);
    547   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    548   EXPECT(cg != NULL, "literal fold cg allocation failed");
    549   if (!cg) {
    550     kit_obj_builder_free(ob);
    551     return;
    552   }
    553 
    554   for (uint32_t i = 0; i < 4; ++i) {
    555     KitCgSym sym = begin_i32_func(c, cg, i32_ty, names[i]);
    556     EXPECT(sym != KIT_CG_SYM_NONE, "literal fold decl failed");
    557     kit_cg_func_begin(cg, sym);
    558     switch (i) {
    559       case 0:
    560         kit_cg_push_int(cg, 40, i32_ty);
    561         kit_cg_push_int(cg, 2, i32_ty);
    562         kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    563         break;
    564       case 1:
    565         kit_cg_push_int(cg, 5, i32_ty);
    566         kit_cg_push_int(cg, 3, i32_ty);
    567         kit_cg_int_binop(cg, KIT_CG_INT_SHL, 0);
    568         kit_cg_push_int(cg, 2, i32_ty);
    569         kit_cg_int_binop(cg, KIT_CG_INT_OR, 0);
    570         break;
    571       case 2:
    572         kit_cg_push_int(cg, 40, i32_ty);
    573         kit_cg_push_int(cg, 2, i32_ty);
    574         kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    575         kit_cg_push_int(cg, 42, i32_ty);
    576         kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
    577         break;
    578       case 3:
    579         kit_cg_push_int(cg, 41, i32_ty);
    580         kit_cg_int_unop(cg, KIT_CG_INT_BNOT, 0);
    581         kit_cg_int_unop(cg, KIT_CG_INT_BNOT, 0);
    582         kit_cg_push_int(cg, 1, i32_ty);
    583         kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    584         break;
    585     }
    586     kit_cg_ret(cg);
    587     kit_cg_func_end(cg);
    588   }
    589 
    590   finish_cg(cg, "literal fold");
    591   kit_cg_free(cg);
    592   EXPECT(text_size(c, ob) <= 128,
    593          "literal folds should avoid arithmetic materialization, text size=%u",
    594          text_size(c, ob));
    595   kit_obj_builder_free(ob);
    596 }
    597 
    598 static uint32_t cg_emit_delayed_chain(KitCompiler* c, KitCgTypeId i32_ty,
    599                                       const char* name) {
    600   KitCodeOptions opts;
    601   KitObjBuilder* ob;
    602   KitCg* cg;
    603   KitCgFuncParam param_desc;
    604   KitCgFuncSig sig;
    605   KitCgDecl decl;
    606   KitCgSym sym;
    607   KitCgLocalAttrs attrs;
    608   KitCgLocal param;
    609   KitCgMemAccess mem;
    610   uint32_t size;
    611 
    612   memset(&opts, 0, sizeof opts);
    613   opts.opt_level = 1;
    614   ob = new_obj(c);
    615   EXPECT(ob != NULL, "delayed chain obj builder allocation failed");
    616   if (!ob) return 0;
    617   cg = NULL;
    618   (void)kit_cg_new(c, &cg);
    619   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    620   EXPECT(cg != NULL, "delayed chain cg allocation failed");
    621   if (!cg) {
    622     kit_obj_builder_free(ob);
    623     return 0;
    624   }
    625 
    626   memset(&param_desc, 0, sizeof param_desc);
    627   param_desc.type = i32_ty;
    628   memset(&sig, 0, sizeof sig);
    629   KitCgFuncResult sig_result;
    630   memset(&sig_result, 0, sizeof sig_result);
    631   sig_result.type = i32_ty;
    632   sig.result = sig_result;
    633   sig.params = &param_desc;
    634   sig.nparams = 1;
    635   sig.call_conv = KIT_CG_CC_TARGET_C;
    636 
    637   memset(&decl, 0, sizeof decl);
    638   decl.kind = KIT_CG_DECL_FUNC;
    639   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    640   decl.display_name = decl.linkage_name;
    641   decl.type = kit_cg_type_func(c, sig);
    642   decl.sym.bind = KIT_SB_GLOBAL;
    643   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    644   sym = kit_cg_decl(cg, decl);
    645   EXPECT(sym != KIT_CG_SYM_NONE, "delayed chain decl failed");
    646 
    647   kit_cg_func_begin(cg, sym);
    648   memset(&attrs, 0, sizeof attrs);
    649   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("p"));
    650   param = kit_cg_param(cg, 0, i32_ty, attrs);
    651   EXPECT(param != KIT_CG_LOCAL_NONE, "delayed chain param failed");
    652   memset(&mem, 0, sizeof mem);
    653   mem.type = i32_ty;
    654   mem.align = kit_cg_type_align(c, i32_ty);
    655   kit_cg_push_local(cg, param);
    656   kit_cg_load(cg, mem);
    657   kit_cg_push_int(cg, 40, i32_ty);
    658   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    659   kit_cg_push_int(cg, 2, i32_ty);
    660   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    661   kit_cg_ret(cg);
    662   kit_cg_func_end(cg);
    663 
    664   finish_cg(cg, "delayed chain");
    665   kit_cg_free(cg);
    666   size = text_size(c, ob);
    667   kit_obj_builder_free(ob);
    668   return size;
    669 }
    670 
    671 static uint32_t cg_emit_unary_chain(KitCompiler* c, KitCgTypeId i32_ty,
    672                                     const char* name) {
    673   KitCodeOptions opts;
    674   KitObjBuilder* ob;
    675   KitCg* cg;
    676   KitCgFuncParam param_desc;
    677   KitCgFuncSig sig;
    678   KitCgDecl decl;
    679   KitCgSym sym;
    680   KitCgLocalAttrs attrs;
    681   KitCgLocal param;
    682   KitCgMemAccess mem;
    683   uint32_t size;
    684 
    685   memset(&opts, 0, sizeof opts);
    686   opts.opt_level = 1;
    687   ob = new_obj(c);
    688   EXPECT(ob != NULL, "unary chain obj builder allocation failed");
    689   if (!ob) return 0;
    690   cg = NULL;
    691   (void)kit_cg_new(c, &cg);
    692   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    693   EXPECT(cg != NULL, "unary chain cg allocation failed");
    694   if (!cg) {
    695     kit_obj_builder_free(ob);
    696     return 0;
    697   }
    698 
    699   memset(&param_desc, 0, sizeof param_desc);
    700   param_desc.type = i32_ty;
    701   memset(&sig, 0, sizeof sig);
    702   KitCgFuncResult sig_result;
    703   memset(&sig_result, 0, sizeof sig_result);
    704   sig_result.type = i32_ty;
    705   sig.result = sig_result;
    706   sig.params = &param_desc;
    707   sig.nparams = 1;
    708   sig.call_conv = KIT_CG_CC_TARGET_C;
    709 
    710   memset(&decl, 0, sizeof decl);
    711   decl.kind = KIT_CG_DECL_FUNC;
    712   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    713   decl.display_name = decl.linkage_name;
    714   decl.type = kit_cg_type_func(c, sig);
    715   decl.sym.bind = KIT_SB_GLOBAL;
    716   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    717   sym = kit_cg_decl(cg, decl);
    718   EXPECT(sym != KIT_CG_SYM_NONE, "unary chain decl failed");
    719 
    720   kit_cg_func_begin(cg, sym);
    721   memset(&attrs, 0, sizeof attrs);
    722   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("p"));
    723   param = kit_cg_param(cg, 0, i32_ty, attrs);
    724   EXPECT(param != KIT_CG_LOCAL_NONE, "unary chain param failed");
    725   memset(&mem, 0, sizeof mem);
    726   mem.type = i32_ty;
    727   mem.align = kit_cg_type_align(c, i32_ty);
    728   kit_cg_push_local(cg, param);
    729   kit_cg_load(cg, mem);
    730   kit_cg_int_unop(cg, KIT_CG_INT_BNOT, 0);
    731   kit_cg_int_unop(cg, KIT_CG_INT_BNOT, 0);
    732   kit_cg_ret(cg);
    733   kit_cg_func_end(cg);
    734 
    735   finish_cg(cg, "unary chain");
    736   kit_cg_free(cg);
    737   size = text_size(c, ob);
    738   kit_obj_builder_free(ob);
    739   return size;
    740 }
    741 
    742 static uint32_t cg_emit_local_shadow(KitCompiler* c, KitCgTypeId i32_ty,
    743                                      const char* name) {
    744   KitCodeOptions opts;
    745   KitObjBuilder* ob;
    746   KitCg* cg;
    747   KitCgFuncSig sig;
    748   KitCgDecl decl;
    749   KitCgSym sym;
    750   KitCgLocalAttrs attrs;
    751   KitCgLocal local;
    752   KitCgMemAccess mem;
    753   uint32_t size;
    754 
    755   memset(&opts, 0, sizeof opts);
    756   opts.opt_level = 1;
    757   ob = new_obj(c);
    758   EXPECT(ob != NULL, "local shadow obj builder allocation failed");
    759   if (!ob) return 0;
    760   cg = NULL;
    761   (void)kit_cg_new(c, &cg);
    762   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    763   EXPECT(cg != NULL, "local shadow cg allocation failed");
    764   if (!cg) {
    765     kit_obj_builder_free(ob);
    766     return 0;
    767   }
    768 
    769   memset(&sig, 0, sizeof sig);
    770   KitCgFuncResult sig_result;
    771   memset(&sig_result, 0, sizeof sig_result);
    772   sig_result.type = i32_ty;
    773   sig.result = sig_result;
    774   sig.call_conv = KIT_CG_CC_TARGET_C;
    775 
    776   memset(&decl, 0, sizeof decl);
    777   decl.kind = KIT_CG_DECL_FUNC;
    778   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    779   decl.display_name = decl.linkage_name;
    780   decl.type = kit_cg_type_func(c, sig);
    781   decl.sym.bind = KIT_SB_GLOBAL;
    782   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    783   sym = kit_cg_decl(cg, decl);
    784   EXPECT(sym != KIT_CG_SYM_NONE, "local shadow decl failed");
    785 
    786   kit_cg_func_begin(cg, sym);
    787   memset(&attrs, 0, sizeof attrs);
    788   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
    789   local = kit_cg_local(cg, i32_ty, attrs);
    790   EXPECT(local != KIT_CG_LOCAL_NONE, "local shadow local failed");
    791   memset(&mem, 0, sizeof mem);
    792   mem.type = i32_ty;
    793   mem.align = kit_cg_type_align(c, i32_ty);
    794   kit_cg_push_local(cg, local);
    795   kit_cg_push_int(cg, 40, i32_ty);
    796   kit_cg_store(cg, mem);
    797   kit_cg_push_local(cg, local);
    798   kit_cg_load(cg, mem);
    799   kit_cg_push_int(cg, 2, i32_ty);
    800   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    801   kit_cg_ret(cg);
    802   kit_cg_func_end(cg);
    803 
    804   finish_cg(cg, "local shadow");
    805   kit_cg_free(cg);
    806   size = text_size(c, ob);
    807   kit_obj_builder_free(ob);
    808   return size;
    809 }
    810 
    811 static uint32_t cg_emit_delayed_cmp(KitCompiler* c, KitCgTypeId i32_ty,
    812                                     const char* name) {
    813   KitCodeOptions opts;
    814   KitObjBuilder* ob;
    815   KitCg* cg;
    816   KitCgFuncParam param_desc;
    817   KitCgFuncSig sig;
    818   KitCgDecl decl;
    819   KitCgSym sym;
    820   KitCgLocalAttrs attrs;
    821   KitCgLocal param;
    822   KitCgMemAccess mem;
    823   uint32_t size;
    824 
    825   memset(&opts, 0, sizeof opts);
    826   opts.opt_level = 1;
    827   ob = new_obj(c);
    828   EXPECT(ob != NULL, "delayed cmp obj builder allocation failed");
    829   if (!ob) return 0;
    830   cg = NULL;
    831   (void)kit_cg_new(c, &cg);
    832   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    833   EXPECT(cg != NULL, "delayed cmp cg allocation failed");
    834   if (!cg) {
    835     kit_obj_builder_free(ob);
    836     return 0;
    837   }
    838 
    839   memset(&param_desc, 0, sizeof param_desc);
    840   param_desc.type = i32_ty;
    841   memset(&sig, 0, sizeof sig);
    842   KitCgFuncResult sig_result;
    843   memset(&sig_result, 0, sizeof sig_result);
    844   sig_result.type = i32_ty;
    845   sig.result = sig_result;
    846   sig.params = &param_desc;
    847   sig.nparams = 1;
    848   sig.call_conv = KIT_CG_CC_TARGET_C;
    849 
    850   memset(&decl, 0, sizeof decl);
    851   decl.kind = KIT_CG_DECL_FUNC;
    852   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    853   decl.display_name = decl.linkage_name;
    854   decl.type = kit_cg_type_func(c, sig);
    855   decl.sym.bind = KIT_SB_GLOBAL;
    856   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    857   sym = kit_cg_decl(cg, decl);
    858   EXPECT(sym != KIT_CG_SYM_NONE, "delayed cmp decl failed");
    859 
    860   kit_cg_func_begin(cg, sym);
    861   memset(&attrs, 0, sizeof attrs);
    862   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("p"));
    863   param = kit_cg_param(cg, 0, i32_ty, attrs);
    864   EXPECT(param != KIT_CG_LOCAL_NONE, "delayed cmp param failed");
    865   memset(&mem, 0, sizeof mem);
    866   mem.type = i32_ty;
    867   mem.align = kit_cg_type_align(c, i32_ty);
    868   kit_cg_push_local(cg, param);
    869   kit_cg_load(cg, mem);
    870   kit_cg_push_int(cg, 40, i32_ty);
    871   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    872   kit_cg_push_int(cg, 2, i32_ty);
    873   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    874   kit_cg_push_int(cg, 42, i32_ty);
    875   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
    876   kit_cg_ret(cg);
    877   kit_cg_func_end(cg);
    878 
    879   finish_cg(cg, "delayed cmp");
    880   kit_cg_free(cg);
    881   size = text_size(c, ob);
    882   kit_obj_builder_free(ob);
    883   return size;
    884 }
    885 
    886 static uint32_t cg_emit_delayed_store(KitCompiler* c, KitCgTypeId i32_ty,
    887                                       const char* name) {
    888   KitCodeOptions opts;
    889   KitObjBuilder* ob;
    890   KitCg* cg;
    891   KitCgFuncParam param_desc;
    892   KitCgFuncSig sig;
    893   KitCgDecl decl;
    894   KitCgSym sym;
    895   KitCgLocalAttrs attrs;
    896   KitCgLocal param;
    897   KitCgLocal local;
    898   KitCgMemAccess mem;
    899   uint32_t size;
    900 
    901   memset(&opts, 0, sizeof opts);
    902   opts.opt_level = 1;
    903   ob = new_obj(c);
    904   EXPECT(ob != NULL, "delayed store obj builder allocation failed");
    905   if (!ob) return 0;
    906   cg = NULL;
    907   (void)kit_cg_new(c, &cg);
    908   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    909   EXPECT(cg != NULL, "delayed store cg allocation failed");
    910   if (!cg) {
    911     kit_obj_builder_free(ob);
    912     return 0;
    913   }
    914 
    915   memset(&param_desc, 0, sizeof param_desc);
    916   param_desc.type = i32_ty;
    917   memset(&sig, 0, sizeof sig);
    918   KitCgFuncResult sig_result;
    919   memset(&sig_result, 0, sizeof sig_result);
    920   sig_result.type = i32_ty;
    921   sig.result = sig_result;
    922   sig.params = &param_desc;
    923   sig.nparams = 1;
    924   sig.call_conv = KIT_CG_CC_TARGET_C;
    925 
    926   memset(&decl, 0, sizeof decl);
    927   decl.kind = KIT_CG_DECL_FUNC;
    928   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
    929   decl.display_name = decl.linkage_name;
    930   decl.type = kit_cg_type_func(c, sig);
    931   decl.sym.bind = KIT_SB_GLOBAL;
    932   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    933   sym = kit_cg_decl(cg, decl);
    934   EXPECT(sym != KIT_CG_SYM_NONE, "delayed store decl failed");
    935 
    936   kit_cg_func_begin(cg, sym);
    937   memset(&attrs, 0, sizeof attrs);
    938   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("p"));
    939   param = kit_cg_param(cg, 0, i32_ty, attrs);
    940   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
    941   local = kit_cg_local(cg, i32_ty, attrs);
    942   EXPECT(param != KIT_CG_LOCAL_NONE, "delayed store param failed");
    943   EXPECT(local != KIT_CG_LOCAL_NONE, "delayed store local failed");
    944   memset(&mem, 0, sizeof mem);
    945   mem.type = i32_ty;
    946   mem.align = kit_cg_type_align(c, i32_ty);
    947   kit_cg_push_local(cg, local);
    948   kit_cg_push_local(cg, param);
    949   kit_cg_load(cg, mem);
    950   kit_cg_push_int(cg, 40, i32_ty);
    951   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    952   kit_cg_push_int(cg, 2, i32_ty);
    953   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    954   kit_cg_store(cg, mem);
    955   kit_cg_push_local(cg, local);
    956   kit_cg_load(cg, mem);
    957   kit_cg_ret(cg);
    958   kit_cg_func_end(cg);
    959 
    960   finish_cg(cg, "delayed store");
    961   kit_cg_free(cg);
    962   size = text_size(c, ob);
    963   kit_obj_builder_free(ob);
    964   return size;
    965 }
    966 
    967 static uint32_t cg_emit_delayed_pressure(KitCompiler* c, KitCgTypeId i32_ty,
    968                                          const char* name) {
    969   enum { NPARAMS = 13 };
    970   KitCodeOptions opts;
    971   KitObjBuilder* ob;
    972   KitCg* cg;
    973   KitCgFuncParam param_desc[NPARAMS];
    974   KitCgFuncSig sig;
    975   KitCgDecl decl;
    976   KitCgSym sym;
    977   KitCgLocalAttrs attrs;
    978   KitCgLocal params[NPARAMS];
    979   KitCgMemAccess mem;
    980   uint32_t size;
    981 
    982   memset(&opts, 0, sizeof opts);
    983   opts.opt_level = 1;
    984   ob = new_obj(c);
    985   EXPECT(ob != NULL, "delayed pressure obj builder allocation failed");
    986   if (!ob) return 0;
    987   cg = NULL;
    988   (void)kit_cg_new(c, &cg);
    989   if (cg) (void)kit_cg_begin(cg, ob, &opts);
    990   EXPECT(cg != NULL, "delayed pressure cg allocation failed");
    991   if (!cg) {
    992     kit_obj_builder_free(ob);
    993     return 0;
    994   }
    995 
    996   memset(param_desc, 0, sizeof param_desc);
    997   for (uint32_t i = 0; i < NPARAMS; ++i) param_desc[i].type = i32_ty;
    998   memset(&sig, 0, sizeof sig);
    999   KitCgFuncResult sig_result;
   1000   memset(&sig_result, 0, sizeof sig_result);
   1001   sig_result.type = i32_ty;
   1002   sig.result = sig_result;
   1003   sig.params = param_desc;
   1004   sig.nparams = NPARAMS;
   1005   sig.call_conv = KIT_CG_CC_TARGET_C;
   1006 
   1007   memset(&decl, 0, sizeof decl);
   1008   decl.kind = KIT_CG_DECL_FUNC;
   1009   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
   1010   decl.display_name = decl.linkage_name;
   1011   decl.type = kit_cg_type_func(c, sig);
   1012   decl.sym.bind = KIT_SB_GLOBAL;
   1013   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1014   sym = kit_cg_decl(cg, decl);
   1015   EXPECT(sym != KIT_CG_SYM_NONE, "delayed pressure decl failed");
   1016 
   1017   kit_cg_func_begin(cg, sym);
   1018   memset(&attrs, 0, sizeof attrs);
   1019   memset(&mem, 0, sizeof mem);
   1020   mem.type = i32_ty;
   1021   mem.align = kit_cg_type_align(c, i32_ty);
   1022   for (uint32_t i = 0; i < NPARAMS; ++i) {
   1023     char pname[8];
   1024     snprintf(pname, sizeof pname, "p%u", (unsigned)i);
   1025     attrs.name = kit_sym_intern(c, kit_slice_cstr(pname));
   1026     params[i] = kit_cg_param(cg, i, i32_ty, attrs);
   1027     EXPECT(params[i] != KIT_CG_LOCAL_NONE, "delayed pressure param failed");
   1028   }
   1029 
   1030   for (uint32_t i = 0; i + 1 < NPARAMS; ++i) {
   1031     kit_cg_push_local(cg, params[i]);
   1032     kit_cg_load(cg, mem);
   1033     kit_cg_push_int(cg, 1, i32_ty);
   1034     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1035   }
   1036   kit_cg_push_local(cg, params[NPARAMS - 1]);
   1037   kit_cg_load(cg, mem);
   1038   kit_cg_drop(cg);
   1039   for (uint32_t i = 0; i + 1 < NPARAMS; ++i) kit_cg_drop(cg);
   1040   kit_cg_push_int(cg, 0, i32_ty);
   1041   kit_cg_ret(cg);
   1042   kit_cg_func_end(cg);
   1043 
   1044   finish_cg(cg, "delayed pressure");
   1045   kit_cg_free(cg);
   1046   size = text_size(c, ob);
   1047   kit_obj_builder_free(ob);
   1048   return size;
   1049 }
   1050 
   1051 typedef enum CgShadowBoundary {
   1052   CG_SHADOW_LABEL,
   1053   CG_SHADOW_BRANCH,
   1054   CG_SHADOW_ADDR,
   1055   CG_SHADOW_VOLATILE,
   1056   CG_SHADOW_INDIRECT_STORE,
   1057 } CgShadowBoundary;
   1058 
   1059 static uint32_t cg_emit_local_shadow_boundary(KitCompiler* c,
   1060                                               KitCgTypeId i32_ty,
   1061                                               const char* name,
   1062                                               CgShadowBoundary boundary) {
   1063   KitCodeOptions opts;
   1064   KitObjBuilder* ob;
   1065   KitCg* cg;
   1066   KitCgFuncSig sig;
   1067   KitCgDecl decl;
   1068   KitCgSym sym;
   1069   KitCgLocalAttrs attrs;
   1070   KitCgLocal local;
   1071   KitCgMemAccess mem;
   1072   uint32_t size;
   1073 
   1074   memset(&opts, 0, sizeof opts);
   1075   opts.opt_level = 1;
   1076   ob = new_obj(c);
   1077   EXPECT(ob != NULL, "local shadow boundary obj builder allocation failed");
   1078   if (!ob) return 0;
   1079   cg = NULL;
   1080   (void)kit_cg_new(c, &cg);
   1081   if (cg) (void)kit_cg_begin(cg, ob, &opts);
   1082   EXPECT(cg != NULL, "local shadow boundary cg allocation failed");
   1083   if (!cg) {
   1084     kit_obj_builder_free(ob);
   1085     return 0;
   1086   }
   1087 
   1088   memset(&sig, 0, sizeof sig);
   1089   KitCgFuncResult sig_result;
   1090   memset(&sig_result, 0, sizeof sig_result);
   1091   sig_result.type = i32_ty;
   1092   sig.result = sig_result;
   1093   sig.call_conv = KIT_CG_CC_TARGET_C;
   1094 
   1095   memset(&decl, 0, sizeof decl);
   1096   decl.kind = KIT_CG_DECL_FUNC;
   1097   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
   1098   decl.display_name = decl.linkage_name;
   1099   decl.type = kit_cg_type_func(c, sig);
   1100   decl.sym.bind = KIT_SB_GLOBAL;
   1101   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1102   sym = kit_cg_decl(cg, decl);
   1103   EXPECT(sym != KIT_CG_SYM_NONE, "local shadow boundary decl failed");
   1104 
   1105   kit_cg_func_begin(cg, sym);
   1106   memset(&attrs, 0, sizeof attrs);
   1107   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
   1108   local = kit_cg_local(cg, i32_ty, attrs);
   1109   EXPECT(local != KIT_CG_LOCAL_NONE, "local shadow boundary local failed");
   1110   memset(&mem, 0, sizeof mem);
   1111   mem.type = i32_ty;
   1112   mem.align = kit_cg_type_align(c, i32_ty);
   1113 
   1114   kit_cg_push_local(cg, local);
   1115   kit_cg_push_int(cg, 40, i32_ty);
   1116   kit_cg_store(cg, mem);
   1117 
   1118   switch (boundary) {
   1119     case CG_SHADOW_LABEL: {
   1120       KitCgLabel label = kit_cg_label_new(cg);
   1121       kit_cg_label_place(cg, label);
   1122       break;
   1123     }
   1124     case CG_SHADOW_BRANCH: {
   1125       KitCgLabel label = kit_cg_label_new(cg);
   1126       kit_cg_push_int(cg, 0, i32_ty);
   1127       kit_cg_branch_true(cg, label);
   1128       kit_cg_label_place(cg, label);
   1129       break;
   1130     }
   1131     case CG_SHADOW_ADDR:
   1132       kit_cg_push_local_addr(cg, local);
   1133       kit_cg_drop(cg);
   1134       break;
   1135     case CG_SHADOW_VOLATILE:
   1136       mem.flags = KIT_CG_MEM_VOLATILE;
   1137       kit_cg_push_local(cg, local);
   1138       kit_cg_load(cg, mem);
   1139       kit_cg_drop(cg);
   1140       mem.flags = 0;
   1141       break;
   1142     case CG_SHADOW_INDIRECT_STORE:
   1143       kit_cg_push_local_addr(cg, local);
   1144       kit_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the store */
   1145       kit_cg_push_int(cg, 41, i32_ty);
   1146       kit_cg_store(cg, mem);
   1147       break;
   1148   }
   1149 
   1150   kit_cg_push_local(cg, local);
   1151   kit_cg_load(cg, mem);
   1152   kit_cg_push_int(cg, 2, i32_ty);
   1153   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1154   kit_cg_ret(cg);
   1155   kit_cg_func_end(cg);
   1156 
   1157   finish_cg(cg, "local shadow boundary");
   1158   kit_cg_free(cg);
   1159   size = text_size(c, ob);
   1160   kit_obj_builder_free(ob);
   1161   return size;
   1162 }
   1163 
   1164 static uint32_t cg_emit_local_shadow_partial_store(KitCompiler* c,
   1165                                                    KitCgTypeId i32_ty,
   1166                                                    KitCgTypeId i8_ty,
   1167                                                    const char* name) {
   1168   KitCodeOptions opts;
   1169   KitObjBuilder* ob;
   1170   KitCg* cg;
   1171   KitCgFuncSig sig;
   1172   KitCgDecl decl;
   1173   KitCgSym sym;
   1174   KitCgLocalAttrs attrs;
   1175   KitCgLocal local;
   1176   KitCgMemAccess mem_i32;
   1177   KitCgMemAccess mem_i8;
   1178   uint32_t size;
   1179 
   1180   memset(&opts, 0, sizeof opts);
   1181   opts.opt_level = 1;
   1182   ob = new_obj(c);
   1183   EXPECT(ob != NULL, "partial shadow obj builder allocation failed");
   1184   if (!ob) return 0;
   1185   cg = NULL;
   1186   (void)kit_cg_new(c, &cg);
   1187   if (cg) (void)kit_cg_begin(cg, ob, &opts);
   1188   EXPECT(cg != NULL, "partial shadow cg allocation failed");
   1189   if (!cg) {
   1190     kit_obj_builder_free(ob);
   1191     return 0;
   1192   }
   1193 
   1194   memset(&sig, 0, sizeof sig);
   1195   KitCgFuncResult sig_result;
   1196   memset(&sig_result, 0, sizeof sig_result);
   1197   sig_result.type = i32_ty;
   1198   sig.result = sig_result;
   1199   sig.call_conv = KIT_CG_CC_TARGET_C;
   1200 
   1201   memset(&decl, 0, sizeof decl);
   1202   decl.kind = KIT_CG_DECL_FUNC;
   1203   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
   1204   decl.display_name = decl.linkage_name;
   1205   decl.type = kit_cg_type_func(c, sig);
   1206   decl.sym.bind = KIT_SB_GLOBAL;
   1207   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1208   sym = kit_cg_decl(cg, decl);
   1209   EXPECT(sym != KIT_CG_SYM_NONE, "partial shadow decl failed");
   1210 
   1211   kit_cg_func_begin(cg, sym);
   1212   memset(&attrs, 0, sizeof attrs);
   1213   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("x"));
   1214   local = kit_cg_local(cg, i32_ty, attrs);
   1215   EXPECT(local != KIT_CG_LOCAL_NONE, "partial shadow local failed");
   1216   memset(&mem_i32, 0, sizeof mem_i32);
   1217   mem_i32.type = i32_ty;
   1218   mem_i32.align = kit_cg_type_align(c, i32_ty);
   1219   memset(&mem_i8, 0, sizeof mem_i8);
   1220   mem_i8.type = i8_ty;
   1221   mem_i8.align = kit_cg_type_align(c, i8_ty);
   1222 
   1223   kit_cg_push_local(cg, local);
   1224   kit_cg_push_int(cg, 40, i32_ty);
   1225   kit_cg_store(cg, mem_i32);
   1226   kit_cg_push_local(cg, local);
   1227   kit_cg_push_int(cg, 7, i8_ty);
   1228   kit_cg_store(cg, mem_i8);
   1229   kit_cg_push_local(cg, local);
   1230   kit_cg_load(cg, mem_i32);
   1231   kit_cg_push_int(cg, 2, i32_ty);
   1232   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1233   kit_cg_ret(cg);
   1234   kit_cg_func_end(cg);
   1235 
   1236   finish_cg(cg, "partial shadow");
   1237   kit_cg_free(cg);
   1238   size = text_size(c, ob);
   1239   kit_obj_builder_free(ob);
   1240   return size;
   1241 }
   1242 
   1243 static void exercise_cg_constfold_phases(KitCompiler* c, KitCgTypeId i32_ty,
   1244                                          KitCgTypeId i8_ty) {
   1245   uint32_t delayed_size =
   1246       cg_emit_delayed_chain(c, i32_ty, "cg_delayed_chain_o1");
   1247   uint32_t unary_size = cg_emit_unary_chain(c, i32_ty, "cg_unary_chain_o1");
   1248   uint32_t local_size = cg_emit_local_shadow(c, i32_ty, "cg_local_shadow_o1");
   1249   uint32_t delayed_cmp_size =
   1250       cg_emit_delayed_cmp(c, i32_ty, "cg_delayed_cmp_o1");
   1251   uint32_t delayed_store_size =
   1252       cg_emit_delayed_store(c, i32_ty, "cg_delayed_store_o1");
   1253   uint32_t pressure_size =
   1254       cg_emit_delayed_pressure(c, i32_ty, "cg_delayed_pressure_o1");
   1255   uint32_t label_size = cg_emit_local_shadow_boundary(
   1256       c, i32_ty, "cg_shadow_label_o1", CG_SHADOW_LABEL);
   1257   uint32_t branch_size = cg_emit_local_shadow_boundary(
   1258       c, i32_ty, "cg_shadow_branch_o1", CG_SHADOW_BRANCH);
   1259   uint32_t addr_size = cg_emit_local_shadow_boundary(
   1260       c, i32_ty, "cg_shadow_addr_o1", CG_SHADOW_ADDR);
   1261   uint32_t volatile_size = cg_emit_local_shadow_boundary(
   1262       c, i32_ty, "cg_shadow_volatile_o1", CG_SHADOW_VOLATILE);
   1263   uint32_t indirect_size = cg_emit_local_shadow_boundary(
   1264       c, i32_ty, "cg_shadow_indirect_o1", CG_SHADOW_INDIRECT_STORE);
   1265   uint32_t partial_size = cg_emit_local_shadow_partial_store(
   1266       c, i32_ty, i8_ty, "cg_shadow_partial_o1");
   1267 
   1268   EXPECT(delayed_size <= 56,
   1269          "delayed arithmetic chain should materialize as one add, text "
   1270          "size=%u",
   1271          delayed_size);
   1272   EXPECT(unary_size <= 48,
   1273          "delayed unary chain should collapse before return, text size=%u",
   1274          unary_size);
   1275   EXPECT(local_size <= 32,
   1276          "local constant shadow should fold x=40; return x+2, text size=%u",
   1277          local_size);
   1278   EXPECT(delayed_cmp_size <= 64,
   1279          "delayed arithmetic consumed by compare should stay compact, text "
   1280          "size=%u",
   1281          delayed_cmp_size);
   1282   EXPECT(delayed_store_size <= 64,
   1283          "delayed arithmetic forced by store should stay compact, text size=%u",
   1284          delayed_store_size);
   1285   EXPECT(pressure_size > 0,
   1286          "delayed arithmetic pressure materialization should emit code");
   1287   EXPECT(label_size > local_size,
   1288          "label should clear local shadow, label=%u folded=%u", label_size,
   1289          local_size);
   1290   EXPECT(branch_size > local_size,
   1291          "branch should clear local shadow, branch=%u folded=%u", branch_size,
   1292          local_size);
   1293   EXPECT(addr_size > local_size,
   1294          "address-taking should clear local shadow, addr=%u folded=%u",
   1295          addr_size, local_size);
   1296   EXPECT(volatile_size > local_size,
   1297          "volatile access should clear local shadow, volatile=%u folded=%u",
   1298          volatile_size, local_size);
   1299   EXPECT(indirect_size > local_size,
   1300          "indirect store should clear local shadow, indirect=%u folded=%u",
   1301          indirect_size, local_size);
   1302   EXPECT(partial_size > local_size,
   1303          "partial-width store should clear local shadow, partial=%u folded=%u",
   1304          partial_size, local_size);
   1305 }
   1306 
   1307 static void exercise_cg_memop_constfold_shape(KitCompiler* c,
   1308                                               KitCgTypeId i32_ty,
   1309                                               KitCgTypeId i64_ty,
   1310                                               KitCgTypeId ptr_i32) {
   1311   KitCodeOptions opts;
   1312   KitObjBuilder* ob;
   1313   KitWriter* dump = NULL;
   1314   KitCg* cg;
   1315   KitCgFuncParam params[2];
   1316   KitCgFuncSig sig;
   1317   KitCgDecl decl;
   1318   KitCgSym fn_sym;
   1319   KitCgSym data_sym;
   1320   KitCgLocalAttrs attrs;
   1321   KitCgLocal base_param;
   1322   KitCgLocal idx_param;
   1323   KitCgMemAccess mem_i32;
   1324   KitCgMemAccess mem_i64;
   1325   KitCgMemAccess mem_ptr;
   1326   const uint8_t data[64] = {0};
   1327   const uint8_t* bytes;
   1328   size_t len = 0;
   1329   char text[8192];
   1330   size_t copy_len;
   1331 
   1332   memset(&opts, 0, sizeof opts);
   1333   opts.opt_level = 1;
   1334   opts.emit_ir = true;
   1335   EXPECT(kit_writer_mem(&g_u.heap, &dump) == KIT_OK && dump != NULL,
   1336          "memop fold dump writer allocation failed");
   1337   if (!dump) return;
   1338   opts.ir_dump_writer = dump;
   1339 
   1340   ob = new_obj(c);
   1341   EXPECT(ob != NULL, "memop fold obj builder allocation failed");
   1342   if (!ob) {
   1343     kit_writer_close(dump);
   1344     return;
   1345   }
   1346   cg = NULL;
   1347   (void)kit_cg_new(c, &cg);
   1348   if (cg) (void)kit_cg_begin(cg, ob, &opts);
   1349   EXPECT(cg != NULL, "memop fold cg allocation failed");
   1350   if (!cg) {
   1351     kit_obj_builder_free(ob);
   1352     kit_writer_close(dump);
   1353     return;
   1354   }
   1355 
   1356   data_sym = kit_cg_const_data(cg, data, sizeof data, 4, i32_ty);
   1357   EXPECT(data_sym != KIT_CG_SYM_NONE, "memop fold const data failed");
   1358 
   1359   memset(params, 0, sizeof params);
   1360   params[0].type = ptr_i32;
   1361   params[1].type = i64_ty;
   1362   memset(&sig, 0, sizeof sig);
   1363   KitCgFuncResult sig_result;
   1364   memset(&sig_result, 0, sizeof sig_result);
   1365   sig_result.type = i32_ty;
   1366   sig.result = sig_result;
   1367   sig.params = params;
   1368   sig.nparams = 2;
   1369   sig.call_conv = KIT_CG_CC_TARGET_C;
   1370 
   1371   memset(&decl, 0, sizeof decl);
   1372   decl.kind = KIT_CG_DECL_FUNC;
   1373   decl.linkage_name =
   1374       kit_sym_intern(c, KIT_SLICE_LIT("cg_memop_constfold_shape"));
   1375   decl.display_name = decl.linkage_name;
   1376   decl.type = kit_cg_type_func(c, sig);
   1377   decl.sym.bind = KIT_SB_GLOBAL;
   1378   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1379   fn_sym = kit_cg_decl(cg, decl);
   1380   EXPECT(fn_sym != KIT_CG_SYM_NONE, "memop fold function decl failed");
   1381 
   1382   memset(&mem_i32, 0, sizeof mem_i32);
   1383   mem_i32.type = i32_ty;
   1384   mem_i32.align = kit_cg_type_align(c, i32_ty);
   1385   memset(&mem_i64, 0, sizeof mem_i64);
   1386   mem_i64.type = i64_ty;
   1387   mem_i64.align = kit_cg_type_align(c, i64_ty);
   1388   memset(&mem_ptr, 0, sizeof mem_ptr);
   1389   mem_ptr.type = ptr_i32;
   1390   mem_ptr.align = kit_cg_type_align(c, ptr_i32);
   1391 
   1392   kit_cg_func_begin(cg, fn_sym);
   1393   memset(&attrs, 0, sizeof attrs);
   1394   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("base"));
   1395   base_param = kit_cg_param(cg, 0, ptr_i32, attrs);
   1396   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("idx"));
   1397   idx_param = kit_cg_param(cg, 1, i64_ty, attrs);
   1398   EXPECT(base_param != KIT_CG_LOCAL_NONE && idx_param != KIT_CG_LOCAL_NONE,
   1399          "memop fold params failed");
   1400 
   1401   /* Constant base addend + constant index*scale + offset: 11 + 3*8 + 5. */
   1402   kit_cg_push_symbol_addr(cg, data_sym, 11);
   1403   kit_cg_push_int(cg, 3, i64_ty);
   1404   kit_cg_elem_scaled(cg, 8, 5);
   1405   kit_cg_load(cg, mem_i32);
   1406   kit_cg_drop(cg);
   1407 
   1408   /* Non-global offsets wider than the memop displacement are materialized into
   1409    * the base instead of truncated to i32. */
   1410   kit_cg_push_local(cg, base_param);
   1411   kit_cg_load(cg, mem_ptr);
   1412   kit_cg_push_local(cg, idx_param);
   1413   kit_cg_load(cg, mem_i64);
   1414   kit_cg_elem_scaled(cg, 8, 2147483656LL);
   1415   kit_cg_load(cg, mem_i32);
   1416   kit_cg_drop(cg);
   1417 
   1418   /* Dynamic base and index keep the scale and offset on the memory operand. */
   1419   kit_cg_push_local(cg, base_param);
   1420   kit_cg_load(cg, mem_ptr);
   1421   kit_cg_push_local(cg, idx_param);
   1422   kit_cg_load(cg, mem_i64);
   1423   kit_cg_elem_scaled(cg, 8, 5);
   1424   kit_cg_load(cg, mem_i32);
   1425   kit_cg_ret(cg);
   1426   kit_cg_func_end(cg);
   1427 
   1428   EXPECT(kit_cg_finish(cg, NULL) == KIT_OK, "memop fold cg finish failed");
   1429   bytes = kit_writer_mem_bytes(dump, &len);
   1430   copy_len = len < sizeof text - 1u ? len : sizeof text - 1u;
   1431   if (bytes && copy_len) memcpy(text, bytes, copy_len);
   1432   text[copy_len] = '\0';
   1433   EXPECT(bytes != NULL && len > 0 && len < sizeof text,
   1434          "memop fold IR dump missing or too large");
   1435   EXPECT(strstr(text, "addr_of") == NULL,
   1436          "memop fold should not materialize folded addresses:\n%s", text);
   1437   EXPECT(strstr(text, "sym#") != NULL && strstr(text, "+40") != NULL,
   1438          "memop fold should fold symbol base/addend/index/offset:\n%s", text);
   1439   EXPECT(strstr(text, "*8+5") != NULL,
   1440          "memop fold should preserve dynamic index scale/offset:\n%s", text);
   1441   EXPECT(strstr(text, "imm:2147483656") != NULL,
   1442          "memop fold should materialize offsets wider than i32:\n%s", text);
   1443 
   1444   kit_cg_free(cg);
   1445   kit_obj_builder_free(ob);
   1446   kit_writer_close(dump);
   1447 }
   1448 
   1449 static KitCg* begin_void_cg_func(KitCompiler* c, const char* name,
   1450                                  KitObjBuilder** ob_out) {
   1451   KitCodeOptions opts;
   1452   KitObjBuilder* ob;
   1453   KitCg* cg;
   1454   KitCgFuncSig sig;
   1455   KitCgFuncResult result;
   1456   KitCgDecl decl;
   1457   KitCgSym sym;
   1458 
   1459   if (ob_out) *ob_out = NULL;
   1460   memset(&opts, 0, sizeof opts);
   1461   ob = new_obj(c);
   1462   EXPECT(ob != NULL, "%s obj builder allocation failed", name);
   1463   if (!ob) return NULL;
   1464   cg = NULL;
   1465   EXPECT(kit_cg_new(c, &cg) == KIT_OK && cg != NULL, "%s cg allocation failed",
   1466          name);
   1467   if (!cg) {
   1468     kit_obj_builder_free(ob);
   1469     return NULL;
   1470   }
   1471   EXPECT(kit_cg_begin(cg, ob, &opts) == KIT_OK, "%s cg begin failed", name);
   1472 
   1473   memset(&sig, 0, sizeof sig);
   1474   memset(&result, 0, sizeof result);
   1475   result.type = kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID);
   1476   sig.result = result;
   1477   sig.call_conv = KIT_CG_CC_TARGET_C;
   1478   memset(&decl, 0, sizeof decl);
   1479   decl.kind = KIT_CG_DECL_FUNC;
   1480   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
   1481   decl.display_name = decl.linkage_name;
   1482   decl.type = kit_cg_type_func(c, sig);
   1483   decl.sym.bind = KIT_SB_LOCAL;
   1484   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1485   sym = kit_cg_decl(cg, decl);
   1486   EXPECT(sym != KIT_CG_SYM_NONE, "%s decl failed", name);
   1487   if (sym == KIT_CG_SYM_NONE) {
   1488     kit_cg_free(cg);
   1489     kit_obj_builder_free(ob);
   1490     return NULL;
   1491   }
   1492   kit_cg_func_begin(cg, sym);
   1493   if (ob_out) *ob_out = ob;
   1494   return cg;
   1495 }
   1496 
   1497 static void exercise_cg_slot_lang_facts(KitCompiler* c, KitCgTypeId i32_ty) {
   1498   static const char tag_a[] = "slot-a";
   1499   static const char tag_b[] = "slot-b";
   1500   KitObjBuilder* ob;
   1501   KitCg* cg = begin_void_cg_func(c, "cg_slot_lang_facts", &ob);
   1502   KitCgSlotInfo info;
   1503   KitCgScope scope;
   1504   if (!cg) return;
   1505 
   1506   kit_cg_push_int(cg, 1, i32_ty);
   1507   kit_cg_retag_top(cg, tag_a, 0x0003u);
   1508   kit_cg_dup(cg);
   1509   info = kit_cg_slot_info(cg, 0);
   1510   EXPECT(info.cg_type == i32_ty && info.lang_type == tag_a &&
   1511              info.lang_flags == 0x0003u,
   1512          "dup should copy top slot facts");
   1513   info = kit_cg_slot_info(cg, 1);
   1514   EXPECT(info.lang_type == tag_a && info.lang_flags == 0x0003u,
   1515          "dup should preserve original slot facts");
   1516   kit_cg_retag_at(cg, 1, tag_b, 0x0010u);
   1517   kit_cg_set_top_flags(cg, 0x0004u, 0x0001u);
   1518   info = kit_cg_slot_info(cg, 0);
   1519   EXPECT(info.lang_type == tag_a && info.lang_flags == 0x0006u,
   1520          "set_top_flags should update only top flags");
   1521   info = kit_cg_slot_info(cg, 1);
   1522   EXPECT(info.lang_type == tag_b && info.lang_flags == 0x0010u,
   1523          "retag_at should update depth-selected slot");
   1524   kit_cg_drop(cg);
   1525   kit_cg_drop(cg);
   1526 
   1527   kit_cg_push_int(cg, 2, i32_ty);
   1528   kit_cg_retag_top(cg, tag_a, 0x00ffu);
   1529   kit_cg_push_int(cg, 3, i32_ty);
   1530   kit_cg_retag_top(cg, tag_b, 0x00eeu);
   1531   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1532   info = kit_cg_slot_info(cg, 0);
   1533   EXPECT(
   1534       info.cg_type == i32_ty && info.lang_type == NULL && info.lang_flags == 0,
   1535       "fresh binop producer should clear slot facts");
   1536   kit_cg_drop(cg);
   1537 
   1538   scope = kit_cg_block_begin_value(cg, i32_ty);
   1539   kit_cg_push_int(cg, 4, i32_ty);
   1540   kit_cg_retag_top(cg, tag_b, 0x0033u);
   1541   kit_cg_scope_end(cg, scope);
   1542   info = kit_cg_slot_info(cg, 0);
   1543   EXPECT(info.cg_type == i32_ty && info.lang_type == tag_b &&
   1544              info.lang_flags == 0x0033u,
   1545          "scope result mover should preserve slot facts");
   1546   kit_cg_drop(cg);
   1547 
   1548   kit_cg_ret(cg);
   1549   kit_cg_func_end(cg);
   1550   kit_cg_free(cg);
   1551   kit_obj_builder_free(ob);
   1552 }
   1553 
   1554 static void exercise_cg_field_at_store_keep(KitCompiler* c, KitCgTypeId i32_ty,
   1555                                             KitCgTypeId rec_ty) {
   1556   static const char value_tag[] = "assigned-value";
   1557   KitObjBuilder* ob;
   1558   KitCg* cg = begin_void_cg_func(c, "cg_field_at_store_keep", &ob);
   1559   KitCgLocalAttrs attrs;
   1560   KitCgLocal local;
   1561   KitCgMemAccess mem;
   1562   KitCgSlotInfo info;
   1563   if (!cg) return;
   1564 
   1565   memset(&attrs, 0, sizeof attrs);
   1566   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("r"));
   1567   local = kit_cg_local(cg, rec_ty, attrs);
   1568   EXPECT(local != KIT_CG_LOCAL_NONE, "field_at local allocation failed");
   1569 
   1570   memset(&mem, 0, sizeof mem);
   1571   mem.type = i32_ty;
   1572   mem.align = kit_cg_type_align(c, i32_ty);
   1573 
   1574   kit_cg_push_local(cg, local);
   1575   kit_cg_field_at(cg, 4, i32_ty);
   1576   kit_cg_push_int(cg, 42, i32_ty);
   1577   kit_cg_retag_top(cg, value_tag, 0x0042u);
   1578   kit_cg_store_keep(cg, mem);
   1579   EXPECT(kit_cg_stack_depth(cg) == 1u, "store_keep should leave one value");
   1580   info = kit_cg_slot_info(cg, 0);
   1581   EXPECT(info.cg_type == i32_ty && info.lang_type == value_tag &&
   1582              info.lang_flags == 0x0042u,
   1583          "store_keep should preserve assigned value slot facts");
   1584   kit_cg_drop(cg);
   1585 
   1586   kit_cg_push_local(cg, local);
   1587   kit_cg_field_at(cg, 4, i32_ty);
   1588   kit_cg_load(cg, mem);
   1589   info = kit_cg_slot_info(cg, 0);
   1590   EXPECT(
   1591       info.cg_type == i32_ty && info.lang_type == NULL && info.lang_flags == 0,
   1592       "load through field_at should produce a freshly untagged value");
   1593   kit_cg_drop(cg);
   1594 
   1595   kit_cg_ret(cg);
   1596   kit_cg_func_end(cg);
   1597   kit_cg_free(cg);
   1598   kit_obj_builder_free(ob);
   1599 }
   1600 
   1601 typedef struct BadStoreCtx {
   1602   KitCompiler* c;
   1603   KitCgTypeId i32_ty;
   1604   KitCgTypeId i64_ty;
   1605   KitCgTypeId rec_ty;
   1606 } BadStoreCtx;
   1607 
   1608 static KitCg* cg_begin_bad_store_func(KitCompiler* c, const char* name) {
   1609   KitCodeOptions opts;
   1610   KitObjBuilder* ob;
   1611   KitCg* cg;
   1612   KitCgFuncSig sig;
   1613   KitCgFuncResult result;
   1614   KitCgDecl decl;
   1615   KitCgSym sym;
   1616 
   1617   memset(&opts, 0, sizeof opts);
   1618   ob = new_obj(c);
   1619   EXPECT(ob != NULL, "bad-store obj builder allocation failed");
   1620   if (!ob) return NULL;
   1621   cg = NULL;
   1622   (void)kit_cg_new(c, &cg);
   1623   if (cg) (void)kit_cg_begin(cg, ob, &opts);
   1624   EXPECT(cg != NULL, "bad-store cg allocation failed");
   1625   if (!cg) {
   1626     kit_obj_builder_free(ob);
   1627     return NULL;
   1628   }
   1629 
   1630   memset(&sig, 0, sizeof sig);
   1631   memset(&result, 0, sizeof result);
   1632   result.type = kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID);
   1633   sig.result = result;
   1634   sig.call_conv = KIT_CG_CC_TARGET_C;
   1635   memset(&decl, 0, sizeof decl);
   1636   decl.kind = KIT_CG_DECL_FUNC;
   1637   decl.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
   1638   decl.display_name = decl.linkage_name;
   1639   decl.type = kit_cg_type_func(c, sig);
   1640   decl.sym.bind = KIT_SB_LOCAL;
   1641   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1642   sym = kit_cg_decl(cg, decl);
   1643   EXPECT(sym != KIT_CG_SYM_NONE, "bad-store function decl failed");
   1644   if (sym == KIT_CG_SYM_NONE) {
   1645     kit_cg_free(cg);
   1646     kit_obj_builder_free(ob);
   1647     return NULL;
   1648   }
   1649   kit_cg_func_begin(cg, sym);
   1650   return cg;
   1651 }
   1652 
   1653 static void run_bad_scalar_access_to_aggregate(void* arg) {
   1654   BadStoreCtx* ctx = (BadStoreCtx*)arg;
   1655   KitCgLocal local;
   1656   KitCgLocalAttrs attrs;
   1657   KitCgMemAccess mem;
   1658   KitCg* cg =
   1659       cg_begin_bad_store_func(ctx->c, "cg_bad_scalar_access_to_aggregate");
   1660   if (!cg) return;
   1661 
   1662   memset(&attrs, 0, sizeof attrs);
   1663   local = kit_cg_local(cg, ctx->rec_ty, attrs);
   1664   memset(&mem, 0, sizeof mem);
   1665   mem.type = ctx->i32_ty;
   1666   mem.align = kit_cg_type_align(ctx->c, ctx->i32_ty);
   1667   kit_cg_push_local(cg, local);
   1668   kit_cg_push_int(cg, 42, ctx->i32_ty);
   1669   kit_cg_store(cg, mem);
   1670 }
   1671 
   1672 static void run_bad_store_value_size(void* arg) {
   1673   BadStoreCtx* ctx = (BadStoreCtx*)arg;
   1674   KitCgLocal local;
   1675   KitCgLocalAttrs attrs;
   1676   KitCgMemAccess mem;
   1677   KitCg* cg = cg_begin_bad_store_func(ctx->c, "cg_bad_store_value_size");
   1678   if (!cg) return;
   1679 
   1680   memset(&attrs, 0, sizeof attrs);
   1681   local = kit_cg_local(cg, ctx->i64_ty, attrs);
   1682   memset(&mem, 0, sizeof mem);
   1683   mem.type = ctx->i64_ty;
   1684   mem.align = kit_cg_type_align(ctx->c, ctx->i64_ty);
   1685   kit_cg_push_local(cg, local);
   1686   kit_cg_push_int(cg, 42, ctx->i32_ty);
   1687   kit_cg_store(cg, mem);
   1688 }
   1689 
   1690 static void exercise_cg_memory_mismatch_diags(KitCompiler* c,
   1691                                               KitCgTypeId i32_ty,
   1692                                               KitCgTypeId i64_ty,
   1693                                               KitCgTypeId rec_ty) {
   1694   BadStoreCtx ctx;
   1695   ctx.c = c;
   1696   ctx.i32_ty = i32_ty;
   1697   ctx.i64_ty = i64_ty;
   1698   ctx.rec_ty = rec_ty;
   1699 
   1700   /* Scalar store at offset 0 into an aggregate lvalue is now a field-store
   1701    * under the EA model (see doc/INDIRECT.md), so no diagnostic fires. */
   1702   (void)run_bad_scalar_access_to_aggregate;
   1703   EXPECT(expect_panic_contains(c, run_bad_store_value_size, &ctx,
   1704                                "store value type/size mismatch"),
   1705          "store size mismatch should diagnose clearly, got '%s'",
   1706          g_u.last_diag);
   1707 }
   1708 
   1709 static void exercise_compile_session_two_deltas(KitCompiler* c) {
   1710   KitCompileSessionOptions sopts;
   1711   KitCompileSession* s = NULL;
   1712   KitAsmCompileOptions aopts;
   1713   KitSourceInput in;
   1714   KitObjBuilder* ob1 = NULL;
   1715   KitObjBuilder* ob2 = NULL;
   1716   static const uint8_t empty[] = "";
   1717 
   1718   memset(&sopts, 0, sizeof(sopts));
   1719   memset(&aopts, 0, sizeof(aopts));
   1720   sopts.lang = KIT_LANG_ASM;
   1721   sopts.compile.language_options = &aopts;
   1722   memset(&in, 0, sizeof(in));
   1723   in.name = KIT_SLICE_LIT("<api-session-asm>");
   1724   in.bytes.data = empty;
   1725   in.bytes.len = 0;
   1726   in.lang = KIT_LANG_ASM;
   1727 
   1728   EXPECT(kit_compile_session_new(c, &sopts, &s) == KIT_OK && s,
   1729          "compile session new failed");
   1730   if (!s) return;
   1731   EXPECT(kit_compile_session_compile(s, &in, &ob1) == KIT_OK && ob1,
   1732          "compile session first delta failed");
   1733   EXPECT(kit_compile_session_compile(s, &in, &ob2) == KIT_OK && ob2,
   1734          "compile session second delta failed");
   1735   kit_obj_builder_free(ob1);
   1736   kit_obj_builder_free(ob2);
   1737   kit_compile_session_free(s);
   1738 }
   1739 
   1740 static void exercise_cg_begin_end_two_objects(KitCompiler* c) {
   1741   KitCg* cg = NULL;
   1742   KitObjBuilder* ob1 = NULL;
   1743   KitObjBuilder* ob2 = NULL;
   1744   KitCodeOptions opts;
   1745 
   1746   memset(&opts, 0, sizeof(opts));
   1747   ob1 = new_obj(c);
   1748   ob2 = new_obj(c);
   1749   EXPECT(ob1 && ob2, "obj builder allocation failed for cg begin/end session");
   1750   EXPECT(kit_cg_new(c, &cg) == KIT_OK && cg, "cg session new failed");
   1751   if (cg && ob1) {
   1752     EXPECT(kit_cg_begin(cg, ob1, &opts) == KIT_OK,
   1753            "cg begin first object failed");
   1754     EXPECT(kit_cg_finish(cg, NULL) == KIT_OK, "cg finish first object failed");
   1755     EXPECT(kit_cg_detach(cg) == KIT_OK, "cg detach first object failed");
   1756   }
   1757   if (cg && ob2) {
   1758     EXPECT(kit_cg_begin(cg, ob2, &opts) == KIT_OK,
   1759            "cg begin second object failed");
   1760     EXPECT(kit_cg_finish(cg, NULL) == KIT_OK, "cg finish second object failed");
   1761     EXPECT(kit_cg_detach(cg) == KIT_OK, "cg detach second object failed");
   1762   }
   1763   kit_cg_free(cg);
   1764   kit_obj_builder_free(ob1);
   1765   kit_obj_builder_free(ob2);
   1766 }
   1767 
   1768 static void exercise_cg_free_does_not_finish(KitCompiler* c,
   1769                                              KitCgTypeId i32_ty) {
   1770   KitCodeOptions opts;
   1771   KitCgUnitOptions unit_opts;
   1772   KitObjBuilder* ob = NULL;
   1773   KitCg* cg = NULL;
   1774   KitCgFuncSig sig;
   1775   KitCgDecl decl;
   1776   KitCgSym sym;
   1777 
   1778   memset(&opts, 0, sizeof opts);
   1779   opts.opt_level = 1;
   1780   ob = new_obj(c);
   1781   EXPECT(ob != NULL, "no-finish obj builder allocation failed");
   1782   if (!ob) return;
   1783   EXPECT(kit_cg_new(c, &cg) == KIT_OK && cg, "no-finish cg new failed");
   1784   if (!cg) {
   1785     kit_obj_builder_free(ob);
   1786     return;
   1787   }
   1788   EXPECT(kit_cg_begin(cg, ob, &opts) == KIT_OK, "no-finish cg begin failed");
   1789   memset(&unit_opts, 0, sizeof unit_opts);
   1790   unit_opts.source_name = KIT_SLICE_LIT("cg_free_does_not_finish.c");
   1791   EXPECT(kit_cg_begin_unit(cg, &unit_opts) == KIT_OK,
   1792          "no-finish begin unit failed");
   1793 
   1794   memset(&sig, 0, sizeof sig);
   1795   {
   1796     KitCgFuncResult result;
   1797     memset(&result, 0, sizeof result);
   1798     result.type = i32_ty;
   1799     sig.result = result;
   1800     sig.call_conv = KIT_CG_CC_TARGET_C;
   1801 
   1802     memset(&decl, 0, sizeof decl);
   1803     decl.kind = KIT_CG_DECL_FUNC;
   1804     decl.linkage_name =
   1805         kit_sym_intern(c, KIT_SLICE_LIT("cg_free_does_not_finish"));
   1806     decl.display_name = decl.linkage_name;
   1807     decl.type = kit_cg_type_func(c, sig);
   1808     decl.sym.bind = KIT_SB_GLOBAL;
   1809     decl.sym.visibility = KIT_CG_VIS_DEFAULT;
   1810     sym = kit_cg_decl(cg, decl);
   1811   }
   1812   EXPECT(sym != KIT_CG_SYM_NONE, "no-finish decl failed");
   1813   kit_cg_func_begin(cg, sym);
   1814   kit_cg_push_int(cg, 42, i32_ty);
   1815   kit_cg_ret(cg);
   1816   kit_cg_func_end(cg);
   1817   EXPECT(kit_cg_end_unit(cg) == KIT_OK, "no-finish end unit failed");
   1818 
   1819   kit_cg_free(cg);
   1820   EXPECT(kit_obj_builder_finalize(ob) == KIT_OK,
   1821          "no-finish explicit object finalize failed");
   1822   EXPECT(text_size(c, ob) == 0,
   1823          "kit_cg_free must not lower optimized IR into the object");
   1824   kit_obj_builder_free(ob);
   1825 }
   1826 
   1827 int main(void) {
   1828   KitTargetSpec target;
   1829   KitCompiler* c;
   1830   KitCgTypeId void_ty;
   1831   KitCgTypeId i8_ty;
   1832   KitCgTypeId i32_ty;
   1833   KitCgTypeId i64_ty;
   1834   KitCgTypeId f64_ty;
   1835   KitCgTypeId va_list_ty;
   1836   KitCgTypeId ptr_i32;
   1837   KitCgTypeId array_i32;
   1838   KitCgTypeId huge_array_a;
   1839   KitCgTypeId huge_array_b;
   1840   KitCgFuncParam params[2];
   1841   KitCgFuncSig sig;
   1842   KitCgTypeId fn;
   1843   KitCgTypeInfo info;
   1844   KitCgTypeId rec;
   1845   KitCgTypeId rec_ex;
   1846   KitCgTypeId rec_decl;
   1847   KitCgTypeId rec_ptr;
   1848   KitCgTypeId rec_self_ptr;
   1849   KitCgTypeId rec_bad;
   1850   KitCgTypeId enm;
   1851   KitCgRecordDesc rdesc;
   1852   KitCgFieldDesc fields[2];
   1853   const KitCgRecordLayout* rlayout;
   1854   KitCgFieldLayout field_out;
   1855   KitCgEnumValue vals[2];
   1856   uint64_t field_off;
   1857 
   1858   kit_unit_init(&g_u);
   1859   target = kit_unit_target(KIT_ARCH_ARM_64, KIT_OS_LINUX, KIT_OBJ_ELF);
   1860 
   1861   c = NULL;
   1862   if (kit_unit_compiler_new(&g_u, target, &c) != KIT_OK || !c) {
   1863     fprintf(stderr, "compiler_new failed\n");
   1864     return 2;
   1865   }
   1866 
   1867   void_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID);
   1868   i8_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I8);
   1869   i32_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I32);
   1870   i64_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I64);
   1871   f64_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_F64);
   1872   va_list_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_VARARG_STATE);
   1873   EXPECT(void_ty != KIT_CG_TYPE_NONE, "void builtin id is none");
   1874   EXPECT(i8_ty != KIT_CG_TYPE_NONE, "i8 builtin id is none");
   1875   EXPECT(i32_ty != KIT_CG_TYPE_NONE, "i32 builtin id is none");
   1876   EXPECT(f64_ty != KIT_CG_TYPE_NONE, "f64 builtin id is none");
   1877   EXPECT(va_list_ty != KIT_CG_TYPE_NONE, "va_list builtin id is none");
   1878   EXPECT(void_ty != i32_ty && i32_ty != f64_ty, "builtin ids collide");
   1879   EXPECT(void_ty == 1u, "void builtin should be first direct id");
   1880   EXPECT(i8_ty == (KitCgTypeId)KIT_CG_BUILTIN_I8 + 1u,
   1881          "builtin id should be direct enum+1");
   1882   EXPECT(!kit_cg_type_is_void(c, KIT_CG_TYPE_NONE),
   1883          "invalid type id must not masquerade as void");
   1884   EXPECT(kit_cg_type_is_void(c, void_ty), "void builtin predicate failed");
   1885   EXPECT(!kit_cg_type_is_sized(c, void_ty), "void should not be sized");
   1886 
   1887   ptr_i32 = kit_cg_type_ptr(c, i32_ty, 0);
   1888   array_i32 = kit_cg_type_array(c, i32_ty, 4);
   1889   EXPECT(ptr_i32 != KIT_CG_TYPE_NONE, "ptr type failed");
   1890   EXPECT(array_i32 != KIT_CG_TYPE_NONE, "array type failed");
   1891   EXPECT(kit_cg_type_ptr(c, i32_ty, 0) == ptr_i32,
   1892          "ptr type id should be interned");
   1893   EXPECT(kit_cg_type_array(c, i32_ty, 4) == array_i32,
   1894          "array type id should be interned");
   1895   EXPECT(kit_cg_type_ptr(c, KIT_CG_TYPE_NONE, 0) == KIT_CG_TYPE_NONE,
   1896          "invalid pointer pointee should fail");
   1897   EXPECT(kit_cg_type_size(c, ptr_i32) == 8, "ptr size mismatch");
   1898   EXPECT(kit_cg_type_align(c, ptr_i32) == 8, "ptr align mismatch");
   1899   EXPECT(kit_cg_type_ptr_pointee(c, ptr_i32) == i32_ty, "ptr pointee mismatch");
   1900   EXPECT(kit_cg_type_array_elem(c, array_i32) == i32_ty, "array elem mismatch");
   1901   EXPECT(kit_cg_type_array_count(c, array_i32) == 4, "array count mismatch");
   1902   huge_array_a = kit_cg_type_array(c, i32_ty, (uint64_t)UINT32_MAX + 1u);
   1903   huge_array_b = kit_cg_type_array(c, i32_ty, 1);
   1904   EXPECT(huge_array_a == KIT_CG_TYPE_NONE,
   1905          "out-of-range array object should be rejected");
   1906   EXPECT(huge_array_b != KIT_CG_TYPE_NONE,
   1907          "small array after huge rejection should still work");
   1908 
   1909   EXPECT(kit_cg_type_resolve_alias(c, i32_ty) == i32_ty,
   1910          "storage identity should resolve to itself");
   1911   EXPECT(kit_cg_type_info(c, i32_ty, &info) == KIT_OK, "i32 info failed");
   1912   EXPECT(info.kind == KIT_CG_TYPE_INT && info.storage_id == i32_ty &&
   1913              info.layout.valid &&
   1914              info.layout.storage_kind == KIT_CG_STORAGE_INT &&
   1915              info.layout.scalar_width == 32,
   1916          "i32 info identity/layout mismatch");
   1917   EXPECT(kit_cg_type_info(c, ptr_i32, &info) == KIT_OK, "ptr info failed");
   1918   EXPECT(info.kind == KIT_CG_TYPE_PTR && info.storage_id == ptr_i32,
   1919          "ptr info should keep storage identity");
   1920   EXPECT(kit_cg_type_same_storage(c, i32_ty, i32_ty),
   1921          "type should share storage with itself");
   1922   EXPECT(!kit_cg_type_same_storage(c, ptr_i32, i32_ty),
   1923          "unrelated types should not share storage");
   1924 
   1925   memset(fields, 0, sizeof fields);
   1926   fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("a"));
   1927   fields[0].type = i32_ty;
   1928   fields[0].align_override = 0;
   1929   fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("b"));
   1930   fields[1].type = ptr_i32;
   1931   fields[1].align_override = 1;
   1932   memset(&rdesc, 0, sizeof rdesc);
   1933   rdesc.tag = kit_sym_intern(c, KIT_SLICE_LIT("R"));
   1934   rdesc.fields = fields;
   1935   rdesc.nfields = 2;
   1936   rec = kit_cg_type_record(c, &rdesc);
   1937   EXPECT(rec != KIT_CG_TYPE_NONE, "record type failed");
   1938   memset(&rdesc, 0, sizeof rdesc);
   1939   rdesc.tag = kit_sym_intern(c, KIT_SLICE_LIT("Bad"));
   1940   EXPECT(kit_cg_type_record(c, &rdesc) != KIT_CG_TYPE_NONE,
   1941          "empty record type failed");
   1942   EXPECT(kit_cg_type_kind(c, rec) == KIT_CG_TYPE_RECORD,
   1943          "record kind mismatch");
   1944   EXPECT(kit_cg_type_record_nfields(c, rec) == 2,
   1945          "record field count mismatch");
   1946   rlayout = kit_cg_type_record_layout(c, rec);
   1947   EXPECT(rlayout && rlayout->nfields > 1, "record field query failed");
   1948   field_out = rlayout->fields[1];
   1949   field_off = field_out.offset;
   1950   EXPECT(field_out.name == fields[1].name && field_out.type == ptr_i32,
   1951          "record field data mismatch");
   1952   EXPECT(field_off == 4, "record field offset mismatch");
   1953 
   1954   memset(fields, 0, sizeof fields);
   1955   fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("lo"));
   1956   fields[0].type = i32_ty;
   1957   fields[0].flags = KIT_CG_FIELD_BITFIELD;
   1958   fields[0].bit_width = 5;
   1959   fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("hi"));
   1960   fields[1].type = i32_ty;
   1961   fields[1].flags = KIT_CG_FIELD_BITFIELD;
   1962   fields[1].bit_width = 3;
   1963   memset(&rdesc, 0, sizeof rdesc);
   1964   rdesc.tag = kit_sym_intern(c, KIT_SLICE_LIT("BF"));
   1965   rdesc.fields = fields;
   1966   rdesc.nfields = 2;
   1967   rec_ex = kit_cg_type_record(c, &rdesc);
   1968   EXPECT(rec_ex != KIT_CG_TYPE_NONE, "bit-field record type failed");
   1969   EXPECT(kit_cg_type_size(c, rec_ex) == 4, "bit-field record size mismatch");
   1970   rlayout = kit_cg_type_record_layout(c, rec_ex);
   1971   EXPECT(rlayout && rlayout->nfields > 1, "bit-field record query failed");
   1972   field_out = rlayout->fields[1];
   1973   field_off = field_out.offset;
   1974   EXPECT(field_off == 0 && field_out.bit_offset == 5 &&
   1975              field_out.bit_width == 3 && field_out.bit_storage_size == 4,
   1976          "bit-field metadata mismatch");
   1977 
   1978   memset(fields, 0, sizeof fields);
   1979   fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("a"));
   1980   fields[0].type = i32_ty;
   1981   fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("b"));
   1982   fields[1].type = ptr_i32;
   1983   fields[1].align_override = 1;
   1984   memset(&rdesc, 0, sizeof rdesc);
   1985   rdesc.tag = kit_sym_intern(c, KIT_SLICE_LIT("U"));
   1986   rdesc.fields = fields;
   1987   rdesc.nfields = 2;
   1988   rdesc.is_union = 1;
   1989   rdesc.align_override = 16;
   1990   rec_ex = kit_cg_type_record(c, &rdesc);
   1991   EXPECT(rec_ex != KIT_CG_TYPE_NONE, "record desc type failed");
   1992   EXPECT(kit_cg_type_size(c, rec_ex) == 16, "record desc size mismatch");
   1993   EXPECT(kit_cg_type_align(c, rec_ex) == 16, "record desc align mismatch");
   1994   rlayout = kit_cg_type_record_layout(c, rec_ex);
   1995   EXPECT(rlayout && rlayout->nfields > 1, "record desc field query failed");
   1996   field_out = rlayout->fields[1];
   1997   field_off = field_out.offset;
   1998   EXPECT(field_off == 0, "union field offset mismatch");
   1999 
   2000   rec_decl =
   2001       kit_cg_type_record_decl(c, kit_sym_intern(c, KIT_SLICE_LIT("Node")), 0);
   2002   EXPECT(rec_decl != KIT_CG_TYPE_NONE, "record decl failed");
   2003   EXPECT(kit_cg_type_kind(c, rec_decl) == KIT_CG_TYPE_RECORD,
   2004          "record decl kind mismatch");
   2005   EXPECT(!kit_cg_type_is_complete(c, rec_decl),
   2006          "fresh record decl should be incomplete");
   2007   EXPECT(!kit_cg_type_is_sized(c, rec_decl),
   2008          "fresh record decl should be unsized");
   2009   EXPECT(kit_cg_type_record_layout(c, rec_decl) == NULL,
   2010          "incomplete record should not expose fields");
   2011   rec_ptr = kit_cg_type_ptr(c, rec_decl, 0);
   2012   EXPECT(rec_ptr != KIT_CG_TYPE_NONE,
   2013          "pointer to incomplete record should be legal");
   2014   EXPECT(kit_cg_type_array(c, rec_decl, 1) == KIT_CG_TYPE_NONE,
   2015          "array of incomplete record should fail");
   2016   memset(fields, 0, sizeof fields);
   2017   fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("next"));
   2018   fields[0].type = rec_ptr;
   2019   memset(&rdesc, 0, sizeof rdesc);
   2020   rdesc.tag = kit_cg_type_record_tag(c, rec_decl);
   2021   rdesc.fields = fields;
   2022   rdesc.nfields = 1;
   2023   EXPECT(kit_cg_type_record_complete(c, rec_decl, &rdesc) == KIT_OK,
   2024          "record completion with self pointer failed");
   2025   EXPECT(kit_cg_type_is_complete(c, rec_decl),
   2026          "completed record should be complete");
   2027   EXPECT(kit_cg_type_is_sized(c, rec_decl), "completed record should be sized");
   2028   EXPECT(kit_cg_type_record_complete(c, rec_decl, &rdesc) == KIT_INVALID,
   2029          "record completion should be one-shot");
   2030 
   2031   rec_bad = kit_cg_type_record_decl(
   2032       c, kit_sym_intern(c, KIT_SLICE_LIT("ByValueSelf")), 0);
   2033   memset(fields, 0, sizeof fields);
   2034   fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("self"));
   2035   fields[0].type = rec_bad;
   2036   memset(&rdesc, 0, sizeof rdesc);
   2037   rdesc.tag = kit_cg_type_record_tag(c, rec_bad);
   2038   rdesc.fields = fields;
   2039   rdesc.nfields = 1;
   2040   EXPECT(kit_cg_type_record_complete(c, rec_bad, &rdesc) == KIT_INVALID,
   2041          "recursive by-value record should fail");
   2042   rec_self_ptr = kit_cg_type_ptr(c, rec_bad, 0);
   2043   EXPECT(rec_self_ptr != KIT_CG_TYPE_NONE,
   2044          "pointer to failed incomplete record should still be legal");
   2045 
   2046   vals[0].name = kit_sym_intern(c, KIT_SLICE_LIT("A"));
   2047   vals[0].value = 1;
   2048   vals[1].name = kit_sym_intern(c, KIT_SLICE_LIT("B"));
   2049   vals[1].value = 2;
   2050   enm = kit_cg_type_enum(c, kit_sym_intern(c, KIT_SLICE_LIT("E")),
   2051                          KIT_CG_TYPE_NONE, vals, 2);
   2052   EXPECT(enm != KIT_CG_TYPE_NONE, "enum type failed");
   2053   /* Enumerators must be preserved so debug info can emit DW_TAG_enumerator
   2054    * children rather than collapsing the enum to a bare integer. */
   2055   EXPECT(kit_cg_type_enum_nvalues(c, enm) == 2,
   2056          "enum should preserve its enumerator count");
   2057   {
   2058     KitCgEnumValue ev;
   2059     EXPECT(kit_cg_type_enum_value(c, enm, 1, &ev) == KIT_OK &&
   2060                ev.name == vals[1].name && ev.value == 2,
   2061            "enum should preserve enumerator name/value pairs");
   2062   }
   2063   /* An enum with an explicit integer underlying type must construct and retain
   2064    * that operational base exactly. Source spellings now travel through the
   2065    * debug type channel rather than wrapper type ids. */
   2066   {
   2067     KitCgTypeId enm_u = kit_cg_type_enum(
   2068         c, kit_sym_intern(c, KIT_SLICE_LIT("EU")), i8_ty, vals, 2);
   2069     EXPECT(enm_u != KIT_CG_TYPE_NONE,
   2070            "enum over an explicit integer underlying type should construct");
   2071     EXPECT(kit_cg_type_enum_base(c, enm_u) == i8_ty,
   2072            "enum should retain its explicit underlying type id");
   2073     EXPECT(kit_cg_type_int_width(c, enm_u) == 8,
   2074            "enum width should follow its explicit underlying type");
   2075   }
   2076 
   2077   memset(params, 0, sizeof(params));
   2078   params[0].type = i32_ty;
   2079   params[1].type = ptr_i32;
   2080   memset(&sig, 0, sizeof(sig));
   2081   KitCgFuncResult sig_result;
   2082   memset(&sig_result, 0, sizeof sig_result);
   2083   sig_result.type = i64_ty;
   2084   sig.result = sig_result;
   2085   sig.params = params;
   2086   sig.nparams = 2;
   2087   sig.abi_variadic = 1;
   2088   sig.call_conv = KIT_CG_CC_TARGET_C;
   2089   fn = kit_cg_type_func(c, sig);
   2090   EXPECT(fn != KIT_CG_TYPE_NONE, "function type failed");
   2091   EXPECT(kit_cg_type_func(c, sig) == fn, "function type id should be interned");
   2092   EXPECT(kit_cg_type_func_result(c, fn).type == i64_ty,
   2093          "function return mismatch");
   2094   EXPECT(kit_cg_type_func_nparams(c, fn) == 2, "function param count mismatch");
   2095   EXPECT(kit_cg_type_func_param(c, fn, 1).type == ptr_i32,
   2096          "function param mismatch");
   2097   memset(&sig, 0, sizeof sig);
   2098   sig.result.type = void_ty;
   2099   fn = kit_cg_type_func(c, sig);
   2100   EXPECT(fn != KIT_CG_TYPE_NONE, "void function type failed");
   2101   EXPECT(kit_cg_type_func_result(c, fn).type == void_ty,
   2102          "void function result should use void builtin");
   2103   EXPECT(!kit_cg_func_result_has_value(c, kit_cg_type_func_result(c, fn)),
   2104          "void function should not have a value result");
   2105   memset(&sig, 0, sizeof sig);
   2106   EXPECT(kit_cg_type_func(c, sig) == KIT_CG_TYPE_NONE,
   2107          "function result NONE should be rejected");
   2108   sig.nparams = 70000;
   2109   EXPECT(kit_cg_type_func(c, sig) == KIT_CG_TYPE_NONE,
   2110          "oversized function param list should fail");
   2111 
   2112   exercise_cg_handles(c, i32_ty, 0);
   2113   exercise_cg_handles(c, i32_ty, 1);
   2114   exercise_cg_scalar_local(c, i32_ty, 0);
   2115   exercise_cg_scalar_local(c, i32_ty, 1);
   2116   exercise_cg_late_local_addr(c, i32_ty, 0);
   2117   exercise_cg_late_local_addr(c, i32_ty, 1);
   2118   exercise_cg_data_entsize(c, i8_ty);
   2119   exercise_cg_debug_global_object(c, i32_ty);
   2120   exercise_cg_literal_folds(c, i32_ty);
   2121   exercise_cg_constfold_phases(c, i32_ty, i8_ty);
   2122   exercise_cg_memop_constfold_shape(c, i32_ty, i64_ty, ptr_i32);
   2123   exercise_cg_slot_lang_facts(c, i32_ty);
   2124   exercise_cg_field_at_store_keep(c, i32_ty, rec);
   2125   exercise_cg_memory_mismatch_diags(c, i32_ty, i64_ty, rec);
   2126   exercise_compile_session_two_deltas(c);
   2127   exercise_cg_begin_end_two_objects(c);
   2128   exercise_cg_free_does_not_finish(c, i32_ty);
   2129 
   2130   kit_compiler_free(c);
   2131   kit_unit_summary(&g_u, "cg_api_test");
   2132   return kit_unit_status(&g_u);
   2133 }