Skip to content

Commit b42b869

Browse files
committed
Add codegen test for BTF relocations
Test the `btf_field_exists`, `btf_field_byte_offset` and `btf_field_byte_size` builtins and make sure they emit correct LLVM intrinsic calls.
1 parent 93801e5 commit b42b869

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//@ add-minicore
2+
//@ needs-llvm-components: bpf
3+
//@ compile-flags: --target bpfel-unknown-none -Cdebuginfo=2
4+
5+
#![feature(allow_internal_unstable, btf_relocations, decl_macro, no_core)]
6+
#![no_core]
7+
#![no_std]
8+
#![no_main]
9+
10+
extern crate minicore;
11+
use minicore::*;
12+
13+
#[allow_internal_unstable(builtin_syntax)]
14+
pub macro field_byte_offset($Container:ty, $($fields:expr)+ $(,)?) {{
15+
if builtin # btf_field_exists($Container, $($fields)+) {
16+
::minicore::Option::Some(builtin # btf_field_byte_offset($Container, $($fields)+))
17+
} else {
18+
::minicore::Option::None
19+
}
20+
}}
21+
22+
#[allow_internal_unstable(builtin_syntax)]
23+
pub macro field_byte_size($Container:ty, $($fields:expr)+ $(,)?) {{
24+
if builtin # btf_field_exists($Container, $($fields)+) {
25+
::minicore::Option::Some(builtin # btf_field_byte_size($Container, $($fields)+))
26+
} else {
27+
::minicore::Option::None
28+
}
29+
}}
30+
31+
#[btf_relocatable]
32+
#[repr(C)]
33+
pub struct Inner {
34+
pub x: u32,
35+
pub y: u64,
36+
}
37+
38+
#[btf_relocatable]
39+
#[repr(C)]
40+
pub union Payload {
41+
pub word: u64,
42+
pub half: u32,
43+
}
44+
45+
#[btf_relocatable]
46+
#[repr(C)]
47+
pub struct Outer {
48+
pub pad: u32,
49+
pub inner: Inner,
50+
pub payload: Payload,
51+
}
52+
53+
// Each `Option` query emits a `BPF_CORE_FIELD_EXISTS` relocation (kind 2), followed by either
54+
// `BPF_CORE_FIELD_BYTE_OFFSET` (kind 0) or `BPF_CORE_FIELD_BYTE_SIZE` (kind 1). The value between
55+
// the second and third colons is the compile-time fallback.
56+
//
57+
// CHECK-DAG: @"llvm.Outer:2:1$0:1" = external global i32, !llvm.preserve.access.index
58+
// CHECK-DAG: @"llvm.Outer:0:8$0:1" = external global i32, !llvm.preserve.access.index
59+
// CHECK-DAG: @"llvm.Outer:1:16$0:1" = external global i32, !llvm.preserve.access.index
60+
//
61+
// CHECK-DAG: @"llvm.Outer:2:1$0:1:1" = external global i32, !llvm.preserve.access.index
62+
// CHECK-DAG: @"llvm.Outer:0:16$0:1:1" = external global i32, !llvm.preserve.access.index
63+
// CHECK-DAG: @"llvm.Outer:1:8$0:1:1" = external global i32, !llvm.preserve.access.index
64+
//
65+
// CHECK-DAG: @"llvm.Outer:2:1$0:2:1" = external global i32, !llvm.preserve.access.index
66+
// CHECK-DAG: @"llvm.Outer:0:24$0:2:1" = external global i32, !llvm.preserve.access.index
67+
// CHECK-DAG: @"llvm.Outer:1:4$0:2:1" = external global i32, !llvm.preserve.access.index
68+
69+
// CHECK-LABEL: define{{.*}} @field_offset(
70+
#[unsafe(no_mangle)]
71+
pub fn field_offset() -> Option<usize> {
72+
field_byte_offset!(Outer, inner)
73+
}
74+
75+
// CHECK-LABEL: define{{.*}} @field_size(
76+
#[unsafe(no_mangle)]
77+
pub fn field_size() -> Option<usize> {
78+
field_byte_size!(Outer, inner)
79+
}
80+
81+
// CHECK-LABEL: define{{.*}} @nested_field_offset(
82+
#[unsafe(no_mangle)]
83+
pub fn nested_field_offset() -> Option<usize> {
84+
field_byte_offset!(Outer, inner.y)
85+
}
86+
87+
// CHECK-LABEL: define{{.*}} @nested_field_size(
88+
#[unsafe(no_mangle)]
89+
pub fn nested_field_size() -> Option<usize> {
90+
field_byte_size!(Outer, inner.y)
91+
}
92+
93+
// CHECK-LABEL: define{{.*}} @union_field_offset(
94+
#[unsafe(no_mangle)]
95+
pub fn union_field_offset() -> Option<usize> {
96+
field_byte_offset!(Outer, payload.half)
97+
}
98+
99+
// CHECK-LABEL: define{{.*}} @union_field_size(
100+
#[unsafe(no_mangle)]
101+
pub fn union_field_size() -> Option<usize> {
102+
field_byte_size!(Outer, payload.half)
103+
}

0 commit comments

Comments
 (0)