bpf: return results larger than one register indirectly

Fixes triggering the "only small returns supported" error in the BPF
target.
This commit is contained in:
Alessandro Decina
2025-10-13 13:32:15 +00:00
parent 956f47c32f
commit 056c2da339
3 changed files with 50 additions and 0 deletions
@@ -29,3 +29,9 @@ pub(crate) fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
classify_arg(arg);
}
}
pub(crate) fn compute_rust_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
}
}
@@ -715,6 +715,7 @@ pub fn adjust_for_rust_abi<C>(&mut self, cx: &C)
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self),
"loongarch32" | "loongarch64" => loongarch::compute_rust_abi_info(cx, self),
"aarch64" => aarch64::compute_rust_abi_info(cx, self),
"bpf" => bpf::compute_rust_abi_info(self),
_ => {}
};
@@ -0,0 +1,43 @@
// Checks that results larger than one register are returned indirectly
//@ only-bpf
//@ needs-llvm-components: bpf
//@ compile-flags: --target bpfel-unknown-none
#![no_std]
#![no_main]
#[no_mangle]
fn outer(a: u64) -> u64 {
let v = match inner_res(a) {
Ok(v) => v,
Err(()) => 0,
};
inner_big(v).a[0] as u64
}
// CHECK-LABEL: define {{.*}} @_ZN{{.*}}inner_res{{.*}}E(
// CHECK-SAME: ptr{{[^,]*}},
// CHECK-SAME: i64{{[^)]*}}
#[inline(never)]
fn inner_res(a: u64) -> Result<u64, ()> {
if a == 0 { Err(()) } else { Ok(a + 1) }
}
struct Big {
a: [u16; 32],
b: u64,
}
// CHECK-LABEL: define {{.*}} @_ZN{{.*}}inner_big{{.*}}E(
// CHECK-SAME: ptr{{[^,]*}},
// CHECK-SAME: i64{{[^)]*}}
#[inline(never)]
fn inner_big(a: u64) -> Big {
Big { a: [a as u16; 32], b: 42 }
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}