commit 557ef189d7571446bc3e5130a23aadeed4825e0d
parent c55dd9714a923b709a594fcabba01ed5a9447fc6
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 14 May 2026 12:26:43 -0700
Route ABI selection through arch descriptors
Diffstat:
6 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/doc/arch-registration-plan.md b/doc/arch-registration-plan.md
@@ -4,7 +4,7 @@
- [x] Introduce one internal arch descriptor and registry lookup.
- [x] Route existing arch dispatchers through that descriptor without changing behavior.
-- [ ] Move ABI selection behind the arch descriptor.
+- [x] Move ABI selection behind the arch descriptor.
- [ ] Move object-format relocation translators behind the arch descriptor.
- [ ] Move linker-only arch constants and stub emitters fully behind the descriptor.
- [ ] Move assembler/disassembler/register helpers behind arch-owned implementation files.
diff --git a/src/abi/abi.c b/src/abi/abi.c
@@ -5,10 +5,9 @@
* before calling into this layer.
*
* Per-ABI bits (function classification, __va_list shape) live in
- * abi_aapcs64.c, abi_sysv_x64.c, ... abi_init switches on
- * (target.arch, target.os) and installs the right vtable. The C-
- * standard-driven scalar profile and record layout stay here so all
- * ABIs share one impl. */
+ * abi_aapcs64.c, abi_sysv_x64.c, ... The active arch descriptor selects the
+ * ABI vtable for (target.arch, target.os). The C-standard-driven scalar
+ * profile and record layout stay here so all ABIs share one impl. */
#include "abi/abi.h"
@@ -17,6 +16,7 @@
#include "abi/abi_internal.h"
#include "api/cg_type.h"
+#include "arch/arch.h"
#include "core/arena.h"
#include "core/core.h"
@@ -201,29 +201,15 @@ ABITypeInfo abi_va_list_info(TargetABI* a) { return a->vt->va_list_info; }
/* ---- lifecycle ---- */
-/* Vtable selection keys on (arch, os): the Apple variants of the
- * ARM64 / x86_64 ABIs differ from AAPCS64 / SysV-x64 in calling
- * convention details (variadic-on-stack, va_list shape, stack-arg
- * promotion). Microsoft x64 / Windows-on-ARM64 will land here as
- * additional (arch, OS_WINDOWS) cases when COFF support arrives. */
static const ABIVtable* select_vtable(Compiler* c) {
- switch (c->target.arch) {
- case CFREE_ARCH_ARM_64:
- switch (c->target.os) {
- case CFREE_OS_MACOS:
- return &apple_arm64_vtable;
- default:
- return &aapcs64_vtable;
- }
- case CFREE_ARCH_X86_64:
- return &sysv_x64_vtable;
- case CFREE_ARCH_RV64:
- return &rv64_vtable;
- default: {
- SrcLoc loc = {0, 0, 0};
- compiler_panic(c, loc, "abi_init: unsupported target arch %d",
- (int)c->target.arch);
- }
+ const ArchImpl* arch = arch_for_compiler(c);
+ if (arch && arch->abi_vtable) {
+ return arch->abi_vtable(c, c->target.os);
+ }
+ {
+ SrcLoc loc = {0, 0, 0};
+ compiler_panic(c, loc, "abi_init: unsupported target arch %d",
+ (int)c->target.arch);
}
}
diff --git a/src/arch/aarch64/arch.c b/src/arch/aarch64/arch.c
@@ -1,10 +1,21 @@
#include "arch/arch.h"
+#include "abi/abi_internal.h"
#include "arch/aa64.h"
#include "arch/aa64_disasm.h"
#include "arch/aa64_regs.h"
#include "link/link_arch.h"
+static const ABIVtable* aa64_abi_vtable(Compiler* c, CfreeOSKind os) {
+ (void)c;
+ switch (os) {
+ case CFREE_OS_MACOS:
+ return &apple_arm64_vtable;
+ default:
+ return &aapcs64_vtable;
+ }
+}
+
static int aa64_register_at_public(uint32_t idx, CfreeArchReg* out) {
if (!out) return 1;
return aa64_register_iter_get(idx, &out->dwarf_idx, &out->name);
@@ -13,6 +24,7 @@ static int aa64_register_at_public(uint32_t idx, CfreeArchReg* out) {
const ArchImpl arch_impl_aa64 = {
.kind = CFREE_ARCH_ARM_64,
.name = "aa64",
+ .abi_vtable = aa64_abi_vtable,
.cgtarget_new = aa64_cgtarget_new,
.disasm_new = aa64_disasm_new,
.link = &link_arch_aa64,
diff --git a/src/arch/arch.h b/src/arch/arch.h
@@ -701,11 +701,13 @@ struct ArchDisasm {
};
typedef struct LinkArchDesc LinkArchDesc;
+typedef struct ABIVtable ABIVtable;
typedef struct ArchImpl {
CfreeArchKind kind;
const char* name;
+ const ABIVtable* (*abi_vtable)(Compiler*, CfreeOSKind os);
CGTarget* (*cgtarget_new)(Compiler*, ObjBuilder*, MCEmitter*);
ArchDisasm* (*disasm_new)(Compiler*);
diff --git a/src/arch/rv64/arch.c b/src/arch/rv64/arch.c
@@ -1,11 +1,19 @@
#include "arch/arch.h"
+#include "abi/abi_internal.h"
#include "arch/rv64.h"
#include "link/link_arch.h"
+static const ABIVtable* rv64_abi_vtable(Compiler* c, CfreeOSKind os) {
+ (void)c;
+ (void)os;
+ return &rv64_vtable;
+}
+
const ArchImpl arch_impl_rv64 = {
.kind = CFREE_ARCH_RV64,
.name = "rv64",
+ .abi_vtable = rv64_abi_vtable,
.cgtarget_new = rv64_cgtarget_new,
.disasm_new = NULL,
.link = &link_arch_rv64,
diff --git a/src/arch/x64/arch.c b/src/arch/x64/arch.c
@@ -1,11 +1,19 @@
#include "arch/arch.h"
+#include "abi/abi_internal.h"
#include "arch/x64.h"
#include "link/link_arch.h"
+static const ABIVtable* x64_abi_vtable(Compiler* c, CfreeOSKind os) {
+ (void)c;
+ (void)os;
+ return &sysv_x64_vtable;
+}
+
const ArchImpl arch_impl_x64 = {
.kind = CFREE_ARCH_X86_64,
.name = "x64",
+ .abi_vtable = x64_abi_vtable,
.cgtarget_new = x64_cgtarget_new,
.disasm_new = NULL,
.link = &link_arch_x64,