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 }