commit 6ed292ae28aba49938fbbd848517724be0fee3a8
parent 26a7338891273c9c3c5d5b7b3a0710b002bc9bd3
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 3 Jun 2026 10:30:58 -0700
econ(obj-api-tables): table-drive COFF machine set; drop source.c temps
- object_detect.c: introduce one COFF_MACHINES[] {machine -> arch} table +
coff_machine_lookup(); route both kit_detect_fmt membership checks and
detect_coff's arch mapping through it. Unifies detect_coff to accept
ARM64EC (0xA641 -> AArch64), matching the two fmt sites and registry.c.
- source.c: drop the tmp/st out-param dance in kit_source_add_file/_memory/
_builtin; tail-call the internal source_add_* which already takes u32* out.
- test/coff: add detect_arm64ec asserting ARM64EC detects as COFF + AArch64.
(cherry picked from commit fc9936a09ee6364077fc2025844c81f1a7825dac)
Diffstat:
3 files changed, 61 insertions(+), 68 deletions(-)
diff --git a/src/api/object_detect.c b/src/api/object_detect.c
@@ -5,6 +5,35 @@
#include "core/core.h"
+/* COFF Machine numbers we recognize, mapped to their kit arch. ARM64EC
+ * (0xA641) is accepted as plain AArch64: the encoding is unchanged, only the
+ * ABI differs, and src/obj/registry.c aliases 0xA641 to ARM64 before lookup
+ * (coff.h documents ARM64EC as plain AArch64). Single source of truth for the
+ * two membership checks in kit_detect_fmt and the arch mapping in
+ * detect_coff. */
+static const struct {
+ u16 machine;
+ KitArchKind arch;
+} COFF_MACHINES[] = {
+ {0x8664, KIT_ARCH_X86_64}, {0x014C, KIT_ARCH_X86_32},
+ {0xAA64, KIT_ARCH_ARM_64}, {0xA641, KIT_ARCH_ARM_64},
+ {0x01C4, KIT_ARCH_ARM_32}, {0x5032, KIT_ARCH_RV32},
+ {0x5064, KIT_ARCH_RV64},
+};
+
+/* Look up a COFF Machine number. Returns 1 and sets *arch on a match, 0
+ * otherwise. *arch may be NULL when only membership matters. */
+static int coff_machine_lookup(u16 machine, KitArchKind* arch) {
+ size_t i;
+ for (i = 0; i < sizeof COFF_MACHINES / sizeof COFF_MACHINES[0]; i++) {
+ if (COFF_MACHINES[i].machine == machine) {
+ if (arch) *arch = COFF_MACHINES[i].arch;
+ return 1;
+ }
+ }
+ return 0;
+}
+
KitBinFmt kit_detect_fmt(const uint8_t* data, size_t len) {
u32 m;
u16 coff_machine;
@@ -36,20 +65,7 @@ KitBinFmt kit_detect_fmt(const uint8_t* data, size_t len) {
}
if (len >= 2) {
coff_machine = (u16)data[0] | ((u16)data[1] << 8);
- switch (coff_machine) {
- case 0x8664:
- case 0x014C:
- case 0xAA64:
- case 0xA641: /* ARM64EC — accept as a COFF flavour the ARM64
- * codegen / linker treat as plain AArch64 (the
- * encoding is unchanged; only the ABI differs,
- * and we link these objs into pure-AArch64
- * images). */
- case 0x01C4:
- case 0x5032:
- case 0x5064:
- return KIT_BIN_COFF;
- }
+ if (coff_machine_lookup(coff_machine, NULL)) return KIT_BIN_COFF;
}
/* Microsoft "short import" record: Sig1=0, Sig2=0xFFFF. Routed
* through read_coff (which dispatches to read_coff_short_import).
@@ -59,20 +75,7 @@ KitBinFmt kit_detect_fmt(const uint8_t* data, size_t len) {
if (len >= 8 && data[0] == 0x00 && data[1] == 0x00 && data[2] == 0xFF &&
data[3] == 0xFF) {
u16 mach = (u16)data[6] | ((u16)data[7] << 8);
- switch (mach) {
- case 0x8664:
- case 0x014C:
- case 0xAA64:
- case 0xA641: /* ARM64EC — accept as a COFF flavour the ARM64
- * codegen / linker treat as plain AArch64 (the
- * encoding is unchanged; only the ABI differs,
- * and we link these objs into pure-AArch64
- * images). */
- case 0x01C4:
- case 0x5032:
- case 0x5064:
- return KIT_BIN_COFF;
- }
+ if (coff_machine_lookup(mach, NULL)) return KIT_BIN_COFF;
}
return KIT_BIN_UNKNOWN;
}
@@ -154,33 +157,14 @@ static KitStatus detect_elf(const u8* d, size_t len, KitTargetSpec* out) {
static KitStatus detect_coff(const u8* d, size_t len, KitTargetSpec* out) {
u16 machine;
+ KitArchKind arch;
if (len < 2) return KIT_MALFORMED;
machine = (u16)d[0] | ((u16)d[1] << 8);
+ if (!coff_machine_lookup(machine, &arch)) return KIT_UNSUPPORTED;
detect_target_defaults(out);
out->obj = KIT_OBJ_COFF;
out->os = KIT_OS_WINDOWS;
- switch (machine) {
- case 0x8664:
- detect_set_ptr(out, KIT_ARCH_X86_64);
- break;
- case 0x014C:
- detect_set_ptr(out, KIT_ARCH_X86_32);
- break;
- case 0xAA64:
- detect_set_ptr(out, KIT_ARCH_ARM_64);
- break;
- case 0x01C4:
- detect_set_ptr(out, KIT_ARCH_ARM_32);
- break;
- case 0x5032:
- detect_set_ptr(out, KIT_ARCH_RV32);
- break;
- case 0x5064:
- detect_set_ptr(out, KIT_ARCH_RV64);
- break;
- default:
- return KIT_UNSUPPORTED;
- }
+ detect_set_ptr(out, arch);
return KIT_OK;
}
diff --git a/src/api/source.c b/src/api/source.c
@@ -8,35 +8,20 @@
KitStatus kit_source_add_file(KitCompiler* c, const char* path,
int system_header, uint32_t* file_id_out) {
- uint32_t tmp;
- KitStatus st;
if (!c || !file_id_out) return KIT_INVALID;
- st = source_add_file(c->sources, path, system_header, &tmp);
- if (st != KIT_OK) return st;
- *file_id_out = tmp;
- return KIT_OK;
+ return source_add_file(c->sources, path, system_header, file_id_out);
}
KitStatus kit_source_add_memory(KitCompiler* c, KitSlice name,
uint32_t* file_id_out) {
- uint32_t tmp;
- KitStatus st;
if (!c || !file_id_out) return KIT_INVALID;
- st = source_add_memory(c->sources, name, &tmp);
- if (st != KIT_OK) return st;
- *file_id_out = tmp;
- return KIT_OK;
+ return source_add_memory(c->sources, name, file_id_out);
}
KitStatus kit_source_add_builtin(KitCompiler* c, KitSlice name,
uint32_t* file_id_out) {
- uint32_t tmp;
- KitStatus st;
if (!c || !file_id_out) return KIT_INVALID;
- st = source_add_builtin(c->sources, name, &tmp);
- if (st != KIT_OK) return st;
- *file_id_out = tmp;
- return KIT_OK;
+ return source_add_builtin(c->sources, name, file_id_out);
}
KitStatus kit_source_add_include(KitCompiler* c, uint32_t includer_file_id,
diff --git a/test/coff/kit-roundtrip-coff.c b/test/coff/kit-roundtrip-coff.c
@@ -1363,6 +1363,29 @@ static void test_short_import_amd64(void) {
free_compiler(c);
}
+/* Format/target detection from raw header bytes. ARM64EC (Machine 0xA641)
+ * must be recognized as a COFF object and resolve to plain AArch64 — the
+ * encoding is identical to ARM64 and the linker/codegen treat it as such. */
+static void test_detect_arm64ec(void) {
+ /* Minimal COFF header prefix: Machine word then NumberOfSections. 0xA641
+ * is little-endian {0x41, 0xA6}. */
+ static const uint8_t arm64ec[] = {0x41, 0xA6, 0x00, 0x00};
+ static const uint8_t arm64[] = {0x64, 0xAA, 0x00, 0x00};
+ KitTarget t;
+ EXPECT(kit_detect_fmt(arm64ec, sizeof arm64ec) == KIT_BIN_COFF,
+ "ARM64EC machine not detected as COFF");
+ memset(&t, 0, sizeof t);
+ EXPECT(kit_detect_target(arm64ec, sizeof arm64ec, &t) == KIT_OK,
+ "kit_detect_target failed on ARM64EC");
+ EXPECT(t.arch == KIT_ARCH_ARM_64, "ARM64EC did not resolve to AArch64");
+ EXPECT(t.obj == KIT_OBJ_COFF, "ARM64EC obj fmt not COFF");
+ /* Sanity: plain ARM64 still resolves the same arch. */
+ memset(&t, 0, sizeof t);
+ EXPECT(kit_detect_target(arm64, sizeof arm64, &t) == KIT_OK,
+ "kit_detect_target failed on ARM64");
+ EXPECT(t.arch == KIT_ARCH_ARM_64, "ARM64 did not resolve to AArch64");
+}
+
/* ---- driver -------------------------------------------------------- */
typedef void (*TestFn)(void);
@@ -1393,6 +1416,7 @@ static const struct {
{"align_nibble", test_align_nibble},
{"empty_obj", test_empty_obj},
{"short_import_amd64", test_short_import_amd64},
+ {"detect_arm64ec", test_detect_arm64ec},
};
static const size_t NTESTS = sizeof TESTS / sizeof TESTS[0];