session.c (16511B)
1 #include <kit/config.h> 2 3 #include "cg/internal.h" 4 5 #if KIT_OPT_ENABLED 6 #include "opt/opt.h" 7 #endif 8 9 #include "obj/symresolve.h" 10 #include "obj/wasm_imports.h" 11 12 static void cg_free_obj_state(KitCg* g) { 13 Heap* h; 14 if (!g) return; 15 h = g->c->ctx->heap; 16 if (g->stack) { 17 h->free(h, g->stack, sizeof(ApiSValue) * g->cap); 18 g->stack = NULL; 19 } 20 if (g->locals) { 21 h->free(h, g->locals, sizeof(*g->locals) * g->locals_cap); 22 g->locals = NULL; 23 } 24 if (g->sym_types) { 25 h->free(h, g->sym_types, sizeof(*g->sym_types) * g->sym_cap); 26 g->sym_types = NULL; 27 } 28 if (g->sym_attrs) { 29 h->free(h, g->sym_attrs, sizeof(*g->sym_attrs) * g->sym_cap); 30 g->sym_attrs = NULL; 31 } 32 if (g->sym_def_seq) { 33 h->free(h, g->sym_def_seq, sizeof(*g->sym_def_seq) * g->sym_def_seq_cap); 34 g->sym_def_seq = NULL; 35 g->sym_def_seq_cap = 0; 36 } 37 if (g->data_tls_collect) { 38 buf_fini(&g->data_tls_bytes); 39 g->data_tls_collect = 0; 40 } 41 if (g->data_tls_relocs) { 42 h->free(h, g->data_tls_relocs, 43 sizeof(*g->data_tls_relocs) * g->data_tls_relocs_cap); 44 g->data_tls_relocs = NULL; 45 } 46 g->sp = 0; 47 g->cap = 0; 48 g->nlocals = 0; 49 g->locals_cap = 0; 50 g->sym_cap = 0; 51 g->fn_ret_type = 0; 52 memset(&g->fn_desc, 0, sizeof(g->fn_desc)); 53 memset(g->fn_params, 0, sizeof(g->fn_params)); 54 memset(g->scopes, 0, sizeof(g->scopes)); 55 g->nscopes = 0; 56 g->scope_generation = 0; 57 g->rodata_counter = 0; 58 g->function_sections = 0; 59 g->data_sections = 0; 60 g->data_sec = OBJ_SEC_NONE; 61 g->data_sym = OBJ_SYM_NONE; 62 g->data_base = 0; 63 g->data_size = 0; 64 g->data_local_static_target = 0; 65 g->data_discard = 0; 66 g->data_tls_zero_fill = 0; 67 g->data_tls_align = 0; 68 g->data_tls_nrelocs = 0; 69 g->data_tls_relocs_cap = 0; 70 } 71 72 KitStatus kit_cg_new(KitCompiler* c, KitCg** cg_out) { 73 Heap* h; 74 KitCg* g; 75 if (!cg_out) return KIT_INVALID; 76 *cg_out = NULL; 77 if (!c) return KIT_INVALID; 78 h = (Heap*)c->ctx->heap; 79 g = (KitCg*)h->alloc(h, sizeof(KitCg), _Alignof(KitCg)); 80 if (!g) return KIT_NOMEM; 81 memset(g, 0, sizeof *g); 82 g->c = (Compiler*)c; 83 g->data_sec = OBJ_SEC_NONE; 84 g->data_sym = OBJ_SYM_NONE; 85 *cg_out = g; 86 return KIT_OK; 87 } 88 89 KitStatus kit_cg_begin(KitCg* g, KitObjBuilder* out, 90 const KitCodeOptions* opts) { 91 KitCompiler* c; 92 CgTarget* target; 93 const CGBackend* backend; 94 int opt_level = opts ? opts->opt_level : 0; 95 if (!g || !g->c || !out) return KIT_INVALID; 96 if (g->obj || g->target || g->debug || g->unit_active || g->finished) 97 return KIT_INVALID; 98 c = (KitCompiler*)g->c; 99 if (opt_level < 0 || opt_level > 2) { 100 compiler_panic((Compiler*)c, api_no_loc(), 101 "KitCg: unsupported opt_level %d", opt_level); 102 } 103 if (opts && opts->emit_ir && opt_level < 1) { 104 compiler_panic((Compiler*)c, api_no_loc(), 105 "KitCg: emit_ir requires opt_level >= 1 " 106 "(the IR tape is only recorded when the optimizer runs)"); 107 } 108 #if !KIT_OPT_ENABLED 109 if (opt_level > 0) { 110 compiler_panic((Compiler*)c, api_no_loc(), 111 "KitCg: opt_level %d requires KIT_OPT_ENABLED", opt_level); 112 } 113 #endif 114 backend = cg_backend_for_session((Compiler*)c, opts); 115 if (!backend) { 116 /* No CGBackend serves this request in this build. Distinguish the two 117 * causes so the failure is actionable instead of surfacing as a generic 118 * codegen error in each frontend. Consistent with the opt_level config 119 * panics above. */ 120 if (opts && opts->emit_c_source) 121 compiler_panic((Compiler*)c, api_no_loc(), 122 "KitCg: C-source backend not enabled in this build " 123 "(KIT_ARCH_C_TARGET_ENABLED)"); 124 compiler_panic((Compiler*)c, api_no_loc(), 125 "KitCg: no code generator for target arch '%s' — no " 126 "backend enabled in this build (KIT_ARCH_*_ENABLED)", 127 arch_kind_name(kit_compiler_target_spec(c).arch)); 128 } 129 target = backend->make((Compiler*)c, (ObjBuilder*)out, opts); 130 if (!target) return KIT_UNSUPPORTED; 131 /* The backend's make() creates the DWARF producer when opts->debug_info 132 * is set (NULL otherwise); capture it before any optimizer wrapper so the 133 * session can drive func/line/emit. The backend's MCEmitter holds the 134 * same Debug for line-row emission. */ 135 g->debug = target->debug; 136 #if KIT_OPT_ENABLED 137 if (opt_level > 0) { 138 target = opt_cgtarget_new((Compiler*)c, target, opt_level); 139 if (!target) return KIT_UNSUPPORTED; 140 if (opts && opts->emit_ir) 141 opt_set_dump_writer(target, (Writer*)opts->ir_dump_writer); 142 } 143 #endif 144 g->obj = (ObjBuilder*)out; 145 g->target = target; 146 g->opt_level = opt_level; 147 g->check_only = (opts && opts->check_only) ? 1u : 0u; 148 g->function_sections = (opts && opts->function_sections) ? 1u : 0u; 149 g->data_sections = (opts && opts->data_sections) ? 1u : 0u; 150 g->nsource_units = 0; 151 g->unit_active = 0; 152 g->finished = 0; 153 memset(&g->cur_unit, 0, sizeof(g->cur_unit)); 154 return KIT_OK; 155 } 156 157 KitStatus kit_cg_begin_unit(KitCg* g, const KitCgUnitOptions* opts) { 158 KitCgUnitOptions unit; 159 if (!g || !g->obj || !g->target) return KIT_INVALID; 160 if (g->finished || g->unit_active) return KIT_INVALID; 161 memset(&unit, 0, sizeof unit); 162 if (opts) { 163 if (opts->flags) return KIT_INVALID; 164 unit = *opts; 165 } 166 if (!unit.source_id) unit.source_id = g->nsource_units + 1u; 167 g->cur_unit = unit; 168 g->nsource_units++; 169 g->cur_unit_seq = g->nsource_units; /* nonzero, unique per unit */ 170 g->unit_active = 1; 171 return KIT_OK; 172 } 173 174 KitStatus kit_cg_end_unit(KitCg* g) { 175 if (!g || !g->obj || !g->target) return KIT_INVALID; 176 if (!g->unit_active) return KIT_INVALID; 177 g->unit_active = 0; 178 memset(&g->cur_unit, 0, sizeof(g->cur_unit)); 179 return KIT_OK; 180 } 181 182 KitStatus kit_cg_finish(KitCg* g, const KitCgFinishOptions* opts) { 183 CgFinishPolicy policy; 184 if (!g) return KIT_INVALID; 185 if (!g->obj || !g->target) return KIT_INVALID; 186 if (g->finished || g->unit_active) return KIT_INVALID; 187 memset(&policy, 0, sizeof policy); 188 if (opts) { 189 if (opts->output_kind > KIT_CG_OUTPUT_ARCHIVE_MEMBER) return KIT_INVALID; 190 if (opts->interposition_policy > KIT_CG_INTERPOSITION_DEFAULT_VISIBILITY) 191 return KIT_INVALID; 192 if (opts->npreserved_symbols && !opts->preserved_symbols) 193 return KIT_INVALID; 194 policy.output_kind = opts->output_kind; 195 policy.interposition_policy = opts->interposition_policy; 196 policy.preserved_symbols = (const ObjSymId*)opts->preserved_symbols; 197 policy.npreserved_symbols = opts->npreserved_symbols; 198 } 199 for (u32 i = 0; i < policy.npreserved_symbols; ++i) { 200 ObjSymId sym = policy.preserved_symbols[i]; 201 const ObjSym* os = obj_symbol_get(g->obj, sym); 202 if (sym == OBJ_SYM_NONE || !os || os->removed) return KIT_INVALID; 203 } 204 cgtarget_set_finish_policy(g->target, &policy); 205 #if KIT_OPT_ENABLED 206 /* opt_set_finish_policy treats the recorder's user as an OptImpl, which is 207 * only true when the optimizer wrapped the backend (opt_level > 0; see 208 * kit_cg_begin). At opt_level 0 g->target is the bare backend recorder — e.g. 209 * the C-source backend, whose user is a CTarget — so calling it there is a 210 * type confusion that corrupts the backend. Guard it the same way 211 * opt_set_dump_writer is guarded at its call site. */ 212 if (g->opt_level > 0) opt_set_finish_policy(g->target, &policy); 213 #endif 214 cgtarget_finalize(g->target); 215 if (g->debug) { 216 debug_emit(g->debug); 217 debug_free(g->debug); 218 g->debug = NULL; 219 } 220 g->finished = 1; 221 return KIT_OK; 222 } 223 224 KitStatus kit_cg_detach(KitCg* g) { 225 if (!g) return KIT_INVALID; 226 if (g->debug) { 227 debug_free(g->debug); 228 g->debug = NULL; 229 } 230 cgtarget_free(g->target); 231 g->obj = NULL; 232 g->target = NULL; 233 g->finished = 0; 234 g->unit_active = 0; 235 g->nsource_units = 0; 236 memset(&g->cur_unit, 0, sizeof(g->cur_unit)); 237 cg_free_obj_state(g); 238 return KIT_OK; 239 } 240 241 KitStatus kit_cg_abort(KitCg* g) { return kit_cg_detach(g); } 242 243 void kit_cg_free(KitCg* g) { 244 Heap* h; 245 if (!g) return; 246 h = g->c->ctx->heap; 247 (void)kit_cg_abort(g); 248 h->free(h, g, sizeof *g); 249 } 250 251 /* ============================================================ 252 * Source location 253 * ============================================================ */ 254 255 void kit_cg_set_loc(KitCg* g, KitSrcLoc loc) { 256 if (!g) return; 257 g->cur_loc = *(SrcLoc*)&loc; 258 if (g->debug) debug_set_pending_loc(g->debug, *(SrcLoc*)&loc); 259 if (g->target->set_loc) g->target->set_loc(g->target, *(SrcLoc*)&loc); 260 } 261 262 /* ============================================================ 263 * Function lifecycle 264 * ============================================================ */ 265 266 KitCgSym kit_cg_decl(KitCg* g, KitCgDecl decl) { 267 Compiler* c; 268 ObjBuilder* ob; 269 ObjSymId sym; 270 KitCgTypeId ty; 271 if (!g || !decl.linkage_name) return KIT_CG_SYM_NONE; 272 c = g->c; 273 ob = g->obj; 274 ty = resolve_type(c, decl.type); 275 if (!ty) return KIT_CG_SYM_NONE; 276 sym = (decl.sym.bind == KIT_SB_LOCAL) 277 ? OBJ_SYM_NONE 278 : obj_symbol_find(ob, (Sym)decl.linkage_name); 279 if (sym == OBJ_SYM_NONE) { 280 sym = obj_symbol_ex(ob, (Sym)decl.linkage_name, api_map_bind(decl.sym.bind), 281 api_map_vis(decl.sym.visibility), 282 api_decl_sym_kind(decl), OBJ_SEC_NONE, 0, 0, 0); 283 } else if (decl.sym.bind == KIT_SB_WEAK) { 284 /* C permits the `weak` attribute on any declaration of a symbol; a later 285 * weak (re)declaration demotes a previously-strong global to weak. Without 286 * this, a plain prototype followed by a `weak` definition would emit a 287 * strong global and collide with any strong override at link time. In a 288 * shared LTO builder, do not let a weak declaration from a later TU demote 289 * an already-defined strong symbol; merge policy handles that override. */ 290 const ObjSym* s = obj_symbol_get(ob, sym); 291 if (s && s->bind == SB_GLOBAL && !symresolve_sym_is_def(s)) 292 obj_symbol_set_bind(ob, sym, SB_WEAK); 293 } 294 if (decl.sym.flags) { 295 obj_symbol_set_flags(ob, sym, (u16)decl.sym.flags); 296 } 297 api_remember_sym(g, sym, ty, decl); 298 /* Forward wasm import overrides onto the ObjBuilder side-table so the wasm 299 * backend can find them when promoting an undefined function symbol into a 300 * `(import ...)` entry. Honored only by the wasm target — the storage cost 301 * for other backends is one heap allocation that no one reads. */ 302 if (decl.kind == KIT_CG_DECL_FUNC && 303 (decl.as.func.wasm_import_module || decl.as.func.wasm_import_name)) { 304 wasm_imports_set(ob, (Sym)decl.linkage_name, 305 (Sym)decl.as.func.wasm_import_module, 306 (Sym)decl.as.func.wasm_import_name); 307 } 308 return (KitCgSym)sym; 309 } 310 311 KitCgSym kit_cg_alias(KitCg* g, KitCgAlias alias) { 312 ObjBuilder* ob; 313 ObjSymId sym; 314 const ObjSym* ts; 315 KitCgDecl decl_attrs; 316 if (!g || !alias.linkage_name || alias.target == KIT_CG_SYM_NONE) { 317 return KIT_CG_SYM_NONE; 318 } 319 ob = g->obj; 320 sym = obj_symbol_find(ob, (Sym)alias.linkage_name); 321 ts = obj_symbol_get(ob, (ObjSymId)alias.target); 322 if (!ts) return KIT_CG_SYM_NONE; 323 if (sym == OBJ_SYM_NONE) { 324 sym = 325 obj_symbol_ex(ob, (Sym)alias.linkage_name, api_map_bind(alias.sym.bind), 326 api_map_vis(alias.sym.visibility), (SymKind)ts->kind, 327 ts->section_id, ts->value, ts->size, ts->common_align); 328 } else if (ts->section_id != OBJ_SEC_NONE) { 329 obj_symbol_define(ob, sym, ts->section_id, ts->value, ts->size); 330 } 331 if (alias.sym.flags) obj_symbol_set_flags(ob, sym, (u16)alias.sym.flags); 332 decl_attrs = api_sym_attrs(g, alias.target); 333 decl_attrs.sym = alias.sym; 334 api_remember_sym(g, sym, api_sym_type(g, alias.target), decl_attrs); 335 /* Notify the backend so it can mirror the alias in any output form that 336 * isn't a relocatable obj — e.g. the C-source target. Native machine-code 337 * backends leave this hook NULL because obj_symbol_define above already 338 * aliased the underlying bytes. */ 339 if (g->target && g->target->alias) { 340 g->target->alias(g->target, sym, (ObjSymId)alias.target, 341 api_sym_type(g, alias.target)); 342 } 343 return (KitCgSym)sym; 344 } 345 346 void kit_cg_func_begin_attrs(KitCg* g, KitCgSym cg_sym, 347 KitCgFuncAttrs begin_attrs) { 348 Compiler* c; 349 ObjBuilder* ob; 350 CgTarget* T; 351 ObjSymId sym; 352 ObjSecId text_sec; 353 KitCgTypeId fty; 354 KitCgDecl attrs; 355 Sym sec_name; 356 if (!g) return; 357 c = g->c; 358 ob = g->obj; 359 T = g->target; 360 sym = (ObjSymId)cg_sym; 361 fty = api_sym_type(g, cg_sym); 362 if (!fty) return; 363 attrs = api_sym_attrs(g, cg_sym); 364 365 sec_name = begin_attrs.section ? (Sym)begin_attrs.section 366 : (Sym)attrs.as.func.section; 367 int atomize = 0; 368 if (!sec_name && g->function_sections) { 369 atomize = obj_format_split_sections_as_atoms(c); 370 if (!atomize) { 371 sec_name = 372 api_cg_symbol_section_name(g, SLICE_LIT(".text"), attrs.linkage_name); 373 } 374 } 375 if (!sec_name) sec_name = pool_intern_slice(c->global, SLICE_LIT(".text")); 376 text_sec = obj_section(ob, sec_name, SEC_TEXT, SF_EXEC | SF_ALLOC, 4); 377 378 if (sym != OBJ_SYM_NONE) { 379 obj_symbol_define(ob, sym, text_sec, 0, 0); 380 } 381 382 memset(&g->fn_desc, 0, sizeof g->fn_desc); 383 g->fn_desc.sym = sym; 384 g->fn_desc.text_section_id = text_sec; 385 g->fn_desc.group_id = OBJ_GROUP_NONE; 386 g->fn_desc.fn_type = fty; 387 g->fn_desc.result_type = cg_type_func_result_id(c, fty); 388 g->fn_desc.loc = g->cur_loc; 389 g->fn_desc.sym_bind = api_map_bind(attrs.sym.bind); 390 g->fn_desc.sym_kind = SK_FUNC; 391 g->fn_desc.sym_vis = api_map_vis(attrs.sym.visibility); 392 g->fn_desc.atomize = atomize ? 1u : 0u; 393 if (attrs.as.func.flags & KIT_CG_FUNC_NORETURN) { 394 g->fn_desc.flags |= CGFD_NORETURN; 395 } 396 g->fn_desc.inline_policy = attrs.as.func.inline_policy; 397 if (begin_attrs.inline_policy != KIT_CG_INLINE_DEFAULT) 398 g->fn_desc.inline_policy = begin_attrs.inline_policy; 399 if (begin_attrs.flags & KIT_CG_FUNC_NORETURN) 400 g->fn_desc.flags |= CGFD_NORETURN; 401 402 g->fn_ret_type = cg_type_func_ret_id(c, fty); 403 g->nlocals = 0; 404 g->sp = 0; 405 406 if (g->debug) { 407 DebugTypeId dt = api_debug_type(g, fty); 408 if (dt != DEBUG_TYPE_NONE) debug_func_begin(g->debug, sym, dt, g->cur_loc); 409 } 410 T->func_begin(T, &g->fn_desc); 411 api_temp_locals_begin(g); 412 } 413 414 void kit_cg_func_begin(KitCg* g, KitCgSym cg_sym) { 415 KitCgFuncAttrs attrs; 416 memset(&attrs, 0, sizeof attrs); 417 kit_cg_func_begin_attrs(g, cg_sym, attrs); 418 } 419 420 static int api_source_local_debug_visible(const ApiSourceLocal* rec) { 421 u32 hidden_flags = KIT_CG_LOCAL_ARTIFICIAL | KIT_CG_LOCAL_OPTIMIZED_OUT | 422 KIT_CG_LOCAL_COMPILER_TEMP; 423 return rec && rec->name && (rec->attrs.flags & hidden_flags) == 0; 424 } 425 426 static int api_debug_var_loc_from_cg(CGDebugLoc in, DebugVarLoc* out) { 427 if (!out) return 0; 428 memset(out, 0, sizeof *out); 429 switch ((CGDebugLocKind)in.kind) { 430 case CG_DEBUG_LOC_FRAME: 431 out->kind = DVL_FRAME; 432 out->v.frame_ofs = in.v.frame_ofs; 433 return 1; 434 case CG_DEBUG_LOC_REG: 435 out->kind = DVL_REG; 436 out->v.reg = in.v.reg; 437 return 1; 438 case CG_DEBUG_LOC_GLOBAL: 439 out->kind = DVL_GLOBAL; 440 out->v.global = in.v.global; 441 return 1; 442 default: 443 return 0; 444 } 445 } 446 447 static void api_debug_emit_source_locals(KitCg* g) { 448 u32 i; 449 if (!g || !g->debug || !g->target || !g->target->local_debug_loc) return; 450 for (i = 0; i < g->nlocals; ++i) { 451 ApiSourceLocal* rec = &g->locals[i]; 452 CGDebugLoc cg_loc; 453 DebugVarLoc dbg_loc; 454 DebugTypeId dbg_type; 455 if (!api_source_local_debug_visible(rec)) continue; 456 memset(&cg_loc, 0, sizeof cg_loc); 457 if (!g->target->local_debug_loc(g->target, rec->storage, &cg_loc)) continue; 458 if (!api_debug_var_loc_from_cg(cg_loc, &dbg_loc)) continue; 459 dbg_type = api_debug_type(g, rec->type); 460 if (dbg_type == DEBUG_TYPE_NONE) continue; 461 if (rec->kind == API_SOURCE_LOCAL_PARAM) { 462 debug_param(g->debug, (Sym)rec->name, dbg_type, rec->loc, 463 rec->param_index, dbg_loc); 464 } else { 465 debug_local(g->debug, (Sym)rec->name, dbg_type, rec->loc, dbg_loc); 466 } 467 } 468 } 469 470 void kit_cg_func_end(KitCg* g) { 471 if (!g) return; 472 api_temp_locals_finish(g); 473 g->target->func_end(g->target); 474 api_debug_emit_source_locals(g); 475 if (g->debug) debug_func_end(g->debug); 476 g->fn_ret_type = KIT_CG_TYPE_NONE; 477 g->nscopes = 0; 478 memset(g->scopes, 0, sizeof g->scopes); 479 } 480 481 void api_call_symbol_common(KitCg* g, KitCgSym sym, uint32_t nargs, 482 KitCgCallAttrs attrs);