kit

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

registry.c (5272B)


      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 
     21 #if KIT_ARCH_AA64_ENABLED
     22 extern const ArchImpl arch_impl_aa64;
     23 #endif
     24 #if KIT_ARCH_RV32_ENABLED
     25 extern const ArchImpl arch_impl_rv32;
     26 #endif
     27 #if KIT_ARCH_RV64_ENABLED
     28 extern const ArchImpl arch_impl_rv64;
     29 #endif
     30 #if KIT_ARCH_X64_ENABLED
     31 extern const ArchImpl arch_impl_x64;
     32 #endif
     33 #if KIT_ARCH_C_TARGET_ENABLED
     34 extern const CGBackend cg_backend_c_target;
     35 #endif
     36 extern const CGBackend cg_backend_check;
     37 #if KIT_ARCH_WASM_ENABLED
     38 extern const ArchImpl arch_impl_wasm;
     39 #endif
     40 
     41 /* Arch-metadata roster. The arch_lookup_* helpers iterate this list when a
     42  * caller needs machine-arch metadata — answers only come from backends that
     43  * have an ArchImpl, so c_target is intentionally absent.
     44  * cg_backend_for_session() picks the CGBackend (which is &impl->backend or
     45  * &cg_backend_c_target) without consulting this list. */
     46 static const ArchImpl* const arch_impls[] = {
     47 #if KIT_ARCH_AA64_ENABLED
     48     &arch_impl_aa64,
     49 #endif
     50 #if KIT_ARCH_X64_ENABLED
     51     &arch_impl_x64,
     52 #endif
     53 #if KIT_ARCH_RV32_ENABLED
     54     &arch_impl_rv32,
     55 #endif
     56 #if KIT_ARCH_RV64_ENABLED
     57     &arch_impl_rv64,
     58 #endif
     59 #if KIT_ARCH_WASM_ENABLED
     60     &arch_impl_wasm,
     61 #endif
     62 #if !KIT_ARCH_AA64_ENABLED && !KIT_ARCH_X64_ENABLED && \
     63     !KIT_ARCH_RV32_ENABLED && !KIT_ARCH_RV64_ENABLED && !KIT_ARCH_WASM_ENABLED
     64     NULL,
     65 #endif
     66 };
     67 
     68 static u32 arch_impls_count(void) {
     69   return (u32)(sizeof arch_impls / sizeof arch_impls[0]);
     70 }
     71 
     72 const char* arch_kind_name(KitArchKind arch) {
     73   switch (arch) {
     74     case KIT_ARCH_X86_32:
     75       return "x86_32";
     76     case KIT_ARCH_X86_64:
     77       return "x86_64";
     78     case KIT_ARCH_ARM_32:
     79       return "arm32";
     80     case KIT_ARCH_ARM_64:
     81       return "aarch64";
     82     case KIT_ARCH_RV32:
     83       return "riscv32";
     84     case KIT_ARCH_RV64:
     85       return "riscv64";
     86     case KIT_ARCH_WASM:
     87       return "wasm";
     88   }
     89   return "unknown";
     90 }
     91 
     92 const ArchImpl* arch_lookup(KitArchKind arch) {
     93   for (u32 i = 0; i < arch_impls_count(); ++i) {
     94     if (arch_impls[i] && arch_impls[i]->kind == arch) return arch_impls[i];
     95   }
     96   return NULL;
     97 }
     98 
     99 const ArchImpl* arch_for_compiler(const Compiler* c) {
    100   if (!c) return NULL;
    101   return arch_lookup(c->target.arch);
    102 }
    103 
    104 int arch_target_feature_index(const ArchImpl* a, KitSlice name, u32* idx_out) {
    105   u32 i;
    106   if (!a || !name.s) return 0;
    107   for (i = 0; i < a->ntarget_features; ++i) {
    108     if (kit_slice_eq_cstr(name, a->target_features[i].name)) {
    109       if (idx_out) *idx_out = i;
    110       return 1;
    111     }
    112   }
    113   return 0;
    114 }
    115 
    116 void arch_target_feature_defaults(const ArchImpl* a, const Target* target,
    117                                   u64* words, u32 nwords) {
    118   if (!a || !words || nwords == 0) return;
    119   if (a->target_feature_defaults) {
    120     a->target_feature_defaults(target, words, nwords);
    121   }
    122 }
    123 
    124 KitStatus arch_target_feature_apply_isa(const ArchImpl* a, const Target* target,
    125                                         KitSlice isa, u64* words, u32 nwords) {
    126   if (!a || !isa.s || isa.len == 0) return KIT_OK;
    127   if (!words && nwords != 0) return KIT_INVALID;
    128   if (!a->target_feature_apply_isa) return KIT_UNSUPPORTED;
    129   return a->target_feature_apply_isa(target, isa, words, nwords);
    130 }
    131 
    132 int arch_reloc_operand(const Compiler* c, u16 reloc_kind,
    133                        ArchRelocOperand* out) {
    134   const ArchImpl* a = arch_for_compiler(c);
    135   if (!a || !a->asm_ops || !a->asm_ops->reloc_operand) return 0;
    136   return a->asm_ops->reloc_operand(reloc_kind, c->target.obj, out);
    137 }
    138 
    139 int arch_is_local_branch(const Compiler* c, KitSlice mnemonic) {
    140   const ArchImpl* a = arch_for_compiler(c);
    141   if (!a || !a->asm_ops || !a->asm_ops->is_local_branch) return 0;
    142   return a->asm_ops->is_local_branch(mnemonic);
    143 }
    144 
    145 int arch_reloc_call_pair(const Compiler* c, u16 reloc_kind,
    146                          KitSlice pair_mnemonic, KitSlice pair_ops,
    147                          const char** mnemonic_out) {
    148   const ArchImpl* a = arch_for_compiler(c);
    149   if (!a || !a->asm_ops || !a->asm_ops->reloc_call_pair) return 0;
    150   return a->asm_ops->reloc_call_pair(reloc_kind, pair_mnemonic, pair_ops,
    151                                      mnemonic_out);
    152 }
    153 
    154 const CGBackend* cg_backend_for_session(const Compiler* c,
    155                                         const KitCodeOptions* opts) {
    156   if (opts && opts->check_only) {
    157     return &cg_backend_check;
    158   }
    159   if (opts && opts->emit_c_source) {
    160 #if KIT_ARCH_C_TARGET_ENABLED
    161     return &cg_backend_c_target;
    162 #else
    163     return NULL;
    164 #endif
    165   }
    166   {
    167     const ArchImpl* impl = arch_for_compiler(c);
    168     return impl ? &impl->backend : NULL;
    169   }
    170 }