From aec971197a727cfe06e9013d3b250750a5c65880 Mon Sep 17 00:00:00 2001 From: kalsprite Date: Mon, 10 Aug 2026 21:34:08 -0700 Subject: [PATCH] riscv64: a pointer is not an integer in the FP calling convention --- src/llvm_abi.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index e06aa9244..06a083a2f 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1738,6 +1738,13 @@ namespace lbAbiRiscv64 { } } + // The psABI's rule is "one floating-point real and one integer (or bitfield)", and a pointer + // is not an integer. `is_register` admits pointers and keeps that meaning for its other + // callers, so the floating-point arms need their own predicate. + gb_internal bool is_int_member(LLVMTypeRef type) { + return LLVMGetTypeKind(type) == LLVMIntegerTypeKind && lb_sizeof(type) > 0; + } + gb_internal lbArgType compute_arg_type(lbModule *m, LLVMTypeRef type, int *gprs_left, int *fprs_left, Type *odin_type) { LLVMContextRef c = m->ctx; @@ -1808,13 +1815,13 @@ namespace lbAbiRiscv64 { return lb_arg_type_direct(orig_type, fp_type, nullptr, nullptr); } - if (is_float(ty1) && is_register(ty2) && ty1s <= flen && ty2s <= xlen && *fprs_left >= 1 && *gprs_left >= 1) { + if (is_float(ty1) && is_int_member(ty2) && ty1s <= flen && ty2s <= xlen && *fprs_left >= 1 && *gprs_left >= 1) { *fprs_left -= 1; *gprs_left -= 1; return lb_arg_type_direct(orig_type, fp_type, nullptr, nullptr); } - if (is_register(ty1) && is_float(ty2) && ty1s <= xlen && ty2s <= flen && *gprs_left >= 1 && *fprs_left >= 1) { + if (is_int_member(ty1) && is_float(ty2) && ty1s <= xlen && ty2s <= flen && *gprs_left >= 1 && *fprs_left >= 1) { *fprs_left -= 1; *gprs_left -= 1; return lb_arg_type_direct(orig_type, fp_type, nullptr, nullptr);