kit

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

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);