kit

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

parse_init.c (57423B)


      1 /* parse_init.c — runtime and static-storage initializers.
      2  *
      3  * Covers §6.7.9 (initializers):
      4  *   - Runtime aggregate/scalar initializers (init_at, init_elided,
      5  *     init_struct_fields, init_string_at, parse_designator_chain,
      6  *     push_subobject_lv, emit_copy_leaf, emit_walk_copy,
      7  *     emit_struct_copy_into_slot, zero_init_at)
      8  *   - Static-storage object definition (parse_static_init_at,
      9  *     parse_static_string_at, parse_static_const, encode_int_le,
     10  *     pick_object_section, define_static_object, srl_push)
     11  */
     12 
     13 #include "parse/parse_priv.h"
     14 
     15 /* ============================================================
     16  * File-local helpers
     17  * ============================================================ */
     18 
     19 static SrcLoc tok_loc_init(const Tok* t) { return t->loc; }
     20 
     21 static CKw ident_kw_init(const Parser* p, Sym name) {
     22   return ident_kw_inline(p, name);
     23 }
     24 
     25 static const Type* init_field_type_at(const Type* ty, u16 i) {
     26   const Field* f = &ty->rec.fields[i];
     27   return f->type;
     28 }
     29 
     30 static u32 init_field_offset_at(const ABIRecordLayout* L, u16 i) {
     31   return L->fields[i].offset;
     32 }
     33 
     34 /* True if `ty` is char/signed char/unsigned char. */
     35 int is_char_kind(const Type* ty) {
     36   if (!ty) return 0;
     37   return ty->kind == TY_CHAR || ty->kind == TY_SCHAR || ty->kind == TY_UCHAR;
     38 }
     39 
     40 /* Decode the string token at p->cur without advancing. Returns a heap-
     41  * allocated byte buffer (caller frees) and writes length (including NUL)
     42  * to *nlen_out. */
     43 static u8* peek_string_bytes(Parser* p, size_t* nlen_out) {
     44   Tok t = p->cur;
     45   if (t.kind != TOK_STR) perr(p, "internal: peek_string_bytes on non-string");
     46   return decode_string_literal(p, &t, nlen_out);
     47 }
     48 
     49 static u64 decode_lit_unit_le(const u8* src, u32 size) {
     50   u64 v = 0;
     51   u32 i;
     52   if (size > 8u) size = 8u;
     53   for (i = 0; i < size; ++i) v |= (u64)src[i] << (8u * i);
     54   return v;
     55 }
     56 
     57 /* ============================================================
     58  * Runtime initializers
     59  * ============================================================ */
     60 
     61 /* Forward declaration for mutual recursion. */
     62 void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
     63              const Type* ty);
     64 
     65 typedef struct InitDesignatorCont {
     66   const Type* parent_ty;
     67   u32 parent_offset;
     68   u32 next_index;
     69 } InitDesignatorCont;
     70 
     71 static void init_aggregate_remainder(Parser* p, FrameSlot slot,
     72                                      const Type* arr_ty, u32 offset,
     73                                      const Type* ty, u32 start_index);
     74 
     75 static void replay_recorded_initializer_expr(Parser* p) {
     76   if (p->replay_len == 0)
     77     perr(p, "internal: empty initializer expression replay");
     78   p->cur = p->replay[0];
     79   p->replay_pos = 1;
     80   p->replay_active = 1;
     81   p->has_next = 0;
     82 }
     83 
     84 static void record_initializer_expr_for_replay(Parser* p) {
     85   u32 len = 0;
     86   u32 cap = 0;
     87   Tok* buf = NULL;
     88   int paren_depth = 0;
     89   int brack_depth = 0;
     90   int brace_depth = 0;
     91 
     92   for (;;) {
     93     if (len == cap) {
     94       u32 new_cap = cap ? cap * 2u : 16u;
     95       Tok* nb = arena_array(p->pool->arena, Tok, new_cap);
     96       if (!nb) perr(p, "out of memory recording initializer expression");
     97       if (buf && len) memcpy(nb, buf, len * sizeof(*buf));
     98       buf = nb;
     99       cap = new_cap;
    100     }
    101     buf[len++] = p->cur;
    102 
    103     if (p->cur.kind == TOK_EOF) break;
    104     if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0 &&
    105         (is_punct(&p->cur, ',') || is_punct(&p->cur, '}'))) {
    106       break;
    107     }
    108 
    109     if (is_punct(&p->cur, '('))
    110       ++paren_depth;
    111     else if (is_punct(&p->cur, ')'))
    112       --paren_depth;
    113     else if (is_punct(&p->cur, '['))
    114       ++brack_depth;
    115     else if (is_punct(&p->cur, ']'))
    116       --brack_depth;
    117     else if (is_punct(&p->cur, '{'))
    118       ++brace_depth;
    119     else if (is_punct(&p->cur, '}'))
    120       --brace_depth;
    121 
    122     advance(p);
    123   }
    124 
    125   p->replay = buf;
    126   p->replay_cap = cap;
    127   p->replay_len = len;
    128   replay_recorded_initializer_expr(p);
    129 }
    130 
    131 static int try_init_aggregate_from_expr(Parser* p, FrameSlot slot,
    132                                         const Type* arr_ty, u32 offset,
    133                                         const Type* ty) {
    134   const Type* expr_ty;
    135   u32 save_sp;
    136   int compatible;
    137 
    138   if (!ty || (ty->kind != TY_STRUCT && ty->kind != TY_UNION)) return 0;
    139   if (is_punct(&p->cur, '{') || is_punct(&p->cur, '.') ||
    140       is_punct(&p->cur, '[')) {
    141     return 0;
    142   }
    143 
    144   record_initializer_expr_for_replay(p);
    145 
    146   save_sp = p->cg_type_sp;
    147   pcg_codegen_suppress_push(p);
    148   parse_assign_expr(p);
    149   expr_ty = pcg_top_type(p);
    150   compatible =
    151       type_compatible(type_unqual(p->pool, ty), type_unqual(p->pool, expr_ty));
    152   p->cg_type_sp = save_sp;
    153   pcg_codegen_suppress_pop(p);
    154 
    155   replay_recorded_initializer_expr(p);
    156   if (!compatible) return 0;
    157 
    158   parse_assign_expr(p);
    159   if (!type_compatible(type_unqual(p->pool, ty),
    160                        type_unqual(p->pool, pcg_top_type(p)))) {
    161     perr(p, "incompatible aggregate initializer");
    162   }
    163   emit_struct_copy_into_slot(p, slot, arr_ty, offset, ty);
    164   return 1;
    165 }
    166 
    167 /* Push the lvalue of a sub-object at byte offset `offset` within the array
    168  * local `slot` (whose type is `arr_ty`), with element type `elem_ty`. */
    169 void push_subobject_lv(Parser* p, FrameSlot slot, const Type* arr_ty,
    170                        u32 offset, const Type* elem_ty) {
    171   pcg_push_local_typed(p, slot, arr_ty);
    172   /* Fold the byte offset onto the local lvalue's aux; the next
    173    * load/store/addr will bake it into the memop's ea.offset. The result is an
    174    * lvalue of elem_ty backed by the frame slot. */
    175   pcg_lv_member(p, (i64)offset, elem_ty, /*bf_off=*/0, /*bf_w=*/0, /*ss=*/0);
    176 }
    177 
    178 static void zero_object_bytes_at(Parser* p, FrameSlot slot, const Type* arr_ty,
    179                                  u32 offset, const Type* ty) {
    180   KitCgMemAccess access = pcg_mem(p, ty);
    181   push_subobject_lv(p, slot, arr_ty, offset, ty);
    182   pcg_addr(p);
    183   if (pcg_emit_enabled(p)) {
    184     kit_cg_memset(p->cg, 0, c_abi_sizeof(p->abi, ty), access);
    185   }
    186   pcg_drop_type(p);
    187 }
    188 
    189 static void push_record_field_lv(Parser* p, FrameSlot slot, const Type* arr_ty,
    190                                  u32 rec_offset, const Type* rec_ty,
    191                                  u32 field_index) {
    192   const Field* f = &rec_ty->rec.fields[field_index];
    193   const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, rec_ty);
    194   u32 foff = L->fields[field_index].offset;
    195   u16 bf_off = 0;
    196   u16 bf_w = 0;
    197   u32 bf_ss = 0;
    198   push_subobject_lv(p, slot, arr_ty, rec_offset, rec_ty);
    199   if (f->flags & FIELD_BITFIELD) {
    200     bf_off = L->fields[field_index].bit_offset;
    201     bf_w = L->fields[field_index].bit_width;
    202     bf_ss = L->fields[field_index].storage_size;
    203   }
    204   pcg_lv_member(p, (i64)foff, f->type, bf_off, bf_w, bf_ss);
    205 }
    206 
    207 /* Emit a load+store for one scalar leaf. */
    208 static void emit_copy_leaf(Parser* p, FrameSlot dst_slot,
    209                            const Type* dst_arr_ty, u32 dst_off,
    210                            FrameSlot src_ptr_slot, const Type* src_ptr_ty,
    211                            u32 src_off, const Type* leaf_ty) {
    212   push_subobject_lv(p, dst_slot, dst_arr_ty, dst_off, leaf_ty);
    213   pcg_push_local_typed(p, src_ptr_slot, src_ptr_ty);
    214   pcg_load(p);
    215   /* TOS is now a pointer rvalue (the loaded source pointer). Retag as a
    216    * C-language lvalue with POINTER_RV base, then fold the source byte offset
    217    * onto its aux. The next pcg_load consumes the EA into the memop. */
    218   pcg_deref(p, leaf_ty);
    219   pcg_lv_member(p, (i64)src_off, leaf_ty, 0, 0, 0);
    220   pcg_load(p);
    221   pcg_store(p);
    222   pcg_drop(p);
    223 }
    224 
    225 /* Walk a (possibly nested) aggregate, emitting a leaf load+store for each
    226  * scalar member. */
    227 static void emit_walk_copy(Parser* p, FrameSlot dst_slot,
    228                            const Type* dst_arr_ty, u32 dst_off,
    229                            FrameSlot src_ptr_slot, const Type* src_ptr_ty,
    230                            u32 src_off, const Type* ty) {
    231   if (ty->kind == TY_STRUCT) {
    232     const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
    233     for (u16 i = 0; i < ty->rec.nfields; ++i) {
    234       const Field* f = &ty->rec.fields[i];
    235       if (f->flags & FIELD_BITFIELD) continue;
    236       const Type* fty = init_field_type_at(ty, i);
    237       u32 foff = init_field_offset_at(L, i);
    238       emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + foff, src_ptr_slot,
    239                      src_ptr_ty, src_off + foff, fty);
    240     }
    241     return;
    242   }
    243   if (ty->kind == TY_ARRAY) {
    244     u32 esz = c_abi_sizeof(p->abi, ty->arr.elem);
    245     for (u32 i = 0; i < ty->arr.count; ++i) {
    246       emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + i * esz, src_ptr_slot,
    247                      src_ptr_ty, src_off + i * esz, ty->arr.elem);
    248     }
    249     return;
    250   }
    251   if (ty->kind == TY_UNION) {
    252     u32 sz = c_abi_sizeof(p->abi, ty);
    253     const Type* uchar_ty = type_prim(p->pool, TY_UCHAR);
    254     for (u32 i = 0; i < sz; ++i) {
    255       emit_copy_leaf(p, dst_slot, dst_arr_ty, dst_off + i, src_ptr_slot,
    256                      src_ptr_ty, src_off + i, uchar_ty);
    257     }
    258     return;
    259   }
    260   emit_copy_leaf(p, dst_slot, dst_arr_ty, dst_off, src_ptr_slot, src_ptr_ty,
    261                  src_off, ty);
    262 }
    263 
    264 /* Source struct/union value is on top of the cg stack as an lvalue.
    265  * Spill its address into a fresh pointer slot, then walk the type and
    266  * copy each scalar leaf into the destination sub-object. */
    267 void emit_struct_copy_into_slot(Parser* p, FrameSlot dst_slot,
    268                                 const Type* dst_arr_ty, u32 dst_off,
    269                                 const Type* ty) {
    270   const Type* ptr_ty = type_ptr(p->pool, ty);
    271   FrameSlotDesc fsd;
    272   FrameSlot src_ptr_slot;
    273   pcg_addr(p);
    274   memset(&fsd, 0, sizeof fsd);
    275   fsd.type = ptr_ty;
    276   fsd.size = c_abi_sizeof(p->abi, ptr_ty);
    277   fsd.align = c_abi_alignof(p->abi, ptr_ty);
    278   fsd.kind = FS_LOCAL;
    279   fsd.flags = FSF_NONE;
    280   src_ptr_slot = pcg_local(p, &fsd);
    281   pcg_push_local_typed(p, src_ptr_slot, ptr_ty);
    282   pcg_swap(p);
    283   pcg_store(p);
    284   pcg_drop(p);
    285   emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off, src_ptr_slot, ptr_ty, 0, ty);
    286 }
    287 
    288 /* Recursively zero-initialize the sub-object at `offset` of type `ty`. */
    289 static void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty,
    290                          u32 offset, const Type* ty) {
    291   if (ty->kind == TY_ARRAY) {
    292     u32 esz = c_abi_sizeof(p->abi, ty->arr.elem);
    293     for (u32 i = 0; i < ty->arr.count; ++i) {
    294       zero_init_at(p, slot, arr_ty, offset + i * esz, ty->arr.elem);
    295     }
    296     return;
    297   }
    298   if (ty->kind == TY_STRUCT) {
    299     const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
    300     for (u16 i = 0; i < ty->rec.nfields; ++i) {
    301       const Field* f = &ty->rec.fields[i];
    302       if (f->flags & FIELD_ZERO_WIDTH) continue;
    303       if (f->flags & FIELD_BITFIELD) {
    304         push_record_field_lv(p, slot, arr_ty, offset, ty, i);
    305         pcg_push_int(p, 0, f->type);
    306         pcg_store(p);
    307         pcg_drop(p);
    308         continue;
    309       }
    310       {
    311         const Type* fty = init_field_type_at(ty, i);
    312         u32 foff = init_field_offset_at(L, i);
    313         zero_init_at(p, slot, arr_ty, offset + foff, fty);
    314       }
    315     }
    316     return;
    317   }
    318   if (ty->kind == TY_UNION) {
    319     if (ty->rec.nfields > 0) {
    320       const Field* f = &ty->rec.fields[0];
    321       if (!(f->flags & FIELD_BITFIELD)) {
    322         zero_init_at(p, slot, arr_ty, offset, f->type);
    323       }
    324     }
    325     return;
    326   }
    327   push_subobject_lv(p, slot, arr_ty, offset, ty);
    328   pcg_push_int(p, 0, ty);
    329   pcg_store(p);
    330   pcg_drop(p);
    331 }
    332 
    333 static void init_field_at(Parser* p, FrameSlot slot, const Type* arr_ty,
    334                           u32 rec_offset, const Type* rec_ty, u32 field_index) {
    335   const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, rec_ty);
    336   const Field* f = &rec_ty->rec.fields[field_index];
    337   if (f->flags & FIELD_ZERO_WIDTH) return;
    338   if (f->flags & FIELD_BITFIELD) {
    339     push_record_field_lv(p, slot, arr_ty, rec_offset, rec_ty, field_index);
    340     parse_assign_expr(p);
    341     to_rvalue(p);
    342     {
    343       const Type* rhs = pcg_top_type(p);
    344       CSemCheck chk =
    345           c_sem_check_assignment(p->pool, f->type, rhs, C_SEM_ASSIGN_INIT);
    346       if (!chk.ok) perr(p, "%.*s", KIT_SLICE_ARG(kit_slice_cstr(chk.message)));
    347     }
    348     coerce_top_to_lvalue(p);
    349     pcg_store(p);
    350     pcg_drop(p);
    351     return;
    352   }
    353   init_at(p, slot, arr_ty, rec_offset + L->fields[field_index].offset, f->type);
    354 }
    355 
    356 /* Emit byte stores for a string literal initializing a char-array sub-object.
    357  */
    358 static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty,
    359                            u32 offset, const Type* elem_ty, u32 count) {
    360   size_t n = 0;
    361   u8* bytes = peek_string_bytes(p, &n);
    362   u32 elem_size = c_abi_sizeof(p->abi, elem_ty);
    363   size_t elems = elem_size ? n / elem_size : 0;
    364   size_t copy = elems;
    365   size_t i;
    366   if (copy > count) copy = count;
    367   for (i = 0; i < copy; ++i) {
    368     push_subobject_lv(p, slot, arr_ty, offset + (u32)i * elem_size, elem_ty);
    369     pcg_push_int(p, (i64)decode_lit_unit_le(bytes + i * elem_size, elem_size),
    370                  elem_ty);
    371     pcg_store(p);
    372     pcg_drop(p);
    373   }
    374   for (; i < count; ++i) {
    375     push_subobject_lv(p, slot, arr_ty, offset + (u32)i * elem_size, elem_ty);
    376     pcg_push_int(p, 0, elem_ty);
    377     pcg_store(p);
    378     pcg_drop(p);
    379   }
    380   kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
    381                                          bytes, 0);
    382   advance(p); /* consume TOK_STR */
    383 }
    384 
    385 /* Parse a designator chain (`[const]` and `.ident` repeats) ending at `=`. */
    386 static void parse_designator_chain(Parser* p, const Type* outer_ty,
    387                                    u32 outer_offset, const Type** sub_ty_out,
    388                                    u32* sub_offset_out, u32* top_index_out,
    389                                    InitDesignatorCont* cont_out) {
    390   const Type* cur_ty = outer_ty;
    391   u32 cur_off = outer_offset;
    392   int first = 1;
    393   InitDesignatorCont cont;
    394   memset(&cont, 0, sizeof cont);
    395   for (;;) {
    396     if (is_punct(&p->cur, '[')) {
    397       i64 idx;
    398       u32 esz;
    399       SrcLoc cloc = tok_loc_init(&p->cur);
    400       const Type* parent_ty = cur_ty;
    401       u32 parent_off = cur_off;
    402       advance(p);
    403       idx = eval_const_int(p, cloc);
    404       expect_punct(p, ']', "']' after designator index");
    405       if (!cur_ty || cur_ty->kind != TY_ARRAY) {
    406         perr(p, "array designator on non-array");
    407       }
    408       if (idx < 0 || (u32)idx >= cur_ty->arr.count) {
    409         perr(p, "array designator index out of range");
    410       }
    411       esz = c_abi_sizeof(p->abi, cur_ty->arr.elem);
    412       cur_off += (u32)idx * esz;
    413       cur_ty = cur_ty->arr.elem;
    414       cont.parent_ty = parent_ty;
    415       cont.parent_offset = parent_off;
    416       cont.next_index = (u32)idx + 1u;
    417       if (first) *top_index_out = (u32)idx;
    418       first = 0;
    419     } else if (is_punct(&p->cur, '.')) {
    420       Sym fname;
    421       const Type* fty;
    422       u32 foff;
    423       const Field* ff;
    424       u16 fi;
    425       u32 selected_index = 0;
    426       int have_selected_index = 0;
    427       const Type* parent_ty = cur_ty;
    428       u32 parent_off = cur_off;
    429       advance(p);
    430       if (p->cur.kind != TOK_IDENT ||
    431           ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
    432         perr(p, "expected field name after '.'");
    433       }
    434       fname = p->cur.v.ident;
    435       advance(p);
    436       if (!cur_ty || (cur_ty->kind != TY_STRUCT && cur_ty->kind != TY_UNION)) {
    437         perr(p, "field designator on non-record type");
    438       }
    439       if (!find_field(p->abi, p->pool, cur_ty, fname, &fty, &foff, &ff)) {
    440         perr(p, "no such field in designator");
    441       }
    442       cur_off += foff;
    443       for (fi = 0; fi < cur_ty->rec.nfields; ++fi) {
    444         const Field* g = &cur_ty->rec.fields[fi];
    445         if (g->name == fname && fname != 0) {
    446           selected_index = fi;
    447           have_selected_index = 1;
    448           if (first) {
    449             *top_index_out = fi;
    450           }
    451           break;
    452         }
    453         if ((g->flags & FIELD_ANON) &&
    454             (g->type->kind == TY_STRUCT || g->type->kind == TY_UNION)) {
    455           const Type* tmp_ty;
    456           u32 tmp_off;
    457           const Field* tmp_f;
    458           if (find_field(p->abi, p->pool, g->type, fname, &tmp_ty, &tmp_off,
    459                          &tmp_f)) {
    460             selected_index = fi;
    461             have_selected_index = 1;
    462             if (first) {
    463               *top_index_out = fi;
    464             }
    465             break;
    466           }
    467         }
    468       }
    469       if (have_selected_index) {
    470         cont.parent_ty = parent_ty;
    471         cont.parent_offset = parent_off;
    472         cont.next_index = selected_index + 1u;
    473       }
    474       cur_ty = fty;
    475       first = 0;
    476     } else {
    477       break;
    478     }
    479   }
    480   if (first) perr(p, "internal: empty designator chain");
    481   expect_punct(p, '=', "'=' after designator");
    482   *sub_ty_out = cur_ty;
    483   *sub_offset_out = cur_off;
    484   if (cont_out) *cont_out = cont;
    485 }
    486 
    487 static int aggregate_has_index(const Type* ty, u32 index) {
    488   if (!ty) return 0;
    489   if (ty->kind == TY_ARRAY) return index < ty->arr.count;
    490   if (ty->kind == TY_STRUCT) return index < ty->rec.nfields;
    491   return 0;
    492 }
    493 
    494 static int designator_continues_inside(Parser* p, const Type* outer_ty,
    495                                        u32 outer_offset, const Type* top_ty,
    496                                        u32 top_offset,
    497                                        const InitDesignatorCont* cont) {
    498   u32 top_size;
    499   if (!cont || !cont->parent_ty) return 0;
    500   if (cont->parent_ty == outer_ty && cont->parent_offset == outer_offset)
    501     return 0;
    502   if (!aggregate_has_index(cont->parent_ty, cont->next_index)) return 0;
    503   top_size = c_abi_sizeof(p->abi, top_ty);
    504   return cont->parent_offset >= top_offset &&
    505          cont->parent_offset - top_offset <= top_size;
    506 }
    507 
    508 static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
    509                               u32 offset, const Type* ty, u32 start_field,
    510                               int braced) {
    511   const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
    512   u32 i = start_field;
    513   u32 zero_lo = start_field;
    514   /* A braced list may carry designators that re-target any field, including a
    515    * field earlier than one already seen, so the running position `i` does not
    516    * bound the loop — only '}'/EOF (or, for an unbraced nested list, the field
    517    * count) terminates it. */
    518   for (;;) {
    519     if (braced) {
    520       if (is_punct(&p->cur, '}') || p->cur.kind == TOK_EOF) break;
    521     } else if (i >= ty->rec.nfields) {
    522       break;
    523     }
    524     if (braced && is_punct(&p->cur, '.')) {
    525       const Type* sub_ty;
    526       u32 sub_off;
    527       u32 top_idx = 0;
    528       InitDesignatorCont cont;
    529       parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, &cont);
    530       while (zero_lo < top_idx) {
    531         const Field* zf = &ty->rec.fields[zero_lo];
    532         if (zf->flags & FIELD_BITFIELD) {
    533           if (!(zf->flags & FIELD_ZERO_WIDTH)) {
    534             push_record_field_lv(p, slot, arr_ty, offset, ty, zero_lo);
    535             pcg_push_int(p, 0, zf->type);
    536             pcg_store(p);
    537             pcg_drop(p);
    538           }
    539         } else {
    540           u32 zoff = offset + L->fields[zero_lo].offset;
    541           zero_init_at(p, slot, arr_ty, zoff, zf->type);
    542         }
    543         ++zero_lo;
    544       }
    545       init_at(p, slot, arr_ty, sub_off, sub_ty);
    546       {
    547         const Field* top_f = &ty->rec.fields[top_idx];
    548         u32 top_off = offset + L->fields[top_idx].offset;
    549         if (designator_continues_inside(p, ty, offset, top_f->type, top_off,
    550                                         &cont) &&
    551             accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
    552           init_aggregate_remainder(p, slot, arr_ty, cont.parent_offset,
    553                                    cont.parent_ty, cont.next_index);
    554         }
    555       }
    556       i = top_idx;
    557       if (zero_lo <= top_idx) zero_lo = top_idx + 1;
    558       goto next_item_struct;
    559     }
    560     if (i >= ty->rec.nfields) {
    561       /* Excess positional initializer with no designator to place it; stop and
    562        * let the caller diagnose the missing '}'. */
    563       break;
    564     }
    565     init_field_at(p, slot, arr_ty, offset, ty, i);
    566     if (zero_lo <= i) zero_lo = i + 1;
    567     if (!braced) {
    568       ++i;
    569       break;
    570     }
    571   next_item_struct:
    572     if (!accept_punct(p, ',')) {
    573       ++i;
    574       break;
    575     }
    576     if (is_punct(&p->cur, '}')) {
    577       ++i;
    578       break;
    579     }
    580     ++i;
    581   }
    582   if (braced) {
    583     u32 j;
    584     for (j = zero_lo; j < ty->rec.nfields; ++j) {
    585       const Field* f = &ty->rec.fields[j];
    586       if (f->flags & FIELD_BITFIELD) {
    587         if (!(f->flags & FIELD_ZERO_WIDTH)) {
    588           push_record_field_lv(p, slot, arr_ty, offset, ty, j);
    589           pcg_push_int(p, 0, f->type);
    590           pcg_store(p);
    591           pcg_drop(p);
    592         }
    593       } else {
    594         u32 foff = offset + L->fields[j].offset;
    595         zero_init_at(p, slot, arr_ty, foff, f->type);
    596       }
    597     }
    598   }
    599   return i;
    600 }
    601 
    602 static void init_aggregate_remainder(Parser* p, FrameSlot slot,
    603                                      const Type* arr_ty, u32 offset,
    604                                      const Type* ty, u32 start_index) {
    605   if (ty->kind == TY_ARRAY) {
    606     u32 esz = c_abi_sizeof(p->abi, ty->arr.elem);
    607     u32 i;
    608     for (i = start_index; i < ty->arr.count; ++i) {
    609       init_at(p, slot, arr_ty, offset + i * esz, ty->arr.elem);
    610       if (i + 1u >= ty->arr.count) return;
    611       if (!accept_punct(p, ',')) break;
    612       if (is_punct(&p->cur, '}')) break;
    613     }
    614     for (++i; i < ty->arr.count; ++i) {
    615       zero_init_at(p, slot, arr_ty, offset + i * esz, ty->arr.elem);
    616     }
    617     return;
    618   }
    619   if (ty->kind == TY_STRUCT) {
    620     const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
    621     u32 i;
    622     for (i = start_index; i < ty->rec.nfields; ++i) {
    623       init_field_at(p, slot, arr_ty, offset, ty, i);
    624       if (i + 1u >= ty->rec.nfields) return;
    625       if (!accept_punct(p, ',')) break;
    626       if (is_punct(&p->cur, '}')) break;
    627     }
    628     for (++i; i < ty->rec.nfields; ++i) {
    629       const Field* f = &ty->rec.fields[i];
    630       if (f->flags & FIELD_BITFIELD) {
    631         if (!(f->flags & FIELD_ZERO_WIDTH)) {
    632           push_record_field_lv(p, slot, arr_ty, offset, ty, i);
    633           pcg_push_int(p, 0, f->type);
    634           pcg_store(p);
    635           pcg_drop(p);
    636         }
    637       } else {
    638         const Type* fty = init_field_type_at(ty, i);
    639         u32 foff = init_field_offset_at(L, i);
    640         zero_init_at(p, slot, arr_ty, offset + foff, fty);
    641       }
    642     }
    643     return;
    644   }
    645   init_at(p, slot, arr_ty, offset, ty);
    646 }
    647 
    648 void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
    649              const Type* ty) {
    650   if (ty->kind == TY_ARRAY) {
    651     const Type* elem_ty = ty->arr.elem;
    652     u32 esz = c_abi_sizeof(p->abi, elem_ty);
    653     if (p->cur.kind == TOK_STR &&
    654         string_literal_initializes_array(p, elem_ty, &p->cur)) {
    655       init_string_at(p, slot, arr_ty, offset, elem_ty, ty->arr.count);
    656       return;
    657     }
    658     if (is_punct(&p->cur, '{') && peek1(p).kind == TOK_STR) {
    659       Tok str = peek1(p);
    660       if (string_literal_initializes_array(p, elem_ty, &str)) {
    661         advance(p);
    662         init_string_at(p, slot, arr_ty, offset, elem_ty, ty->arr.count);
    663         accept_punct(p, ',');
    664         expect_punct(p, '}', "'}' after string initializer");
    665         return;
    666       }
    667     }
    668     if (!is_punct(&p->cur, '{')) {
    669       init_aggregate_remainder(p, slot, arr_ty, offset, ty, 0);
    670       return;
    671     }
    672     advance(p); /* '{' */
    673     {
    674       u32 i = 0;
    675       u32 zero_lo = 0;
    676       if (!is_punct(&p->cur, '}')) {
    677         for (;;) {
    678           if (is_punct(&p->cur, '[')) {
    679             const Type* sub_ty;
    680             u32 sub_off;
    681             u32 top_idx = 0;
    682             InitDesignatorCont cont;
    683             parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx,
    684                                    &cont);
    685             while (zero_lo < top_idx) {
    686               zero_init_at(p, slot, arr_ty, offset + zero_lo * esz, elem_ty);
    687               ++zero_lo;
    688             }
    689             init_at(p, slot, arr_ty, sub_off, sub_ty);
    690             if (designator_continues_inside(p, ty, offset, elem_ty,
    691                                             offset + top_idx * esz, &cont) &&
    692                 accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
    693               init_aggregate_remainder(p, slot, arr_ty, cont.parent_offset,
    694                                        cont.parent_ty, cont.next_index);
    695             }
    696             i = top_idx + 1;
    697             if (zero_lo < i) zero_lo = i;
    698           } else {
    699             if (i >= ty->arr.count) {
    700               perr(p, "too many initializers for array");
    701             }
    702             init_at(p, slot, arr_ty, offset + i * esz, elem_ty);
    703             ++i;
    704             if (zero_lo < i) zero_lo = i;
    705           }
    706           if (!accept_punct(p, ',')) break;
    707           if (is_punct(&p->cur, '}')) break;
    708         }
    709       }
    710       expect_punct(p, '}', "'}' after array initializer");
    711       {
    712         u32 j;
    713         for (j = zero_lo; j < ty->arr.count; ++j) {
    714           zero_init_at(p, slot, arr_ty, offset + j * esz, elem_ty);
    715         }
    716       }
    717     }
    718     return;
    719   }
    720   if (ty->kind == TY_STRUCT) {
    721     if (!is_punct(&p->cur, '{')) {
    722       if (try_init_aggregate_from_expr(p, slot, arr_ty, offset, ty)) return;
    723       init_aggregate_remainder(p, slot, arr_ty, offset, ty, 0);
    724       return;
    725     }
    726     advance(p); /* '{' */
    727     zero_object_bytes_at(p, slot, arr_ty, offset, ty);
    728     init_struct_fields(p, slot, arr_ty, offset, ty, 0, /*braced=*/1);
    729     expect_punct(p, '}', "'}' after struct initializer");
    730     return;
    731   }
    732   if (ty->kind == TY_UNION) {
    733     int had_brace = accept_punct(p, '{');
    734     if (!had_brace &&
    735         try_init_aggregate_from_expr(p, slot, arr_ty, offset, ty)) {
    736       return;
    737     }
    738     if (ty->rec.nfields == 0) {
    739       if (had_brace) expect_punct(p, '}', "'}'");
    740       return;
    741     }
    742     if (had_brace && is_punct(&p->cur, '.')) {
    743       const Type* sub_ty;
    744       u32 sub_off;
    745       u32 top_idx = 0;
    746       parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, NULL);
    747       init_at(p, slot, arr_ty, sub_off, sub_ty);
    748     } else {
    749       const Field* f = &ty->rec.fields[0];
    750       if (!(f->flags & FIELD_BITFIELD)) {
    751         init_at(p, slot, arr_ty, offset, f->type);
    752       }
    753     }
    754     if (had_brace) {
    755       accept_punct(p, ',');
    756       expect_punct(p, '}', "'}' after union initializer");
    757     }
    758     return;
    759   }
    760   /* Scalar (incl. pointer). */
    761   int had_brace = accept_punct(p, '{');
    762   push_subobject_lv(p, slot, arr_ty, offset, ty);
    763   parse_assign_expr(p);
    764   to_rvalue(p);
    765   {
    766     const Type* rhs = pcg_top_type(p);
    767     CSemCheck chk = c_sem_check_assignment(p->pool, ty, rhs, C_SEM_ASSIGN_INIT);
    768     if (!chk.ok) perr(p, "%.*s", KIT_SLICE_ARG(kit_slice_cstr(chk.message)));
    769   }
    770   coerce_top_to_lvalue(p);
    771   pcg_store(p);
    772   pcg_drop(p);
    773   if (had_brace) {
    774     accept_punct(p, ',');
    775     expect_punct(p, '}', "'}' after scalar initializer");
    776   }
    777 }
    778 
    779 /* ============================================================
    780  * Static-storage initializers
    781  * ============================================================ */
    782 
    783 void encode_int_le(u8* dst, u32 size, i64 v) {
    784   for (u32 i = 0; i < size; ++i) {
    785     dst[i] = (u8)((v >> (8u * i)) & 0xffu);
    786   }
    787 }
    788 
    789 static u64 decode_uint_le(const u8* src, u32 size) {
    790   u64 v = 0;
    791   if (size > 8) size = 8;
    792   for (u32 i = 0; i < size; ++i) {
    793     v |= (u64)src[i] << (8u * i);
    794   }
    795   return v;
    796 }
    797 
    798 static void encode_uint_le(u8* dst, u32 size, u64 v) {
    799   if (size > 8) size = 8;
    800   for (u32 i = 0; i < size; ++i) {
    801     dst[i] = (u8)((v >> (8u * i)) & 0xffu);
    802   }
    803 }
    804 
    805 static void encode_uint128_le(u8* dst, u32 size, u64 lo, u64 hi) {
    806   if (size > 16) size = 16;
    807   for (u32 i = 0; i < size; ++i) {
    808     u64 lane = i < 8u ? lo : hi;
    809     dst[i] = (u8)((lane >> (8u * (i & 7u))) & 0xffu);
    810   }
    811 }
    812 
    813 static void encode_binary128_from_double_le(u8 out[16], double value) {
    814   union {
    815     double d;
    816     u64 u;
    817   } in;
    818   u64 lo = 0;
    819   u64 hi = 0;
    820   u64 frac;
    821   u32 sign;
    822   u32 exp;
    823   in.d = value;
    824   sign = (u32)(in.u >> 63);
    825   exp = (u32)((in.u >> 52) & 0x7ffu);
    826   frac = in.u & 0x000fffffffffffffull;
    827   if (sign) hi |= 1ull << 63;
    828   if (exp == 0x7ffu) {
    829     hi |= (u64)0x7fffu << 48;
    830     if (frac) {
    831       lo |= (frac & 0xfu) << 60;
    832       hi |= frac >> 4;
    833       hi |= 1ull << 47;
    834     }
    835   } else if (exp != 0 || frac != 0) {
    836     i32 e;
    837     u64 sig;
    838     if (exp == 0) {
    839       e = -1022;
    840       sig = frac;
    841       while ((sig & (1ull << 52)) == 0) {
    842         sig <<= 1;
    843         --e;
    844       }
    845       frac = sig & 0x000fffffffffffffull;
    846     } else {
    847       e = (i32)exp - 1023;
    848     }
    849     hi |= (u64)(u32)(e + 16383) << 48;
    850     lo |= (frac & 0xfu) << 60;
    851     hi |= frac >> 4;
    852   }
    853   encode_uint128_le(out, 16, lo, hi);
    854 }
    855 
    856 static double parse_static_float_add(Parser* p);
    857 
    858 static double parse_static_float_primary(Parser* p) {
    859   double v;
    860   if (accept_punct(p, '+')) return parse_static_float_primary(p);
    861   if (accept_punct(p, '-')) return -parse_static_float_primary(p);
    862   if (accept_punct(p, '(')) {
    863     v = parse_static_float_add(p);
    864     expect_punct(p, ')', "')' in floating constant expression");
    865     return v;
    866   }
    867   if (p->cur.kind == TOK_FLT) {
    868     v = parse_float_literal(p, &p->cur);
    869     advance(p);
    870     return v;
    871   }
    872   if (p->cur.kind == TOK_NUM) {
    873     v = (double)parse_int_literal(p, &p->cur);
    874     advance(p);
    875     return v;
    876   }
    877   perr(p, "expected floating constant expression");
    878   return 0.0;
    879 }
    880 
    881 static double parse_static_float_mul(Parser* p) {
    882   double v = parse_static_float_primary(p);
    883   for (;;) {
    884     if (accept_punct(p, '*')) {
    885       v *= parse_static_float_primary(p);
    886     } else if (accept_punct(p, '/')) {
    887       v /= parse_static_float_primary(p);
    888     } else {
    889       return v;
    890     }
    891   }
    892 }
    893 
    894 static double parse_static_float_add(Parser* p) {
    895   double v = parse_static_float_mul(p);
    896   for (;;) {
    897     if (accept_punct(p, '+')) {
    898       v += parse_static_float_mul(p);
    899     } else if (accept_punct(p, '-')) {
    900       v -= parse_static_float_mul(p);
    901     } else {
    902       return v;
    903     }
    904   }
    905 }
    906 
    907 static int try_parse_static_float(Parser* p, u8* dst, u32 size,
    908                                   const Type* ty) {
    909   const Type* uty = type_unqual(p->pool, ty);
    910   double value;
    911   if (!uty || (uty->kind != TY_FLOAT && uty->kind != TY_DOUBLE &&
    912                uty->kind != TY_LDOUBLE)) {
    913     return 0;
    914   }
    915   value = parse_static_float_add(p);
    916   if (uty->kind == TY_FLOAT && size == 4u) {
    917     union {
    918       float f;
    919       u8 b[4];
    920     } u;
    921     u.f = (float)value;
    922     memcpy(dst, u.b, 4);
    923     return 1;
    924   }
    925   if ((uty->kind == TY_DOUBLE || uty->kind == TY_LDOUBLE) && size == 8u) {
    926     union {
    927       double d;
    928       u8 b[8];
    929     } u;
    930     u.d = value;
    931     memcpy(dst, u.b, 8);
    932     return 1;
    933   }
    934   if (uty->kind == TY_LDOUBLE && size == 16u) {
    935     encode_binary128_from_double_le(dst, value);
    936     return 1;
    937   }
    938   perr(p, "unsupported static floating initializer type");
    939   return 0;
    940 }
    941 
    942 /* Encode a string literal at *buf+offset for a char-array sub-object. */
    943 static void parse_static_string_at(Parser* p, u8* buf, u32 buflen, u32 offset,
    944                                    const Type* elem_ty, u32 count) {
    945   size_t n = 0;
    946   u8* bytes = peek_string_bytes(p, &n);
    947   u32 elem_size = c_abi_sizeof(p->abi, elem_ty);
    948   size_t elems = elem_size ? n / elem_size : 0;
    949   size_t copy = elems;
    950   size_t copy_bytes;
    951   if (copy > count) copy = count;
    952   copy_bytes = copy * elem_size;
    953   if (offset + (u32)copy_bytes > buflen)
    954     perr(p, "string initializer overflows object");
    955   memcpy(buf + offset, bytes, copy_bytes);
    956   kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
    957                                          bytes, 0);
    958   advance(p);
    959 }
    960 
    961 /* Append one pending relocation to the parser-side list. */
    962 void srl_push(Parser* p, u32 offset, u32 size, ObjSymId target, i64 addend) {
    963   if (p->static_relocs_len == p->static_relocs_cap) {
    964     u32 nc = p->static_relocs_cap ? p->static_relocs_cap * 2u : 4u;
    965     void* nb = arena_array(p->pool->arena, StaticReloc, nc);
    966     if (!nb) perr(p, "out of memory recording static relocs");
    967     if (p->static_relocs && p->static_relocs_len) {
    968       memcpy(nb, p->static_relocs,
    969              p->static_relocs_len * sizeof(*p->static_relocs));
    970     }
    971     p->static_relocs = nb;
    972     p->static_relocs_cap = nc;
    973   }
    974   p->static_relocs[p->static_relocs_len].offset = offset;
    975   p->static_relocs[p->static_relocs_len].size = size;
    976   p->static_relocs[p->static_relocs_len].target = target;
    977   p->static_relocs[p->static_relocs_len].addend = addend;
    978   p->static_relocs[p->static_relocs_len].label = 0;
    979   p->static_relocs[p->static_relocs_len].is_label = 0;
    980   ++p->static_relocs_len;
    981 }
    982 
    983 /* Append one pending label-address relocation (&&label) to the list. */
    984 void srl_push_label(Parser* p, u32 offset, u32 size, CGLabel label,
    985                     i64 addend) {
    986   srl_push(p, offset, size, 0, addend);
    987   p->static_relocs[p->static_relocs_len - 1u].label = label;
    988   p->static_relocs[p->static_relocs_len - 1u].is_label = 1;
    989 }
    990 
    991 typedef enum CStaticConstKind {
    992   C_STATIC_CONST_INT,
    993   C_STATIC_CONST_NULL_PTR,
    994   C_STATIC_CONST_ADDR,
    995   C_STATIC_CONST_LABEL_ADDR, /* &&label in a static pointer initializer */
    996 } CStaticConstKind;
    997 
    998 typedef struct CStaticConst {
    999   CStaticConstKind kind;
   1000   CConstInt int_value;
   1001   ObjSymId target;
   1002   i64 addend;
   1003   CGLabel label; /* valid when kind == C_STATIC_CONST_LABEL_ADDR */
   1004 } CStaticConst;
   1005 
   1006 typedef struct StaticRelocSave {
   1007   void* relocs;
   1008   u32 len;
   1009   u32 cap;
   1010 } StaticRelocSave;
   1011 
   1012 static Sym mint_compound_literal_sym(Parser* p) {
   1013   static const char prefix[] = "__kit_compound_literal.";
   1014   char buf[sizeof(prefix) + 12u];
   1015   u32 wlen = 0;
   1016   u32 id = ++p->compound_literal_counter;
   1017   for (u32 i = 0; prefix[i] != 0; ++i) {
   1018     buf[wlen++] = prefix[i];
   1019   }
   1020   {
   1021     char digits[12];
   1022     int dn = 0;
   1023     if (id == 0) digits[dn++] = '0';
   1024     while (id) {
   1025       digits[dn++] = (char)('0' + (id % 10u));
   1026       id /= 10u;
   1027     }
   1028     while (dn) buf[wlen++] = digits[--dn];
   1029   }
   1030   return kit_sym_intern(p->pool->c, (KitSlice){.s = buf, .len = wlen});
   1031 }
   1032 
   1033 static void static_relocs_swap_empty(Parser* p, StaticRelocSave* save) {
   1034   save->relocs = p->static_relocs;
   1035   save->len = p->static_relocs_len;
   1036   save->cap = p->static_relocs_cap;
   1037   p->static_relocs = NULL;
   1038   p->static_relocs_len = 0;
   1039   p->static_relocs_cap = 0;
   1040 }
   1041 
   1042 static void static_relocs_restore(Parser* p, const StaticRelocSave* save) {
   1043   p->static_relocs = save->relocs;
   1044   p->static_relocs_len = save->len;
   1045   p->static_relocs_cap = save->cap;
   1046 }
   1047 
   1048 static ObjSymId define_static_compound_literal(Parser* p, const Type* lit_ty,
   1049                                                SrcLoc loc) {
   1050   Decl decl_in;
   1051   DeclId did;
   1052   ObjSymId sym;
   1053   StaticRelocSave relocs;
   1054 
   1055   if (p->cur_func_name != 0) {
   1056     perr(p, "block-scope compound literal is not a static address constant");
   1057   }
   1058   if (lit_ty && lit_ty->kind == TY_ARRAY && lit_ty->arr.incomplete) {
   1059     lit_ty = complete_incomplete_array(p, lit_ty);
   1060   }
   1061 
   1062   memset(&decl_in, 0, sizeof decl_in);
   1063   decl_in.name = mint_compound_literal_sym(p);
   1064   decl_in.type = lit_ty;
   1065   decl_in.loc = loc;
   1066   decl_in.storage = DS_STATIC;
   1067   decl_in.linkage = DL_INTERNAL;
   1068   decl_in.visibility = SV_DEFAULT;
   1069   did = decl_declare(p->decls, &decl_in);
   1070   sym = decl_obj_sym(p->decls, did);
   1071 
   1072   static_relocs_swap_empty(p, &relocs);
   1073   define_static_object(p, sym, decl_in.section_id, lit_ty,
   1074                        lit_ty ? lit_ty->qual : 0, /*has_init=*/1, loc,
   1075                        decl_in.align);
   1076   static_relocs_restore(p, &relocs);
   1077   return sym;
   1078 }
   1079 
   1080 static CStaticConst parse_static_compound_literal_after_type(Parser* p,
   1081                                                              const Type* lit_ty,
   1082                                                              SrcLoc loc) {
   1083   CStaticConst r;
   1084   memset(&r, 0, sizeof r);
   1085   if (!is_punct(&p->cur, '{')) {
   1086     perr(p, "expected compound literal initializer in static initializer");
   1087   }
   1088   r.kind = C_STATIC_CONST_ADDR;
   1089   r.target = define_static_compound_literal(p, lit_ty, loc);
   1090   r.addend = 0;
   1091   return r;
   1092 }
   1093 
   1094 static CConstInt int_bits_for_type(Parser* p, CConstInt v, const Type* ty) {
   1095   u32 sz = c_abi_sizeof(p->abi, ty);
   1096   v.type = ty;
   1097   if (sz < 8u) {
   1098     u32 bits = sz * 8u;
   1099     v.lo &= bits ? ((1ull << bits) - 1ull) : 0;
   1100     v.hi = 0;
   1101   } else if (sz == 8u) {
   1102     v.hi = 0;
   1103   } else if (sz < 16u) {
   1104     u32 hi_bits = sz * 8u - 64u;
   1105     v.hi &= hi_bits ? ((1ull << hi_bits) - 1ull) : 0;
   1106   }
   1107   if (ty && ty->kind == TY_BOOL) {
   1108     v.lo = (v.lo || v.hi) ? 1u : 0u;
   1109     v.hi = 0;
   1110   }
   1111   return v;
   1112 }
   1113 
   1114 static void check_static_integer_initializer_range(Parser* p, const Type* ty,
   1115                                                    CConstInt v) {
   1116   const Type* dst = type_unqual(p->pool, ty);
   1117   u32 bits;
   1118   if (!dst || !type_is_int(dst) || dst->kind == TY_BOOL) return;
   1119   if (dst->kind == TY_CHAR) return;
   1120   if (!c_abi_type_info(p->abi, dst).signed_) return;
   1121   bits = c_abi_sizeof(p->abi, dst) * 8u;
   1122   if (bits < 64u) {
   1123     i64 minv = -(1ll << (bits - 1u));
   1124     i64 maxv = (1ll << (bits - 1u)) - 1ll;
   1125     if (c_abi_type_info(p->abi, v.type).signed_) {
   1126       i64 sv = const_int_as_i64(p, v);
   1127       if (sv < minv || sv > maxv) {
   1128         perr(p, "initializer value overflows destination type");
   1129       }
   1130     } else {
   1131       u64 maxu = (u64)maxv;
   1132       if (v.hi != 0 || v.lo > maxu) {
   1133         perr(p, "initializer value overflows destination type");
   1134       }
   1135     }
   1136   }
   1137 }
   1138 
   1139 static CConstInt parse_null_pointer_constant(Parser* p, SrcLoc loc) {
   1140   if (is_punct(&p->cur, '(')) {
   1141     Tok n = peek1(p);
   1142     if (starts_type_name(p, &n)) {
   1143       const Type* cast_ty;
   1144       const Type* cast_unqual;
   1145       advance(p);
   1146       cast_ty = parse_type_name(p);
   1147       cast_unqual = type_unqual(p->pool, cast_ty);
   1148       expect_punct(p, ')', "')' after cast in null pointer constant");
   1149       if (!cast_unqual ||
   1150           (cast_unqual->kind != TY_PTR && cast_unqual->kind != TY_VOID &&
   1151            !type_is_int(cast_unqual))) {
   1152         perr(p, "invalid cast in null pointer constant");
   1153       }
   1154       return parse_null_pointer_constant(p, loc);
   1155     }
   1156     if (is_punct(&n, '(')) {
   1157       advance(p);
   1158       {
   1159         CConstInt v = parse_null_pointer_constant(p, loc);
   1160         expect_punct(p, ')', "')' in null pointer constant");
   1161         return v;
   1162       }
   1163     }
   1164   }
   1165   return eval_const_int_typed(p, loc);
   1166 }
   1167 
   1168 /* Try to parse the current expression as a static initializer address
   1169  * constant. Leaves non-address expressions untouched. */
   1170 static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
   1171   Tok t = p->cur;
   1172   Sym name = 0;
   1173   int saw_amp = 0;
   1174   i64 element_addend = 0;
   1175   i64 byte_addend = 0;
   1176   SymEntry* e;
   1177   const Type* tgt_ty;
   1178   ObjSymId tgt;
   1179   if (t.kind == TOK_STR) {
   1180     size_t n = 0;
   1181     u8* bytes = decode_string_literal(p, &t, &n);
   1182     const Type* elem_ty = string_literal_elem_type(p, &t);
   1183     ObjSymId str_sym = emit_string_literal_to_rodata(p, bytes, n, elem_ty);
   1184     kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
   1185                                            bytes, 0);
   1186     advance(p);
   1187     out->kind = C_STATIC_CONST_ADDR;
   1188     out->target = str_sym;
   1189     out->addend = 0;
   1190     return 1;
   1191   }
   1192   if (is_punct(&t, '&')) {
   1193     saw_amp = 1;
   1194     advance(p);
   1195     if (is_punct(&p->cur, '(')) {
   1196       Tok n = peek1(p);
   1197       if (starts_type_name(p, &n)) {
   1198         const Type* lit_ty;
   1199         advance(p);
   1200         lit_ty = parse_type_name(p);
   1201         expect_punct(p, ')', "')' after compound literal type-name");
   1202         *out = parse_static_compound_literal_after_type(p, lit_ty, t.loc);
   1203         return 1;
   1204       }
   1205     }
   1206     if (p->cur.kind != TOK_IDENT ||
   1207         ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
   1208       perr(p, "expected identifier after '&' in static initializer");
   1209     }
   1210     name = p->cur.v.ident;
   1211     advance(p);
   1212   } else if (t.kind == TOK_IDENT && ident_kw_init(p, t.v.ident) == KW_NONE) {
   1213     name = t.v.ident;
   1214     advance(p);
   1215   } else {
   1216     return 0;
   1217   }
   1218   e = scope_lookup(p, name);
   1219   if (!e || (e->kind != SEK_GLOBAL && e->kind != SEK_FUNC)) {
   1220     perr(p, "static initializer is not a constant address expression");
   1221   }
   1222   tgt = e->v.sym;
   1223   tgt_ty = e->type;
   1224   if (saw_amp && is_punct(&p->cur, '[')) {
   1225     SrcLoc cloc;
   1226     advance(p);
   1227     cloc = tok_loc_init(&p->cur);
   1228     element_addend = eval_const_int(p, cloc);
   1229     expect_punct(p, ']', "']' after array-subscript constant");
   1230     if (tgt_ty && tgt_ty->kind == TY_ARRAY) {
   1231       byte_addend +=
   1232           element_addend * (i64)c_abi_sizeof(p->abi, tgt_ty->arr.elem);
   1233     } else {
   1234       byte_addend += element_addend;
   1235     }
   1236   }
   1237   while (is_punct(&p->cur, '+') || is_punct(&p->cur, '-')) {
   1238     int neg = is_punct(&p->cur, '-');
   1239     SrcLoc cloc;
   1240     i64 v;
   1241     advance(p);
   1242     cloc = tok_loc_init(&p->cur);
   1243     v = eval_const_int(p, cloc);
   1244     if (neg) v = -v;
   1245     if (tgt_ty && tgt_ty->kind == TY_ARRAY) {
   1246       byte_addend += v * (i64)c_abi_sizeof(p->abi, tgt_ty->arr.elem);
   1247     } else if (tgt_ty && tgt_ty->kind == TY_PTR) {
   1248       byte_addend += v * (i64)c_abi_sizeof(p->abi, tgt_ty->ptr.pointee);
   1249     } else if (saw_amp) {
   1250       byte_addend += v * (i64)c_abi_sizeof(p->abi, tgt_ty);
   1251     } else {
   1252       byte_addend += v;
   1253     }
   1254   }
   1255   out->kind = C_STATIC_CONST_ADDR;
   1256   out->target = tgt;
   1257   out->addend = byte_addend;
   1258   return 1;
   1259 }
   1260 
   1261 static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
   1262   CStaticConst r;
   1263   memset(&r, 0, sizeof r);
   1264   r.kind = C_STATIC_CONST_INT;
   1265   if (ty && ty->kind == TY_PTR) {
   1266     if (is_punct(&p->cur, P_AND)) {
   1267       /* GNU labels-as-values: `&&label` in a static pointer initializer,
   1268        * e.g. a direct-threaded dispatch table `static void *tab[] = {...}`. */
   1269       Sym lname;
   1270       SrcLoc lloc;
   1271       advance(p); /* '&&' */
   1272       if (p->cur.kind != TOK_IDENT ||
   1273           ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
   1274         perr(p, "expected label name after '&&' in static initializer");
   1275       }
   1276       lname = p->cur.v.ident;
   1277       lloc = tok_loc_init(&p->cur);
   1278       advance(p);
   1279       r.kind = C_STATIC_CONST_LABEL_ADDR;
   1280       r.label = take_label_addr(p, lname, lloc);
   1281       r.addend = 0;
   1282       return r;
   1283     }
   1284     if (is_punct(&p->cur, '(')) {
   1285       Tok n = peek1(p);
   1286       /* Grouping parens around the pointer initializer, e.g. `("str")`,
   1287        * `(&x)`, or `((expr))`. A `(type-name)` is a cast or compound literal
   1288        * and is handled below, so peel only when the inner token does not start
   1289        * a type-name. */
   1290       if (!starts_type_name(p, &n)) {
   1291         advance(p);
   1292         r = parse_static_const(p, ty, loc);
   1293         expect_punct(p, ')', "')' in static pointer initializer");
   1294         return r;
   1295       }
   1296     }
   1297     if (is_punct(&p->cur, '(')) {
   1298       Tok n = peek1(p);
   1299       if (starts_type_name(p, &n)) {
   1300         const Type* cast_ty;
   1301         const Type* cast_unqual;
   1302         advance(p);
   1303         cast_ty = parse_type_name(p);
   1304         cast_unqual = type_unqual(p->pool, cast_ty);
   1305         expect_punct(p, ')', "')' after cast or compound literal type-name");
   1306         if (is_punct(&p->cur, '{')) {
   1307           const Type* lit_unqual = type_unqual(p->pool, cast_ty);
   1308           if (!lit_unqual || lit_unqual->kind != TY_ARRAY) {
   1309             perr(p,
   1310                  "non-array compound literal needs '&' in pointer initializer");
   1311           }
   1312           return parse_static_compound_literal_after_type(p, cast_ty, loc);
   1313         }
   1314         if (!cast_unqual ||
   1315             (cast_unqual->kind != TY_PTR && cast_unqual->kind != TY_VOID &&
   1316              !type_is_int(cast_unqual))) {
   1317           perr(p, "invalid cast in null pointer constant");
   1318         }
   1319         if (cast_unqual->kind == TY_PTR &&
   1320             (p->cur.kind == TOK_STR || is_punct(&p->cur, '&') ||
   1321              (p->cur.kind == TOK_IDENT &&
   1322               ident_kw_init(p, p->cur.v.ident) == KW_NONE)) &&
   1323             try_parse_static_address_const(p, &r)) {
   1324           return r;
   1325         }
   1326         r.int_value = parse_null_pointer_constant(p, loc);
   1327         if (const_int_as_i64(p, r.int_value) != 0 &&
   1328             cast_unqual->kind == TY_PTR) {
   1329           r.kind = C_STATIC_CONST_INT;
   1330           return r;
   1331         }
   1332         if (const_int_as_i64(p, r.int_value) != 0) {
   1333           perr(p, "static pointer initializer is not a null pointer constant");
   1334         }
   1335         r.kind = C_STATIC_CONST_NULL_PTR;
   1336         return r;
   1337       }
   1338     }
   1339     if (try_parse_static_address_const(p, &r)) return r;
   1340     r.int_value = parse_null_pointer_constant(p, loc);
   1341     if (const_int_as_i64(p, r.int_value) != 0) {
   1342       perr(p, "static pointer initializer is not a null pointer constant");
   1343     }
   1344     r.kind = C_STATIC_CONST_NULL_PTR;
   1345     return r;
   1346   }
   1347   r.int_value = eval_const_int_typed(p, loc);
   1348   check_static_integer_initializer_range(p, ty, r.int_value);
   1349   return r;
   1350 }
   1351 
   1352 static void parse_static_bitfield_at(Parser* p, u8* buf, u32 buflen,
   1353                                      u32 rec_offset, const ABIFieldLayout* fl,
   1354                                      const Type* field_ty) {
   1355   SrcLoc cloc = tok_loc_init(&p->cur);
   1356   CStaticConst parsed = parse_static_const(p, field_ty, cloc);
   1357   u32 storage_off = rec_offset + fl->offset;
   1358   u32 storage_size = fl->storage_size;
   1359   u32 width = fl->bit_width;
   1360   u32 lsb = fl->bit_offset;
   1361   u64 ones;
   1362   u64 mask;
   1363   u64 cur;
   1364   u64 val;
   1365   if (parsed.kind != C_STATIC_CONST_INT) {
   1366     perr(p, "bit-field initializer requires integer constant expression");
   1367   }
   1368   if (width == 0) return;
   1369   if (storage_size > 8) perr(p, "bit-field storage unit too wide");
   1370   if (storage_off > buflen || storage_size > buflen - storage_off)
   1371     perr(p, "initializer overflows object");
   1372   ones = width >= 64u ? ~(u64)0 : (((u64)1 << width) - 1u);
   1373   mask = ones << lsb;
   1374   cur = decode_uint_le(buf + storage_off, storage_size);
   1375   val = (int_bits_for_type(p, parsed.int_value, field_ty).lo & ones) << lsb;
   1376   cur = (cur & ~mask) | val;
   1377   encode_uint_le(buf + storage_off, storage_size, cur);
   1378 }
   1379 
   1380 static void parse_static_aggregate_remainder(Parser* p, u8* buf, u32 buflen,
   1381                                              u32 offset, const Type* ty,
   1382                                              u32 start_index) {
   1383   if (ty->kind == TY_ARRAY) {
   1384     const Type* elem = ty->arr.elem;
   1385     u32 esz = c_abi_sizeof(p->abi, elem);
   1386     u32 i;
   1387     for (i = start_index; i < ty->arr.count; ++i) {
   1388       parse_static_init_at(p, buf, buflen, offset + i * esz, elem);
   1389       if (i + 1u >= ty->arr.count) return;
   1390       if (!accept_punct(p, ',')) break;
   1391       if (is_punct(&p->cur, '}')) break;
   1392     }
   1393     return;
   1394   }
   1395   if (ty->kind == TY_STRUCT) {
   1396     const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
   1397     u32 i;
   1398     for (i = start_index; i < ty->rec.nfields; ++i) {
   1399       const Field* f = &ty->rec.fields[i];
   1400       if (f->flags & FIELD_BITFIELD) {
   1401         if (!(f->flags & FIELD_ZERO_WIDTH)) {
   1402           parse_static_bitfield_at(p, buf, buflen, offset, &L->fields[i],
   1403                                    f->type);
   1404         }
   1405       } else {
   1406         const Type* fty = init_field_type_at(ty, i);
   1407         u32 foff = init_field_offset_at(L, i);
   1408         parse_static_init_at(p, buf, buflen, offset + foff, fty);
   1409       }
   1410       if (i + 1u >= ty->rec.nfields) return;
   1411       if (!accept_punct(p, ',')) break;
   1412       if (is_punct(&p->cur, '}')) break;
   1413     }
   1414     return;
   1415   }
   1416   parse_static_init_at(p, buf, buflen, offset, ty);
   1417 }
   1418 
   1419 void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
   1420                           const Type* ty) {
   1421   /* An aggregate object may be initialized by a (possibly parenthesized)
   1422    * compound literal of its own type: `static T x = (T){...};` or, after macro
   1423    * expansion, `static T x = ((T){...});`. Strip the `(type-name)` cast so the
   1424    * brace body below initializes the object in place; peel grouping parens by
   1425    * recursing and matching the closing ')'. Pointer/scalar targets keep their
   1426    * own handling (parse_static_const / eval_const), where a compound literal
   1427    * can instead yield an address or value. */
   1428   if ((ty->kind == TY_STRUCT || ty->kind == TY_UNION || ty->kind == TY_ARRAY) &&
   1429       is_punct(&p->cur, '(')) {
   1430     Tok n = peek1(p);
   1431     if (starts_type_name(p, &n)) {
   1432       advance(p);
   1433       parse_type_name(p);
   1434       expect_punct(p, ')', "')' after compound literal type-name");
   1435     } else if (is_punct(&n, '(')) {
   1436       advance(p);
   1437       parse_static_init_at(p, buf, buflen, offset, ty);
   1438       expect_punct(p, ')', "')' after parenthesized initializer");
   1439       return;
   1440     }
   1441   }
   1442   if (ty->kind == TY_ARRAY) {
   1443     const Type* elem = ty->arr.elem;
   1444     u32 esz = c_abi_sizeof(p->abi, elem);
   1445     u32 i = 0;
   1446     int had_brace;
   1447     if (p->cur.kind == TOK_STR &&
   1448         string_literal_initializes_array(p, elem, &p->cur)) {
   1449       parse_static_string_at(p, buf, buflen, offset, elem, ty->arr.count);
   1450       return;
   1451     }
   1452     if (is_punct(&p->cur, '{') && peek1(p).kind == TOK_STR) {
   1453       Tok str = peek1(p);
   1454       if (string_literal_initializes_array(p, elem, &str)) {
   1455         advance(p);
   1456         parse_static_string_at(p, buf, buflen, offset, elem, ty->arr.count);
   1457         accept_punct(p, ',');
   1458         expect_punct(p, '}', "'}' after string initializer");
   1459         return;
   1460       }
   1461     }
   1462     had_brace = accept_punct(p, '{');
   1463     if (!had_brace) {
   1464       parse_static_aggregate_remainder(p, buf, buflen, offset, ty, 0);
   1465       return;
   1466     }
   1467     if (!is_punct(&p->cur, '}')) {
   1468       for (;;) {
   1469         if (is_punct(&p->cur, '[')) {
   1470           const Type* sub_ty;
   1471           u32 sub_off;
   1472           u32 top_idx = 0;
   1473           InitDesignatorCont cont;
   1474           parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx,
   1475                                  &cont);
   1476           parse_static_init_at(p, buf, buflen, sub_off, sub_ty);
   1477           if (designator_continues_inside(p, ty, offset, elem,
   1478                                           offset + top_idx * esz, &cont) &&
   1479               accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
   1480             parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset,
   1481                                              cont.parent_ty, cont.next_index);
   1482           }
   1483           i = top_idx + 1;
   1484         } else {
   1485           if (i >= ty->arr.count) {
   1486             perr(p, "too many initializers for array");
   1487           }
   1488           parse_static_init_at(p, buf, buflen, offset + i * esz, elem);
   1489           ++i;
   1490         }
   1491         if (!accept_punct(p, ',')) break;
   1492         if (is_punct(&p->cur, '}')) break;
   1493       }
   1494     }
   1495     expect_punct(p, '}', "'}' after array initializer");
   1496     return;
   1497   }
   1498   if (ty->kind == TY_STRUCT) {
   1499     int had_brace = accept_punct(p, '{');
   1500     const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
   1501     u32 i = 0;
   1502     if (!had_brace) {
   1503       parse_static_aggregate_remainder(p, buf, buflen, offset, ty, 0);
   1504       return;
   1505     }
   1506     /* Designators may re-target any field regardless of the running position
   1507      * `i`, so the loop is bounded by '}'/EOF; `i` only drives positional
   1508      * placement (and is range-checked before use). */
   1509     while (!is_punct(&p->cur, '}') && p->cur.kind != TOK_EOF) {
   1510       const Field* f;
   1511       if (is_punct(&p->cur, '.')) {
   1512         const Type* sub_ty;
   1513         u32 sub_off;
   1514         u32 top_idx = 0;
   1515         InitDesignatorCont cont;
   1516         parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx,
   1517                                &cont);
   1518         parse_static_init_at(p, buf, buflen, sub_off, sub_ty);
   1519         {
   1520           const Field* top_f = &ty->rec.fields[top_idx];
   1521           u32 top_off = offset + L->fields[top_idx].offset;
   1522           if (designator_continues_inside(p, ty, offset, top_f->type, top_off,
   1523                                           &cont) &&
   1524               accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
   1525             parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset,
   1526                                              cont.parent_ty, cont.next_index);
   1527           }
   1528         }
   1529         i = top_idx + 1;
   1530         if (!accept_punct(p, ',')) break;
   1531         continue;
   1532       }
   1533       if (i >= ty->rec.nfields) break; /* excess positional initializer */
   1534       f = &ty->rec.fields[i];
   1535       if (f->flags & FIELD_BITFIELD) {
   1536         if (!(f->flags & FIELD_ZERO_WIDTH)) {
   1537           parse_static_bitfield_at(p, buf, buflen, offset, &L->fields[i],
   1538                                    f->type);
   1539         }
   1540       } else {
   1541         const Type* fty = init_field_type_at(ty, i);
   1542         u32 foff = init_field_offset_at(L, i);
   1543         parse_static_init_at(p, buf, buflen, offset + foff, fty);
   1544       }
   1545       ++i;
   1546       if (!accept_punct(p, ',')) break;
   1547     }
   1548     expect_punct(p, '}', "'}' after struct initializer");
   1549     return;
   1550   }
   1551   if (ty->kind == TY_UNION) {
   1552     int had_brace = accept_punct(p, '{');
   1553     if (ty->rec.nfields == 0) {
   1554       if (had_brace) expect_punct(p, '}', "'}' after union initializer");
   1555       return;
   1556     }
   1557     if (had_brace && is_punct(&p->cur, '.')) {
   1558       const Type* sub_ty;
   1559       u32 sub_off;
   1560       u32 top_idx = 0;
   1561       parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, NULL);
   1562       (void)top_idx;
   1563       parse_static_init_at(p, buf, buflen, sub_off, sub_ty);
   1564     } else {
   1565       const Field* f = &ty->rec.fields[0];
   1566       if (!(f->flags & FIELD_BITFIELD)) {
   1567         parse_static_init_at(p, buf, buflen, offset, f->type);
   1568       } else if (!(f->flags & FIELD_ZERO_WIDTH)) {
   1569         const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
   1570         parse_static_bitfield_at(p, buf, buflen, offset, &L->fields[0],
   1571                                  f->type);
   1572       }
   1573     }
   1574     if (had_brace) {
   1575       accept_punct(p, ',');
   1576       expect_punct(p, '}', "'}' after union initializer");
   1577     }
   1578     return;
   1579   }
   1580   /* Scalar / pointer. */
   1581   {
   1582     int had_brace = accept_punct(p, '{');
   1583     SrcLoc cloc = tok_loc_init(&p->cur);
   1584     u32 sz = c_abi_sizeof(p->abi, ty);
   1585     CStaticConst cv;
   1586     if (offset + sz > buflen) perr(p, "initializer overflows object");
   1587     if (try_parse_static_float(p, buf + offset, sz, ty)) {
   1588       if (had_brace) {
   1589         accept_punct(p, ',');
   1590         expect_punct(p, '}', "'}' after scalar initializer");
   1591       }
   1592       return;
   1593     }
   1594     cv = parse_static_const(p, ty, cloc);
   1595     if (cv.kind == C_STATIC_CONST_ADDR) {
   1596       srl_push(p, offset, sz, cv.target, cv.addend);
   1597     } else if (cv.kind == C_STATIC_CONST_LABEL_ADDR) {
   1598       srl_push_label(p, offset, sz, cv.label, cv.addend);
   1599     } else if (cv.kind == C_STATIC_CONST_NULL_PTR) {
   1600       encode_int_le(buf + offset, sz, 0);
   1601     } else {
   1602       {
   1603         CConstInt bits = int_bits_for_type(p, cv.int_value, ty);
   1604         encode_uint128_le(buf + offset, sz, bits.lo, bits.hi);
   1605       }
   1606     }
   1607     if (had_brace) {
   1608       accept_punct(p, ',');
   1609       expect_punct(p, '}', "'}' after scalar initializer");
   1610     }
   1611   }
   1612 }
   1613 
   1614 static void emit_static_data(Parser* p, const u8* buf, u32 size) {
   1615   u32 pos = 0;
   1616   u32 emitted_relocs = 0;
   1617 
   1618   while (emitted_relocs < p->static_relocs_len) {
   1619     u32 best = p->static_relocs_len;
   1620     u32 best_off = 0xffffffffu;
   1621     for (u32 i = 0; i < p->static_relocs_len; ++i) {
   1622       if (p->static_relocs[i].offset < pos) continue;
   1623       if (p->static_relocs[i].offset < best_off) {
   1624         best = i;
   1625         best_off = p->static_relocs[i].offset;
   1626       }
   1627     }
   1628     if (best == p->static_relocs_len) break;
   1629     if (best_off > size || p->static_relocs[best].size > size - best_off) {
   1630       perr(p, "static initializer relocation overflows object");
   1631     }
   1632     if (best_off > pos) {
   1633       if (buf) {
   1634         kit_cg_data_bytes(p->cg, buf + pos, best_off - pos);
   1635       } else {
   1636         kit_cg_data_zero(p->cg, best_off - pos);
   1637       }
   1638     }
   1639     if (p->static_relocs[best].is_label) {
   1640       kit_cg_data_label_addr(p->cg, p->static_relocs[best].label,
   1641                              p->static_relocs[best].addend,
   1642                              p->static_relocs[best].size, 0);
   1643     } else {
   1644       kit_cg_data_addr(p->cg, p->static_relocs[best].target,
   1645                        p->static_relocs[best].addend,
   1646                        p->static_relocs[best].size, 0);
   1647     }
   1648     pos = best_off + p->static_relocs[best].size;
   1649     ++emitted_relocs;
   1650   }
   1651 
   1652   if (pos < size) {
   1653     if (buf) {
   1654       kit_cg_data_bytes(p->cg, buf + pos, size - pos);
   1655     } else {
   1656       kit_cg_data_zero(p->cg, size - pos);
   1657     }
   1658   }
   1659 }
   1660 
   1661 /* Define a static-storage object. */
   1662 void define_static_object(Parser* p, ObjSymId sym, ObjSecId section_id,
   1663                           const Type* var_ty, u16 quals, int has_init,
   1664                           SrcLoc loc, u32 align_override) {
   1665   u32 size = c_abi_sizeof(p->abi, var_ty);
   1666   u32 align = c_abi_alignof(p->abi, var_ty);
   1667   KitCgDataDefAttrs attrs;
   1668   if (align_override > align) align = align_override;
   1669   u8* buf = NULL;
   1670   int has_nonzero = 0;
   1671   int has_label_reloc = 0;
   1672 
   1673   if (has_init) {
   1674     buf = (u8*)arena_array(p->pool->arena, u8, size ? size : 1u);
   1675     memset(buf, 0, size);
   1676     p->static_relocs_len = 0;
   1677     parse_static_init_at(p, buf, size, 0, var_ty);
   1678     for (u32 i = 0; i < size; ++i) {
   1679       if (buf[i]) {
   1680         has_nonzero = 1;
   1681         break;
   1682       }
   1683     }
   1684     if (p->static_relocs_len) has_nonzero = 1;
   1685     for (u32 i = 0; i < p->static_relocs_len; ++i) {
   1686       if (p->static_relocs[i].is_label) {
   1687         has_label_reloc = 1;
   1688         break;
   1689       }
   1690     }
   1691   }
   1692 
   1693   memset(&attrs, 0, sizeof attrs);
   1694   attrs.section = section_id;
   1695   attrs.align = align ? align : 1u;
   1696   /* Label-address relocations (&&label) are tied to the enclosing function's
   1697    * label namespace, so the table must be emitted as function-local static
   1698    * data while that function is still open. */
   1699   if (has_label_reloc) {
   1700     attrs.flags |= KIT_CG_DATADEF_FUNCTION_LOCAL;
   1701   }
   1702   if ((quals & Q_CONST) != 0 && has_nonzero) {
   1703     attrs.flags |= KIT_CG_DATADEF_READONLY;
   1704   }
   1705   if (!has_init || !has_nonzero) {
   1706     attrs.flags |= KIT_CG_DATADEF_ZERO_FILL;
   1707   }
   1708 
   1709   kit_cg_data_begin(p->cg, sym, attrs);
   1710   emit_static_data(p, (attrs.flags & KIT_CG_DATADEF_ZERO_FILL) ? NULL : buf,
   1711                    size);
   1712   kit_cg_data_end(p->cg);
   1713   p->static_relocs_len = 0;
   1714   (void)loc;
   1715 }