kit

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

registry.c (5873B)


      1 /* CGBackend / ArchImpl registry.
      2  *
      3  * This file is the *only* place in the codebase that checks
      4  * KIT_ARCH_*_ENABLED. Everything downstream operates on the registry's
      5  * outputs — `const CGBackend*` for session-level code emission, and
      6  * `const ArchImpl*` for arch-specific metadata (DWARF, debugger hooks,
      7  * register file, etc.).
      8  *
      9  * Conceptually:
     10  *   - A CGBackend is "something that can build a CgTarget from a Compiler +
     11  *     ObjBuilder + KitCodeOptions". Machine-code arches and c_target both
     12  *     qualify.
     13  *   - An ArchImpl is a CGBackend plus the machine-code metadata (its first
     14  *     field is a CGBackend, so `(const CGBackend*)&arch_impl_x` is valid).
     15  *   - c_target has no ArchImpl — it is a CGBackend and nothing more.
     16  */
     17 
     18 #include "arch/arch.h"
     19 #include "kit/config.h"
     20 #include "kit/target.h"
     21 
     22 #if KIT_ARCH_AA64_ENABLED
     23 extern const ArchImpl arch_impl_aa64;
     24 #endif
     25 #if KIT_ARCH_RV32_ENABLED
     26 extern const ArchImpl arch_impl_rv32;
     27 #endif
     28 #if KIT_ARCH_RV64_ENABLED
     29 extern const ArchImpl arch_impl_rv64;
     30 #endif
     31 #if KIT_ARCH_X64_ENABLED
     32 extern const ArchImpl arch_impl_x64;
     33 #endif
     34 #if KIT_ARCH_ARM32_ENABLED
     35 extern const ArchImpl arch_impl_arm32;
     36 #endif
     37 #if KIT_ARCH_C_TARGET_ENABLED
     38 extern const CGBackend cg_backend_c_target;
     39 #endif
     40 extern const CGBackend cg_backend_check;
     41 #if KIT_ARCH_WASM_ENABLED
     42 extern const ArchImpl arch_impl_wasm;
     43 #endif
     44 
     45 /* Arch-metadata roster. The arch_lookup_* helpers iterate this list when a
     46  * caller needs machine-arch metadata — answers only come from backends that
     47  * have an ArchImpl, so c_target is intentionally absent.
     48  * cg_backend_for_session() picks the CGBackend (which is &impl->backend or
     49  * &cg_backend_c_target) without consulting this list. */
     50 static const ArchImpl* const arch_impls[] = {
     51 #if KIT_ARCH_AA64_ENABLED
     52     &arch_impl_aa64,
     53 #endif
     54 #if KIT_ARCH_X64_ENABLED
     55     &arch_impl_x64,
     56 #endif
     57 #if KIT_ARCH_ARM32_ENABLED
     58     &arch_impl_arm32,
     59 #endif
     60 #if KIT_ARCH_RV32_ENABLED
     61     &arch_impl_rv32,
     62 #endif
     63 #if KIT_ARCH_RV64_ENABLED
     64     &arch_impl_rv64,
     65 #endif
     66 #if KIT_ARCH_WASM_ENABLED
     67     &arch_impl_wasm,
     68 #endif
     69 #if !KIT_ARCH_AA64_ENABLED && !KIT_ARCH_X64_ENABLED &&                       \
     70     !KIT_ARCH_ARM32_ENABLED && !KIT_ARCH_RV32_ENABLED &&                    \
     71     !KIT_ARCH_RV64_ENABLED && !KIT_ARCH_WASM_ENABLED
     72     NULL,
     73 #endif
     74 };
     75 
     76 static u32 arch_impls_count(void) {
     77   return (u32)(sizeof arch_impls / sizeof arch_impls[0]);
     78 }
     79 
     80 const char* arch_kind_name(KitArchKind arch) {
     81   /* The arch diagnostic-name table lives with the triple parser/renderer in
     82    * src/api/target.c so all arch-name spellings have one source. */
     83   return kit_target_arch_diag_name(arch);
     84 }
     85 
     86 const ArchImpl* arch_lookup(KitArchKind arch) {
     87   for (u32 i = 0; i < arch_impls_count(); ++i) {
     88     if (arch_impls[i] && arch_impls[i]->kind == arch) return arch_impls[i];
     89   }
     90   return NULL;
     91 }
     92 
     93 const ArchImpl* arch_for_compiler(const Compiler* c) {
     94   if (!c) return NULL;
     95   return arch_lookup(c->target.arch);
     96 }
     97 
     98 int arch_target_feature_index(const ArchImpl* a, KitSlice name, u32* idx_out) {
     99   u32 i;
    100   if (!a || !name.s) return 0;
    101   for (i = 0; i < a->ntarget_features; ++i) {
    102     if (kit_slice_eq_cstr(name, a->target_features[i].name)) {
    103       if (idx_out) *idx_out = i;
    104       return 1;
    105     }
    106   }
    107   return 0;
    108 }
    109 
    110 void arch_target_feature_defaults(const ArchImpl* a, const Target* target,
    111                                   u64* words, u32 nwords) {
    112   if (!a || !words || nwords == 0) return;
    113   if (a->target_feature_defaults) {
    114     a->target_feature_defaults(target, words, nwords);
    115   }
    116 }
    117 
    118 KitStatus arch_target_feature_apply_isa(const ArchImpl* a, const Target* target,
    119                                         KitSlice isa, u64* words, u32 nwords) {
    120   if (!a || !isa.s || isa.len == 0) return KIT_OK;
    121   if (!words && nwords != 0) return KIT_INVALID;
    122   if (!a->target_feature_apply_isa) return KIT_UNSUPPORTED;
    123   return a->target_feature_apply_isa(target, isa, words, nwords);
    124 }
    125 
    126 KitStatus arch_target_feature_apply_cpu(const ArchImpl* a, const Target* target,
    127                                         KitSlice cpu, u64* words, u32 nwords) {
    128   if (!a || !cpu.s || cpu.len == 0) return KIT_OK;
    129   if (!words && nwords != 0) return KIT_INVALID;
    130   /* An arch with no CPU axis ignores -mcpu= (no-op success), matching the way
    131    * non-RISC-V arches ignore -march= today (the spec selectors are advisory for
    132    * those targets). */
    133   if (!a->target_feature_apply_cpu) return KIT_OK;
    134   return a->target_feature_apply_cpu(target, cpu, words, nwords);
    135 }
    136 
    137 int arch_reloc_operand(const Compiler* c, u16 reloc_kind,
    138                        ArchRelocOperand* out) {
    139   const ArchImpl* a = arch_for_compiler(c);
    140   if (!a || !a->asm_ops || !a->asm_ops->reloc_operand) return 0;
    141   return a->asm_ops->reloc_operand(reloc_kind, c->target.obj, out);
    142 }
    143 
    144 int arch_is_local_branch(const Compiler* c, KitSlice mnemonic) {
    145   const ArchImpl* a = arch_for_compiler(c);
    146   if (!a || !a->asm_ops || !a->asm_ops->is_local_branch) return 0;
    147   return a->asm_ops->is_local_branch(mnemonic);
    148 }
    149 
    150 int arch_reloc_call_pair(const Compiler* c, u16 reloc_kind,
    151                          KitSlice pair_mnemonic, KitSlice pair_ops,
    152                          const char** mnemonic_out) {
    153   const ArchImpl* a = arch_for_compiler(c);
    154   if (!a || !a->asm_ops || !a->asm_ops->reloc_call_pair) return 0;
    155   return a->asm_ops->reloc_call_pair(reloc_kind, pair_mnemonic, pair_ops,
    156                                      mnemonic_out);
    157 }
    158 
    159 const CGBackend* cg_backend_for_session(const Compiler* c,
    160                                         const KitCodeOptions* opts) {
    161   if (opts && opts->check_only) {
    162     return &cg_backend_check;
    163   }
    164   if (opts && opts->emit_c_source) {
    165 #if KIT_ARCH_C_TARGET_ENABLED
    166     return &cg_backend_c_target;
    167 #else
    168     return NULL;
    169 #endif
    170   }
    171   {
    172     const ArchImpl* impl = arch_for_compiler(c);
    173     return impl ? &impl->backend : NULL;
    174   }
    175 }