kit

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

data.c (26765B)


      1 #include "cg/internal.h"
      2 #include "core/vec.h"
      3 #include "obj/symresolve.h"
      4 
      5 static void api_data_tls_write_zero(KitCg* g, uint64_t size);
      6 
      7 static SymAttrs api_data_sym_attrs(const ObjSym* s) {
      8   SymAttrs a;
      9   memset(&a, 0, sizeof a);
     10   if (!s) return a;
     11   a.bind = s->bind;
     12   a.kind = s->kind;
     13   a.size = s->size;
     14   a.common_align = (s->kind == SK_COMMON) ? (u32)s->common_align : 0u;
     15   a.in_comdat = 0;
     16   return a;
     17 }
     18 
     19 static SymAttrs api_data_decl_attrs(Compiler* c, const KitCgDecl* decl,
     20                                     uint64_t size, uint32_t common_align) {
     21   SymAttrs a;
     22   memset(&a, 0, sizeof a);
     23   if (!decl) return a;
     24   a.bind = api_map_bind(decl->sym.bind);
     25   a.kind = (decl->as.object.flags & KIT_CG_OBJ_TLS) ? SK_TLS : SK_OBJ;
     26   a.size = size;
     27   a.common_align = common_align;
     28   a.in_comdat = 0;
     29   (void)c;
     30   return a;
     31 }
     32 
     33 static void api_data_clear_state(KitCg* g) {
     34   if (!g) return;
     35   g->data_sec = OBJ_SEC_NONE;
     36   g->data_sym = OBJ_SYM_NONE;
     37   g->data_base = 0;
     38   g->data_size = 0;
     39   g->data_atomize = 0;
     40   g->data_retain = 0;
     41   g->data_local_static_target = 0;
     42   g->data_discard = 0;
     43 }
     44 
     45 static void api_data_discard_begin(KitCg* g, ObjSymId sym) {
     46   if (!g) return;
     47   g->data_sec = OBJ_SEC_NONE;
     48   g->data_sym = sym;
     49   g->data_base = 0;
     50   g->data_size = 0;
     51   g->data_atomize = 0;
     52   g->data_retain = 0;
     53   g->data_local_static_target = 0;
     54   g->data_discard = 1;
     55 }
     56 
     57 static int api_data_section_is_isolated(const Section* sec, const ObjSym* sym) {
     58   if (!sec || !sym || sym->section_id == OBJ_SEC_NONE || sym->value != 0)
     59     return 0;
     60   if (sec->kind == SEC_BSS || sec->sem == SSEM_NOBITS)
     61     return sec->bss_size == sym->size;
     62   return sec->bytes.total == sym->size;
     63 }
     64 
     65 static void api_data_remove_existing_if_isolated(KitCg* g, const ObjSym* sym) {
     66   const Section* sec;
     67   if (!g || !sym || sym->section_id == OBJ_SEC_NONE) return;
     68   sec = obj_section_get(g->obj, sym->section_id);
     69   if (api_data_section_is_isolated(sec, sym))
     70     obj_section_remove(g->obj, sym->section_id);
     71 }
     72 
     73 static void api_data_apply_symbol_attrs(KitCg* g, ObjSymId sym,
     74                                         const KitCgDecl* decl) {
     75   ObjSym* osym;
     76   if (!g || sym == OBJ_SYM_NONE || !decl) return;
     77   osym = (ObjSym*)obj_symbol_get(g->obj, sym);
     78   if (!osym) return;
     79   osym->bind = api_map_bind(decl->sym.bind);
     80   osym->vis = api_map_vis(decl->sym.visibility);
     81   osym->kind = (decl->as.object.flags & KIT_CG_OBJ_TLS) ? SK_TLS : SK_OBJ;
     82   osym->common_align = 0;
     83 }
     84 
     85 /* A symbol already defined by the *current* source unit is a same-TU
     86  * re-definition — legal C tentative-definition coalescing (`int g; int g;`,
     87  * `int g; int g = 5;`, `int arr[]; int arr[3];`). Those re-emit through the
     88  * legacy last-writer-wins path; only a definition contributed by a *different*
     89  * unit (cross-TU LTO staging) is resolved via symresolve_merge. */
     90 static int api_data_defined_this_unit(const KitCg* g, ObjSymId sym) {
     91   if (!g || g->cur_unit_seq == 0 || sym == OBJ_SYM_NONE) return 0;
     92   if (sym >= g->sym_def_seq_cap) return 0;
     93   return g->sym_def_seq[sym] == g->cur_unit_seq;
     94 }
     95 
     96 static void api_data_mark_defined_unit(KitCg* g, ObjSymId sym) {
     97   Heap* h;
     98   u32* na;
     99   u32 cap;
    100   if (!g || g->cur_unit_seq == 0 || sym == OBJ_SYM_NONE) return;
    101   if (sym >= g->sym_def_seq_cap) {
    102     h = g->c->ctx->heap;
    103     cap = g->sym_def_seq_cap ? g->sym_def_seq_cap : 16u;
    104     while (cap <= sym) cap *= 2u;
    105     na = (u32*)h->alloc(h, sizeof(*na) * cap, _Alignof(u32));
    106     if (!na) return;
    107     memset(na, 0, sizeof(*na) * cap);
    108     if (g->sym_def_seq) {
    109       memcpy(na, g->sym_def_seq, sizeof(*na) * g->sym_def_seq_cap);
    110       h->free(h, g->sym_def_seq, sizeof(*g->sym_def_seq) * g->sym_def_seq_cap);
    111     }
    112     g->sym_def_seq = na;
    113     g->sym_def_seq_cap = cap;
    114   }
    115   g->sym_def_seq[sym] = g->cur_unit_seq;
    116 }
    117 
    118 static void api_data_tls_ensure_materialized(KitCg* g) {
    119   if (!g || !g->data_tls_collect || !g->data_tls_zero_fill) return;
    120   if (g->data_size) api_data_tls_write_zero(g, g->data_size);
    121   g->data_tls_zero_fill = 0;
    122 }
    123 
    124 static void api_data_tls_write(KitCg* g, const void* data, size_t len) {
    125   if (!g || !len) return;
    126   api_data_tls_ensure_materialized(g);
    127   buf_write(&g->data_tls_bytes, data, len);
    128   g->data_size += len;
    129 }
    130 
    131 static void api_data_tls_write_zero(KitCg* g, uint64_t size) {
    132   u8 pad[64];
    133   if (!g || !size) return;
    134   memset(pad, 0, sizeof pad);
    135   while (size >= sizeof pad) {
    136     buf_write(&g->data_tls_bytes, pad, sizeof pad);
    137     size -= sizeof pad;
    138   }
    139   if (size) buf_write(&g->data_tls_bytes, pad, (size_t)size);
    140 }
    141 
    142 static void api_data_tls_reloc(KitCg* g, KitCgSym target, int64_t addend,
    143                                RelocKind kind) {
    144   Heap* h;
    145   ObjTlsReloc* r;
    146   if (!g || kind == R_NONE) return;
    147   api_data_tls_ensure_materialized(g);
    148   h = (Heap*)g->c->ctx->heap;
    149   if (VEC_GROW(h, g->data_tls_relocs, g->data_tls_relocs_cap,
    150                g->data_tls_nrelocs + 1u)) {
    151     compiler_panic(g->c, api_no_loc(), "KitCg: oom on TLS data relocs");
    152   }
    153   r = &g->data_tls_relocs[g->data_tls_nrelocs++];
    154   r->offset = (u32)g->data_size;
    155   r->kind = kind;
    156   r->target = (ObjSymId)target;
    157   r->addend = addend;
    158 }
    159 
    160 static void api_data_encode_addend(KitCg* g, u8* out, u32 width,
    161                                    int64_t addend) {
    162   uint64_t v;
    163   if (!g || !out) return;
    164   v = (uint64_t)addend;
    165   for (u32 i = 0; i < width; ++i) {
    166     u32 shift = g->c->target.big_endian ? (width - 1u - i) * 8u : i * 8u;
    167     out[i] = (u8)(v >> shift);
    168   }
    169 }
    170 
    171 void kit_cg_data_begin(KitCg* g, KitCgSym cg_sym, KitCgDataDefAttrs attrs) {
    172   Compiler* c;
    173   ObjBuilder* ob;
    174   ObjSymId sym;
    175   KitCgTypeId ty;
    176   u32 align;
    177   SecKind sec_kind;
    178   u16 sec_flags;
    179   Sym sec_name_sym;
    180   Slice split_base;
    181   ObjSecId sec;
    182   KitCgDecl decl_attrs;
    183   int atomize = 0;
    184   if (!g) return;
    185   c = g->c;
    186   ob = g->obj;
    187   sym = (ObjSymId)cg_sym;
    188   ty = api_sym_type(g, cg_sym);
    189   if (!ty) return;
    190   decl_attrs = api_sym_attrs(g, cg_sym);
    191   align =
    192       attrs.align ? attrs.align : (u32)abi_cg_alignof(c->abi, decl_attrs.type);
    193   if (sym != OBJ_SYM_NONE && !api_data_defined_this_unit(g, sym)) {
    194     const ObjSym* existing = obj_symbol_get(ob, sym);
    195     if (symresolve_sym_is_def(existing)) {
    196       SymAttrs old_attrs = api_data_sym_attrs(existing);
    197       SymAttrs new_attrs =
    198           api_data_decl_attrs(c, &decl_attrs, abi_cg_sizeof(c->abi, ty), 0);
    199       SymMergeResult mr = symresolve_merge(old_attrs, new_attrs);
    200       switch (mr.kind) {
    201         case SYM_MERGE_REPLACE:
    202           api_data_remove_existing_if_isolated(g, existing);
    203           obj_symbol_set_bind(ob, sym, (SymBind)new_attrs.bind);
    204           break;
    205         case SYM_MERGE_KEEP_EXISTING:
    206         case SYM_MERGE_COMDAT_DISCARD:
    207         case SYM_MERGE_COMMON:
    208           api_data_discard_begin(g, sym);
    209           return;
    210         case SYM_MERGE_ODR_ERROR:
    211           compiler_panic(c, g->cur_loc, "duplicate definition of symbol");
    212       }
    213     }
    214   }
    215 
    216   if ((attrs.flags & KIT_CG_DATADEF_FUNCTION_LOCAL) && g->target &&
    217       g->target->local_static_data_begin) {
    218     CGLocalStaticDataDesc desc;
    219     memset(&desc, 0, sizeof desc);
    220     desc.sym = sym;
    221     desc.type = ty;
    222     desc.attrs = attrs;
    223     desc.align = align;
    224     if (g->target->local_static_data_begin(g->target, &desc)) {
    225       g->data_sec = OBJ_SEC_NONE;
    226       g->data_sym = sym;
    227       g->data_base = 0;
    228       g->data_size = 0;
    229       g->data_local_static_target = 1;
    230       return;
    231     }
    232   }
    233 
    234   if ((decl_attrs.as.object.flags & KIT_CG_OBJ_TLS) &&
    235       obj_format_tls_via_descriptor(c)) {
    236     g->data_sec = OBJ_SEC_NONE;
    237     g->data_sym = sym;
    238     g->data_base = 0;
    239     g->data_size = 0;
    240     g->data_tls_collect = 1;
    241     g->data_tls_zero_fill = (attrs.flags & KIT_CG_DATADEF_ZERO_FILL) ? 1u : 0u;
    242     g->data_tls_align = align ? align : 1u;
    243     g->data_tls_nrelocs = 0;
    244     buf_init(&g->data_tls_bytes, (Heap*)c->ctx->heap);
    245     return;
    246   }
    247 
    248   if (!attrs.section && decl_attrs.as.object.section) {
    249     attrs.section = decl_attrs.as.object.section;
    250   }
    251   split_base = SLICE_NULL;
    252   if ((decl_attrs.as.object.flags & KIT_CG_OBJ_TLS) &&
    253       (attrs.flags & KIT_CG_DATADEF_ZERO_FILL)) {
    254     sec_kind = SEC_BSS;
    255     sec_flags = SF_ALLOC | SF_WRITE | SF_TLS;
    256     if (attrs.section) {
    257       sec_name_sym = (Sym)attrs.section;
    258     } else {
    259       sec_name_sym = obj_secname_tbss(c);
    260       split_base = pool_slice(c->global, sec_name_sym);
    261     }
    262   } else if (attrs.flags & KIT_CG_DATADEF_ZERO_FILL) {
    263     sec_kind = SEC_BSS;
    264     sec_flags = SF_ALLOC | SF_WRITE;
    265     if (attrs.section) {
    266       sec_name_sym = (Sym)attrs.section;
    267     } else {
    268       split_base = SLICE_LIT(".bss");
    269       sec_name_sym = pool_intern_slice(c->global, split_base);
    270     }
    271   } else if (attrs.section) {
    272     sec_name_sym = (Sym)attrs.section;
    273     if (attrs.flags & KIT_CG_DATADEF_READONLY) {
    274       sec_kind = SEC_RODATA;
    275       sec_flags = SF_ALLOC;
    276     } else {
    277       sec_kind = SEC_OTHER;
    278       sec_flags = SF_ALLOC | SF_WRITE;
    279     }
    280   } else if ((attrs.flags & KIT_CG_DATADEF_READONLY) ||
    281              (decl_attrs.as.object.flags & KIT_CG_OBJ_READONLY)) {
    282     sec_kind = SEC_RODATA;
    283     sec_flags = SF_ALLOC;
    284     split_base = SLICE_LIT(".rodata");
    285     sec_name_sym = pool_intern_slice(c->global, split_base);
    286   } else if (decl_attrs.as.object.flags & KIT_CG_OBJ_TLS) {
    287     sec_kind = SEC_DATA;
    288     sec_flags = SF_ALLOC | SF_WRITE | SF_TLS;
    289     sec_name_sym = obj_secname_tdata(c);
    290     split_base = pool_slice(c->global, sec_name_sym);
    291   } else {
    292     sec_kind = SEC_DATA;
    293     sec_flags = SF_ALLOC | SF_WRITE;
    294     split_base = SLICE_LIT(".data");
    295     sec_name_sym = pool_intern_slice(c->global, split_base);
    296   }
    297   if (!attrs.section && g->data_sections && split_base.len) {
    298     atomize = obj_format_split_sections_as_atoms(c);
    299     if (!atomize) {
    300       Sym split_name =
    301           api_cg_symbol_section_name(g, split_base, decl_attrs.linkage_name);
    302       if (split_name) sec_name_sym = split_name;
    303     }
    304   }
    305   if (attrs.flags & KIT_CG_DATADEF_RETAIN) sec_flags |= SF_RETAIN;
    306   if (attrs.flags & KIT_CG_DATADEF_MERGE) sec_flags |= SF_MERGE;
    307   if (attrs.flags & KIT_CG_DATADEF_STRINGS) sec_flags |= SF_STRINGS;
    308   if ((attrs.flags & KIT_CG_DATADEF_ZERO_FILL) && atomize &&
    309       obj_format_split_sections_as_atoms(c)) {
    310     sec = obj_section(ob, sec_name_sym, sec_kind, sec_flags, align);
    311   } else if (attrs.flags & KIT_CG_DATADEF_ZERO_FILL) {
    312     sec = obj_section_ex(ob, sec_name_sym, sec_kind, SSEM_NOBITS, sec_flags,
    313                          align, 0, OBJ_SEC_NONE, 0);
    314   } else if (attrs.entsize) {
    315     sec = obj_section_ex(ob, sec_name_sym, sec_kind, SSEM_PROGBITS, sec_flags,
    316                          align, attrs.entsize, OBJ_SEC_NONE, 0);
    317   } else {
    318     sec = obj_section(ob, sec_name_sym, sec_kind, sec_flags, align);
    319   }
    320   g->data_sec = sec;
    321   g->data_sym = sym;
    322   g->data_base = obj_align_to(ob, sec, align);
    323   g->data_size = 0;
    324   g->data_atomize = atomize ? 1u : 0u;
    325   g->data_retain = (attrs.flags & KIT_CG_DATADEF_RETAIN) ? 1u : 0u;
    326   if (sym != OBJ_SYM_NONE) {
    327     api_data_apply_symbol_attrs(g, sym, &decl_attrs);
    328     obj_symbol_define(ob, sym, sec, (u64)g->data_base,
    329                       (u64)abi_cg_sizeof(c->abi, decl_attrs.type));
    330     api_data_mark_defined_unit(g, sym);
    331   }
    332 }
    333 
    334 void kit_cg_data_common(KitCg* g, KitCgSym cg_sym, uint64_t size,
    335                         uint32_t align) {
    336   ObjSym* osym;
    337   ObjSymId sym;
    338   KitCgDecl decl_attrs;
    339   if (!g || cg_sym == KIT_CG_SYM_NONE) return;
    340   sym = (ObjSymId)cg_sym;
    341   osym = (ObjSym*)obj_symbol_get(g->obj, sym);
    342   if (!osym) return;
    343   decl_attrs = api_sym_attrs(g, cg_sym);
    344   if (symresolve_sym_is_def(osym) && !api_data_defined_this_unit(g, sym)) {
    345     SymAttrs old_attrs = api_data_sym_attrs(osym);
    346     SymAttrs new_attrs = api_data_decl_attrs(g->c, &decl_attrs, size, align);
    347     SymMergeResult mr;
    348     new_attrs.kind = SK_COMMON;
    349     mr = symresolve_merge(old_attrs, new_attrs);
    350     switch (mr.kind) {
    351       case SYM_MERGE_COMMON:
    352         osym->bind = new_attrs.bind;
    353         osym->vis = api_map_vis(decl_attrs.sym.visibility);
    354         osym->kind = SK_COMMON;
    355         osym->section_id = OBJ_SEC_NONE;
    356         osym->value = 0;
    357         osym->size = size;
    358         osym->common_align = mr.merged_align;
    359         return;
    360       case SYM_MERGE_REPLACE:
    361         break;
    362       case SYM_MERGE_KEEP_EXISTING:
    363       case SYM_MERGE_COMDAT_DISCARD:
    364         return;
    365       case SYM_MERGE_ODR_ERROR:
    366         compiler_panic(g->c, g->cur_loc, "duplicate definition of symbol");
    367     }
    368   }
    369   osym->bind = api_map_bind(decl_attrs.sym.bind);
    370   osym->vis = api_map_vis(decl_attrs.sym.visibility);
    371   osym->kind = SK_COMMON;
    372   osym->section_id = OBJ_SEC_NONE;
    373   osym->value = 0;
    374   osym->size = size;
    375   osym->common_align = align;
    376   api_data_mark_defined_unit(g, sym);
    377 }
    378 
    379 void kit_cg_data_align(KitCg* g, uint32_t align) {
    380   if (g && g->data_discard) return;
    381   if (g && g->data_local_static_target) {
    382     u32 a = align ? align : 1u;
    383     u64 base = (g->data_size + (a - 1u)) & ~(u64)(a - 1u);
    384     u64 pad = base - g->data_size;
    385     if (pad) kit_cg_data_zero(g, pad);
    386     return;
    387   }
    388   if (g && g->data_tls_collect) {
    389     u32 a = align ? align : 1u;
    390     u64 base = (g->data_size + (a - 1u)) & ~(u64)(a - 1u);
    391     u64 pad = base - g->data_size;
    392     if (pad) {
    393       if (g->data_tls_zero_fill) {
    394         g->data_size += pad;
    395       } else {
    396         api_data_tls_write_zero(g, pad);
    397         g->data_size += pad;
    398       }
    399     }
    400     return;
    401   }
    402   if (!g || g->data_sec == OBJ_SEC_NONE || !align) return;
    403   g->data_size = obj_align_to(g->obj, g->data_sec, align) - g->data_base;
    404 }
    405 
    406 void kit_cg_data_pad(KitCg* g, uint64_t size, uint8_t value) {
    407   u8 pad[64];
    408   if (!g || !size) return;
    409   if (g->data_discard) return;
    410   if (g->data_local_static_target) {
    411     if (value == 0) {
    412       kit_cg_data_zero(g, size);
    413       return;
    414     }
    415     memset(pad, value, sizeof pad);
    416     while (size >= sizeof pad) {
    417       g->target->local_static_data_write(g->target, pad, sizeof pad);
    418       size -= sizeof pad;
    419       g->data_size += sizeof pad;
    420     }
    421     if (size) {
    422       g->target->local_static_data_write(g->target, pad, size);
    423       g->data_size += size;
    424     }
    425     return;
    426   }
    427   if (g->data_tls_collect) {
    428     if (value == 0 && g->data_tls_zero_fill) {
    429       g->data_size += size;
    430       return;
    431     }
    432     api_data_tls_ensure_materialized(g);
    433     memset(pad, value, sizeof pad);
    434     while (size >= sizeof pad) {
    435       buf_write(&g->data_tls_bytes, pad, sizeof pad);
    436       size -= sizeof pad;
    437       g->data_size += sizeof pad;
    438     }
    439     if (size) {
    440       buf_write(&g->data_tls_bytes, pad, (size_t)size);
    441       g->data_size += size;
    442     }
    443     return;
    444   }
    445   memset(pad, value, sizeof(pad));
    446   while (size >= sizeof(pad)) {
    447     obj_write(g->obj, g->data_sec, pad, sizeof(pad));
    448     size -= sizeof(pad);
    449     g->data_size += sizeof(pad);
    450   }
    451   if (size) {
    452     obj_write(g->obj, g->data_sec, pad, (size_t)size);
    453     g->data_size += size;
    454   }
    455 }
    456 
    457 void kit_cg_data_int(KitCg* g, uint64_t value, KitCgTypeId type) {
    458   KitCgTypeId ty;
    459   u32 size;
    460   u8 bytes[8];
    461   if (!g) return;
    462   if (g->data_discard) return;
    463   ty = resolve_type(g->c, type);
    464   if (!ty) return;
    465   size = (u32)abi_cg_sizeof(g->c->abi, type);
    466   if (size > sizeof(bytes)) return;
    467   for (u32 i = 0; i < size; ++i) {
    468     u32 shift = g->c->target.big_endian ? (size - 1u - i) * 8u : i * 8u;
    469     bytes[i] = (u8)(value >> shift);
    470   }
    471   kit_cg_data_bytes(g, bytes, size);
    472 }
    473 
    474 void kit_cg_data_float(KitCg* g, double value, KitCgTypeId type) {
    475   KitCgTypeId ty;
    476   union {
    477     float f;
    478     double d;
    479     u8 b[8];
    480   } u;
    481   if (!g) return;
    482   if (g->data_discard) return;
    483   ty = resolve_type(g->c, type);
    484   if (!ty) return;
    485   if (api_is_f128_type(g->c, ty)) {
    486     u8 bytes[16];
    487     api_encode_binary128_from_double(g, value, bytes);
    488     kit_cg_data_bytes(g, bytes, sizeof bytes);
    489     return;
    490   }
    491   if (ty == builtin_id(KIT_CG_BUILTIN_F32)) {
    492     u.f = (float)value;
    493     if (g->c->target.big_endian) {
    494       u8 t = u.b[0];
    495       u.b[0] = u.b[3];
    496       u.b[3] = t;
    497       t = u.b[1];
    498       u.b[1] = u.b[2];
    499       u.b[2] = t;
    500     }
    501     kit_cg_data_bytes(g, u.b, 4);
    502   } else if (ty == builtin_id(KIT_CG_BUILTIN_F64)) {
    503     u.d = value;
    504     if (g->c->target.big_endian) {
    505       for (u32 i = 0; i < 4; ++i) {
    506         u8 t = u.b[i];
    507         u.b[i] = u.b[7u - i];
    508         u.b[7u - i] = t;
    509       }
    510     }
    511     kit_cg_data_bytes(g, u.b, 8);
    512   }
    513 }
    514 
    515 void kit_cg_data_bytes(KitCg* g, const uint8_t* data, size_t len) {
    516   if (!g || !len) return;
    517   if (g->data_discard) return;
    518   if (g->data_local_static_target) {
    519     g->target->local_static_data_write(g->target, data, (u64)len);
    520     g->data_size += len;
    521     return;
    522   }
    523   if (g->data_tls_collect) {
    524     api_data_tls_write(g, data, len);
    525     return;
    526   }
    527   obj_write(g->obj, g->data_sec, data, len);
    528   g->data_size += len;
    529 }
    530 
    531 void kit_cg_data_zero(KitCg* g, uint64_t size) {
    532   const Section* sec;
    533   if (!g || !size) return;
    534   if (g->data_discard) return;
    535   if (g->data_local_static_target) {
    536     g->target->local_static_data_write(g->target, NULL, size);
    537     g->data_size += size;
    538     return;
    539   }
    540   if (g->data_tls_collect) {
    541     if (g->data_tls_zero_fill) {
    542       g->data_size += size;
    543     } else {
    544       api_data_tls_write_zero(g, size);
    545       g->data_size += size;
    546     }
    547     return;
    548   }
    549   sec = obj_section_get(g->obj, g->data_sec);
    550   if (sec && (sec->kind == SEC_BSS || sec->sem == SSEM_NOBITS)) {
    551     obj_reserve_bss(g->obj, g->data_sec,
    552                     g->data_base + (u32)(g->data_size + size), 0);
    553     g->data_size += size;
    554     return;
    555   }
    556   {
    557     u8 pad[64];
    558     memset(pad, 0, sizeof pad);
    559     u64 remaining = size;
    560     while (remaining >= sizeof pad) {
    561       obj_write(g->obj, g->data_sec, pad, sizeof pad);
    562       remaining -= sizeof pad;
    563     }
    564     if (remaining) obj_write(g->obj, g->data_sec, pad, (size_t)remaining);
    565   }
    566   g->data_size += size;
    567 }
    568 
    569 void api_cg_data_reloc(KitCg* g, KitCgSym target, int64_t addend,
    570                        uint32_t width, int pcrel) {
    571   ObjBuilder* ob;
    572   RelocKind rk;
    573   u8 pad[8];
    574   if (!g || !width || width > sizeof(pad)) return;
    575   if (g->data_discard) return;
    576   ob = g->obj;
    577   rk = api_data_reloc_kind(pcrel, width);
    578   if (rk == R_NONE) return;
    579   memset(pad, 0, sizeof pad);
    580   api_data_encode_addend(g, pad, width, addend);
    581   if (g->data_tls_collect) {
    582     api_data_tls_reloc(g, target, addend, rk);
    583     api_data_tls_write(g, pad, width);
    584     return;
    585   }
    586   obj_write(ob, g->data_sec, pad, width);
    587   obj_reloc(ob, g->data_sec, g->data_base + (u32)g->data_size, rk,
    588             (ObjSymId)target, addend);
    589   g->data_size += width;
    590 }
    591 
    592 void kit_cg_data_addr(KitCg* g, KitCgSym target, int64_t addend, uint32_t width,
    593                       uint32_t address_space) {
    594   (void)address_space;
    595   if (g && g->data_local_static_target) {
    596     compiler_panic(g->c, g->cur_loc,
    597                    "kit_cg_data_addr: function-local static data address "
    598                    "relocations are not yet supported by this target");
    599     return;
    600   }
    601   if (g && g->data_discard) return;
    602   api_cg_data_reloc(g, target, addend, width, 0);
    603 }
    604 
    605 void kit_cg_data_label_addr(KitCg* g, KitCgLabel target, int64_t addend,
    606                             uint32_t width, uint32_t address_space) {
    607   u8 pad[8];
    608   (void)target;
    609   (void)addend;
    610   (void)address_space;
    611   if (!g) return;
    612   if (g->data_discard) return;
    613   if (!width || width > sizeof(pad)) {
    614     compiler_panic(g->c, g->cur_loc,
    615                    "kit_cg_data_label_addr: width must be 1..%u, got %u",
    616                    (unsigned)sizeof(pad), (unsigned)width);
    617     return;
    618   }
    619   if (g->data_local_static_target) {
    620     g->target->local_static_data_label_addr(g->target, (Label)target, addend,
    621                                             width, address_space);
    622     g->data_size += width;
    623     return;
    624   }
    625   if (g->target && g->target->data_label_addr_unsupported_msg) {
    626     const char* msg = g->target->data_label_addr_unsupported_msg(g->target);
    627     if (msg) {
    628       compiler_panic(g->c, g->cur_loc, "%s", msg);
    629       return;
    630     }
    631   }
    632   compiler_panic(g->c, g->cur_loc,
    633                  "kit_cg_data_label_addr: target does not support "
    634                  "intra-function label addresses in data sections");
    635 }
    636 
    637 void kit_cg_data_pcrel(KitCg* g, KitCgSym target, int64_t addend,
    638                        uint32_t width) {
    639   if (g && g->data_local_static_target) {
    640     compiler_panic(g->c, g->cur_loc,
    641                    "kit_cg_data_pcrel: function-local static pcrel data is "
    642                    "not yet supported by this target");
    643     return;
    644   }
    645   if (g && g->data_discard) return;
    646   api_cg_data_reloc(g, target, addend, width, 1);
    647 }
    648 
    649 void kit_cg_data_symdiff(KitCg* g, KitCgSym lhs, KitCgSym rhs, int64_t addend,
    650                          uint32_t width) {
    651   u8 pad[8];
    652   RelocKind add_kind;
    653   RelocKind sub_kind;
    654   const ObjSym* lhs_sym;
    655   const ObjSym* rhs_sym;
    656   if (!g || width > sizeof(pad)) return;
    657   if (g->data_discard) return;
    658   if (g->data_local_static_target) {
    659     compiler_panic(g->c, g->cur_loc,
    660                    "kit_cg_data_symdiff: function-local static symdiff data "
    661                    "is not yet supported by this target");
    662     return;
    663   }
    664   lhs_sym = obj_symbol_get(g->obj, (ObjSymId)lhs);
    665   rhs_sym = obj_symbol_get(g->obj, (ObjSymId)rhs);
    666   if (lhs_sym && rhs_sym && lhs_sym->section_id != OBJ_SEC_NONE &&
    667       lhs_sym->section_id == rhs_sym->section_id) {
    668     u64 value = lhs_sym->value - rhs_sym->value + (u64)addend;
    669     for (u32 i = 0; i < width; ++i) pad[i] = (u8)(value >> (i * 8u));
    670     if (g->data_tls_collect) {
    671       api_data_tls_write(g, pad, width);
    672     } else {
    673       obj_write(g->obj, g->data_sec, pad, width);
    674       g->data_size += width;
    675     }
    676     return;
    677   }
    678   switch (width) {
    679     case 1:
    680       add_kind = R_ADD8;
    681       sub_kind = R_SUB8;
    682       break;
    683     case 2:
    684       add_kind = R_ADD16;
    685       sub_kind = R_SUB16;
    686       break;
    687     case 4:
    688       add_kind = R_ADD32;
    689       sub_kind = R_SUB32;
    690       break;
    691     case 8:
    692       add_kind = R_ADD64;
    693       sub_kind = R_SUB64;
    694       break;
    695     default:
    696       return;
    697   }
    698   memset(pad, 0, sizeof(pad));
    699   if (g->data_tls_collect) {
    700     api_data_tls_reloc(g, lhs, addend, add_kind);
    701     api_data_tls_reloc(g, rhs, 0, sub_kind);
    702     api_data_tls_write(g, pad, width);
    703     return;
    704   }
    705   obj_write(g->obj, g->data_sec, pad, width);
    706   obj_reloc(g->obj, g->data_sec, g->data_base + (u32)g->data_size, add_kind,
    707             (ObjSymId)lhs, addend);
    708   obj_reloc(g->obj, g->data_sec, g->data_base + (u32)g->data_size, sub_kind,
    709             (ObjSymId)rhs, 0);
    710   g->data_size += width;
    711 }
    712 
    713 void kit_cg_data_end(KitCg* g) {
    714   Heap* h;
    715   u8* flat;
    716   if (!g) return;
    717   if (g->data_discard) {
    718     api_data_clear_state(g);
    719     return;
    720   }
    721   if (g->data_local_static_target) {
    722     g->target->local_static_data_end(g->target);
    723     api_data_clear_state(g);
    724     return;
    725   }
    726   if (g->data_tls_collect) {
    727     KitCgDecl decl_attrs = api_sym_attrs(g, (KitCgSym)g->data_sym);
    728     h = (Heap*)g->c->ctx->heap;
    729     flat = NULL;
    730     if (!g->data_tls_zero_fill && g->data_size) {
    731       flat = (u8*)h->alloc(h, (size_t)g->data_size, 1);
    732       if (!flat)
    733         compiler_panic(g->c, api_no_loc(), "KitCg: oom on TLS data bytes");
    734       buf_flatten(&g->data_tls_bytes, flat);
    735     }
    736     api_data_apply_symbol_attrs(g, g->data_sym, &decl_attrs);
    737     obj_define_tls(g->c, g->obj, g->data_sym,
    738                    g->data_tls_zero_fill ? NULL : flat, (u32)g->data_size,
    739                    g->data_tls_zero_fill ? 0 : 1, g->data_tls_align,
    740                    g->data_tls_relocs, g->data_tls_nrelocs);
    741     if (flat) h->free(h, flat, (size_t)g->data_size);
    742     buf_fini(&g->data_tls_bytes);
    743     if (g->data_tls_relocs)
    744       h->free(h, g->data_tls_relocs,
    745               sizeof(*g->data_tls_relocs) * g->data_tls_relocs_cap);
    746     g->data_tls_relocs = NULL;
    747     g->data_tls_relocs_cap = 0;
    748     g->data_tls_nrelocs = 0;
    749     g->data_tls_collect = 0;
    750     g->data_tls_zero_fill = 0;
    751     g->data_tls_align = 0;
    752     api_data_clear_state(g);
    753     return;
    754   }
    755   if (g->data_sym != OBJ_SYM_NONE) {
    756     KitCgDecl decl_attrs = api_sym_attrs(g, (KitCgSym)g->data_sym);
    757     api_data_apply_symbol_attrs(g, g->data_sym, &decl_attrs);
    758     obj_symbol_define(g->obj, g->data_sym, g->data_sec, g->data_base,
    759                       g->data_size);
    760   }
    761   if (g->data_atomize) {
    762     obj_atom_define(g->obj, g->data_sec, g->data_base, (u32)g->data_size,
    763                     g->data_sym, g->data_retain ? OBJ_ATOM_RETAIN : 0u);
    764   }
    765   api_data_clear_state(g);
    766 }
    767 
    768 /* Source targets with a native switch form should override target->switch_.
    769  * The old machine-code jump-table path is intentionally not part of the
    770  * semantic CgTarget cutover. */
    771 ObjSymId api_emit_label_table(KitCg* g, const Label* labels, u32 n) {
    772   Compiler* c;
    773   ObjSymId sym;
    774   KitCgTypeId void_ptr_ty;
    775   KitCgTypeId arr_ty;
    776   CGLocalStaticDataDesc desc;
    777   KitCgDataDefAttrs attrs;
    778   KitCgDecl decl;
    779   char name_buf[32];
    780   StrBuf name_sb;
    781   Sym name;
    782   if (!g || !labels || !n) return OBJ_SYM_NONE;
    783   if (!g->target || !g->target->local_static_data_begin ||
    784       !g->target->local_static_data_write ||
    785       !g->target->local_static_data_label_addr ||
    786       !g->target->local_static_data_end) {
    787     compiler_panic(g->c, g->cur_loc,
    788                    "api_emit_label_table: target does not support semantic "
    789                    "label tables");
    790   }
    791   c = g->c;
    792   strbuf_init(&name_sb, name_buf, sizeof name_buf);
    793   strbuf_put_slice(&name_sb, SLICE_LIT(".Lkit_jt."));
    794   strbuf_put_u64(&name_sb, g->rodata_counter++);
    795   name = pool_intern_slice(c->global, (Slice){.s = strbuf_cstr(&name_sb),
    796                                               .len = strbuf_len(&name_sb)});
    797   sym = obj_symbol_defer(g->obj, name, SB_LOCAL, SV_DEFAULT, SK_OBJ,
    798                          (u64)n * (u64)c->target.ptr_size);
    799   if (sym == OBJ_SYM_NONE)
    800     compiler_panic(c, g->cur_loc, "api_emit_label_table: symbol failed");
    801 
    802   void_ptr_ty = cg_type_ptr_to(c, builtin_id(KIT_CG_BUILTIN_VOID));
    803   arr_ty = kit_cg_type_array((KitCompiler*)c, void_ptr_ty, n);
    804   memset(&decl, 0, sizeof decl);
    805   decl.kind = KIT_CG_DECL_OBJECT;
    806   decl.sym.bind = KIT_SB_LOCAL;
    807   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    808   decl.as.object.flags = KIT_CG_OBJ_READONLY;
    809   api_remember_sym(g, sym, arr_ty, decl);
    810 
    811   memset(&attrs, 0, sizeof attrs);
    812   attrs.flags = KIT_CG_DATADEF_FUNCTION_LOCAL | KIT_CG_DATADEF_READONLY;
    813   attrs.align = (u32)c->target.ptr_align;
    814   memset(&desc, 0, sizeof desc);
    815   desc.sym = sym;
    816   desc.type = arr_ty;
    817   desc.attrs = attrs;
    818   desc.align = attrs.align;
    819   if (!g->target->local_static_data_begin(g->target, &desc)) {
    820     compiler_panic(c, g->cur_loc,
    821                    "api_emit_label_table: target rejected label table");
    822   }
    823   for (u32 i = 0; i < n; ++i) {
    824     g->target->local_static_data_label_addr(g->target, labels[i], 0,
    825                                             (u32)c->target.ptr_size, 0);
    826   }
    827   g->target->local_static_data_end(g->target);
    828   return sym;
    829 }