commit ecd87b418b7a7aa82599b42b633cbdf724c2e25c
parent 7e14bdec70dcc26fe4970524bbc3b36707097be5
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 16 Jul 2026 10:45:10 -0700
link: preserve explicit targets and RISC-V ABI flags
Diffstat:
3 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/driver/cmd/ld.c b/driver/cmd/ld.c
@@ -2935,7 +2935,7 @@ static int ld_run_link(LdOptions* o) {
* a freestanding (`*-none-elf`, EI_OSABI=STANDALONE) object means a
* freestanding link even if a foreign object (e.g. a clang-assembled startup
* stub, which stamps EI_OSABI=SysV and so decodes as Linux) appears first. */
- if (initial_nobject_files > 0) {
+ if (!o->target_explicit && initial_nobject_files > 0) {
KitTargetSpec detected;
if (kit_detect_target(obj_lf[0].data.data, obj_lf[0].data.size,
&detected) == KIT_OK) {
diff --git a/src/obj/elf/emit.c b/src/obj/elf/emit.c
@@ -720,20 +720,24 @@ void emit_elf(Compiler* c, ObjBuilder* ob, Writer* w) {
}
}
/* e_flags: prefer the value preserved from a prior read (round-trip);
- * else synthesize a sensible per-arch default. RV64 kit targets the
- * Linux psABI's lp64d soft-relax convention (RVC + double-float ABI). */
+ * otherwise derive the RISC-V ABI/features from the resolved target rather
+ * than the arch descriptor's default profile. */
u32 e_flags;
if (!obj_get_elf_e_flags(ob, &e_flags)) {
e_flags = elf->e_flags;
- /* rv32 (ptr_size 4): ilp32 and ilp32f share KIT_ARCH_RV32, so the static
- * descriptor's float-ABI bits (a placeholder SINGLE) cannot be right for
- * both. Derive them from -mabi (float_abi); RVC and other descriptor bits
- * are kept. rv64 (ptr_size 8) is left untouched, preserving its e_flags. */
+ /* Both XLENs expose multiple psABIs through -mabi. The static descriptors
+ * describe only their default profiles, so replace the float bits and the
+ * RVC presence bit with the resolved target values. */
if (e_machine == EM_RISCV) {
Compiler* ec = obj_compiler(ob);
- if (ec && ec->target.ptr_size == 4u) {
+ if (ec) {
u32 fa = elf_riscv_float_abi_to_e_flags(ec->target.float_abi);
e_flags = (e_flags & ~(u32)EF_RISCV_FLOAT_ABI_MASK) | fa;
+ if (ec->target_ref &&
+ kit_target_has_feature(ec->target_ref, KIT_SLICE_LIT("c")))
+ e_flags |= EF_RISCV_RVC;
+ else
+ e_flags &= ~(u32)EF_RISCV_RVC;
}
}
/* ARM: keep the EABI version (top byte) from the descriptor and override
diff --git a/src/obj/elf/reloc_riscv64.c b/src/obj/elf/reloc_riscv64.c
@@ -297,14 +297,13 @@ KitFloatAbi elf_riscv_float_abi_from_e_flags(u32 e_flags) {
}
}
-/* Encode the float ABI into RISC-V ELF e_flags (the EF_RISCV_FLOAT_ABI_* bits;
- * caller masks them into e_flags with EF_RISCV_FLOAT_ABI_MASK). Inverse of
- * elf_riscv_float_abi_from_e_flags, kept here so the format-generic ELF writers
- * (emit.c ET_REL, link.c ET_EXEC) don't inline the mapping.
- * KIT_FLOAT_ABI_DEFAULT resolves to SINGLE: the rv32 ilp32/ilp32f pair shares
- * one KitArchKind, so the static descriptor's float bits are a placeholder and
- * -mabi DEFAULT means the rv32 default profile (ilp32f). XLEN-neutral; only the
- * rv32 writers call it. */
+/* Encode the resolved float ABI into RISC-V ELF e_flags (the
+ * EF_RISCV_FLOAT_ABI_* bits; callers mask them into e_flags with
+ * EF_RISCV_FLOAT_ABI_MASK). Inverse of elf_riscv_float_abi_from_e_flags, kept
+ * here so the format-generic ELF writers (emit.c ET_REL, link.c ET_EXEC) do not
+ * inline the mapping. KitTarget construction resolves the ABI for both XLENs;
+ * DEFAULT retains the historical single-float fallback for a synthetic target
+ * that bypasses normal construction. */
u32 elf_riscv_float_abi_to_e_flags(KitFloatAbi abi) {
switch (abi) {
case KIT_FLOAT_ABI_SINGLE: