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 }