Skip to content

Commit 74adfe0

Browse files
committed
update bpf abi to match LLVM 23
1 parent 059bf4a commit 74adfe0

5 files changed

Lines changed: 246 additions & 32 deletions

File tree

compiler/rustc_target/src/callconv/bpf.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
// see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFCallingConv.td
2-
use rustc_abi::TyAbiInterface;
2+
use rustc_abi::{Reg, RegKind, Size, TyAbiInterface};
33

4-
use crate::callconv::{ArgAbi, FnAbi};
4+
use crate::callconv::{ArgAbi, CastTarget, FnAbi, Uniform};
5+
6+
fn classify_aggregate_type<Ty>(arg: &mut ArgAbi<'_, Ty>) {
7+
let size = arg.layout.size;
8+
9+
match size.bits() {
10+
0 => return,
11+
1..=64 => {
12+
arg.cast_to(Reg { kind: RegKind::Integer, size });
13+
}
14+
65..=128 => {
15+
arg.cast_to(CastTarget::from(Uniform::new(Reg::i64(), Size::from_bytes(16))));
16+
}
17+
_ => {
18+
arg.make_indirect();
19+
}
20+
}
21+
}
522

623
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
24+
if !ret.layout.is_sized() {
25+
// Not touching this...
26+
return;
27+
}
28+
729
if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 {
8-
ret.make_indirect();
30+
classify_aggregate_type(ret);
931
} else {
1032
ret.extend_integer_width_to(32);
1133
}
@@ -15,12 +37,16 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
1537
where
1638
Ty: TyAbiInterface<'a, C> + Copy,
1739
{
40+
if !arg.layout.is_sized() {
41+
// Not touching this...
42+
return;
43+
}
1844
if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
1945
arg.make_indirect();
2046
return;
2147
}
2248
if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 {
23-
arg.make_indirect();
49+
classify_aggregate_type(arg);
2450
} else {
2551
arg.extend_integer_width_to(32);
2652
}

