kit

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

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:
Msrc/api/object_detect.c | 84++++++++++++++++++++++++++++++++-----------------------------------------------
Msrc/api/source.c | 21+++------------------
Mtest/coff/kit-roundtrip-coff.c | 24++++++++++++++++++++++++
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];