tests/codegen-llvm/bpf-abi-indirect-return.rs

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Checks that results larger than one register are returned indirectly
2+
//@ add-minicore
3+
//@ revisions: bpfel bpfeb
4+
//@[bpfel] compile-flags: --target=bpfel-unknown-none
5+
//@[bpfeb] compile-flags: --target=bpfeb-unknown-none
6+
//@ needs-llvm-components: bpf
7+
//@ compile-flags: -Copt-level=3
8+
#![crate_type = "lib"]
9+
#![feature(no_core)]
10+
#![no_core]
11+
12+
extern crate minicore;
13+
14+
struct Big {
15+
a: [u16; 32],
16+
b: u64,
17+
}
18+
19+
// CHECK-LABEL: define{{.*}} @inner_big_rust(
20+
// CHECK-SAME: ptr{{[^,]*}},
21+
// CHECK-SAME: i64{{[^)]*}}
22+
#[unsafe(no_mangle)]
23+
fn inner_big_rust(a: u64) -> Big {
24+
Big { a: [a as u16; 32], b: 42 }
25+
}
26+
27+
// CHECK-LABEL: define{{.*}} @inner_big_c(
28+
// CHECK-SAME: ptr{{[^,]*}},
29+
// CHECK-SAME: i64{{[^)]*}}
30+
#[unsafe(no_mangle)]
31+
extern "C" fn inner_big_c(a: u64) -> Big {
32+
Big { a: [a as u16; 32], b: 42 }
33+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//@ add-minicore
2+
//@ revisions: bpfel bpfeb
3+
//@[bpfel] compile-flags: --target=bpfel-unknown-none
4+
//@[bpfeb] compile-flags: --target=bpfeb-unknown-none
5+
//@ needs-llvm-components: bpf
6+
//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes
7+
//@ min-llvm-version: 23
8+
#![feature(no_core)]
9+
#![no_core]
10+
#![crate_type = "lib"]
11+
12+
extern crate minicore;
13+
use minicore::*;
14+
15+
#[repr(C)]
16+
struct Foo1 {
17+
a: i32,
18+
}
19+
20+
#[repr(C)]
21+
struct Foo2 {
22+
a: i32,
23+
b: i64,
24+
}
25+
26+
#[repr(C)]
27+
struct Foo3 {
28+
a: i32,
29+
b: i32,
30+
c: i64,
31+
}
32+
33+
impl Copy for Foo1 {}
34+
impl Copy for Foo2 {}
35+
impl Copy for Foo3 {}
36+
37+
// CHECK-LABEL: define{{.*}} i32 @bar1(
38+
// CHECK: ret i32
39+
#[no_mangle]
40+
#[inline(never)]
41+
extern "C" fn bar1(a: i32) -> Foo1 {
42+
Foo1 { a }
43+
}
44+
45+
// CHECK-LABEL: define{{.*}} [2 x i64] @bar2(
46+
// CHECK: ret [2 x i64]
47+
#[no_mangle]
48+
#[inline(never)]
49+
extern "C" fn bar2(a: i32, b: i32) -> Foo2 {
50+
Foo2 { a, b: b as i64 }
51+
}
52+
53+
// CHECK-LABEL: define{{.*}} [2 x i64] @bar3(
54+
// CHECK: ret [2 x i64]
55+
#[no_mangle]
56+
#[inline(never)]
57+
extern "C" fn bar3(a: i32, b: i32, c: i32) -> Foo3 {
58+
Foo3 { a, b, c: c as i64 }
59+
}
60+
61+
// CHECK-LABEL: define{{.*}} i32 @check1(
62+
// CHECK: %[[C1:.*]] = call i32 @bar1(
63+
// CHECK: store i32 %[[C1]]
64+
#[no_mangle]
65+
extern "C" fn check1(a: i32) -> i32 {
66+
let v = bar1(a);
67+
v.a
68+
}
69+
70+
// CHECK-LABEL: define{{.*}} i32 @check2(
71+
// CHECK: %[[C2:.*]] = call [2 x i64] @bar2(
72+
// CHECK: store [2 x i64] %[[C2]]
73+
#[no_mangle]
74+
extern "C" fn check2(a: i32, b: i32) -> i32 {
75+
let v = bar2(a, b);
76+
hint::black_box(v);
77+
v.a
78+
}
79+
80+
// CHECK-LABEL: define{{.*}} i32 @check3(
81+
// CHECK: %[[C3:.*]] = call [2 x i64] @bar3(
82+
// CHECK: store [2 x i64] %[[C3]]
83+
#[no_mangle]
84+
extern "C" fn check3(a: i32, b: i32, c: i32) -> i32 {
85+
let v = bar3(a, b, c);
86+
hint::black_box(v);
87+
v.a
88+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//@ add-minicore
2+
//@ revisions: bpfel bpfeb
3+
//@[bpfel] compile-flags: --target=bpfel-unknown-none
4+
//@[bpfeb] compile-flags: --target=bpfeb-unknown-none
5+
//@ needs-llvm-components: bpf
6+
//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes
7+
//@ min-llvm-version: 23
8+
#![feature(no_core)]
9+
#![no_core]
10+
#![crate_type = "lib"]
11+
12+
extern crate minicore;
13+
use minicore::*;
14+
15+
#[repr(C)]
16+
struct T1 {}
17+
18+
#[repr(C)]
19+
struct T2 {
20+
a: i32,
21+
}
22+
impl Copy for T2 {}
23+
24+
#[repr(C)]
25+
struct T3 {
26+
a: i32,
27+
b: i64,
28+
}
29+
30+
#[repr(C)]
31+
struct T4 {
32+
a: i64,
33+
b: i64,
34+
c: i64,
35+
}
36+
37+
#[repr(C)]
38+
struct T5 {
39+
a: i8,
40+
}
41+
42+
#[repr(C)]
43+
union U1 {
44+
a: i32,
45+
b: i64,
46+
}
47+
48+
// CHECK: define{{.*}} void @foo1()
49+
#[no_mangle]
50+
extern "C" fn foo1() -> T1 {
51+
T1 {}
52+
}
53+
54+
// CHECK: define{{.*}} i32 @foo2()
55+
#[no_mangle]
56+
extern "C" fn foo2() -> T2 {
57+
T2 { a: 0 }
58+
}
59+
60+
// CHECK: define{{.*}} [2 x i64] @foo3()
61+
#[no_mangle]
62+
extern "C" fn foo3() -> T3 {
63+
T3 { a: 0, b: 0 }
64+
}
65+
66+
// CHECK: define{{.*}} void @foo4(ptr{{.*}}sret([24 x i8]){{.*}}align 8
67+
#[no_mangle]
68+
extern "C" fn foo4() -> T4 {
69+
T4 { a: 0, b: 0, c: 0 }
70+
}
71+
72+
// CHECK: define{{.*}} i8 @foo5()
73+
#[no_mangle]
74+
extern "C" fn foo5() -> T5 {
75+
T5 { a: 0 }
76+
}
77+
78+
// CHECK: define{{.*}} i64 @foou()
79+
#[no_mangle]
80+
extern "C" fn foou() -> U1 {
81+
U1 { b: 0 }
82+
}
83+
84+
// CHECK-LABEL: define{{.*}} i32 @bar()
85+
// CHECK: %[[C2:.*]] = call i32 @foo2()
86+
// CHECK: store i32 %[[C2]]
87+
// CHECK: %[[C3:.*]] = call [2 x i64] @foo3()
88+
// CHECK: store [2 x i64] %[[C3]]
89+
#[no_mangle]
90+
extern "C" fn bar() -> i32 {
91+
let a = foo2();
92+
let b = foo3();
93+
hint::black_box((a, b));
94+
a.a
95+
}

0 commit comments

Comments
 (0)