Skip to content

Commit 786405b

Browse files
committed
Add tests to abi chapter
1 parent 12b9c0c commit 786405b

File tree

1 file changed

+130
-6
lines changed

1 file changed

+130
-6
lines changed

src/abi.md

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,40 @@ Two [integer types] are *abi compatible* if they have the same size and the same
2525
> In particular, `usize` is *abi compatible* with `uN`, and `isize` is *abi compatible* with `iN` where `N` is the target_pointer_width.
2626
> Two integer types with different signedness, such as `u8` and `i8` are not *abi compatible*.
2727
28+
```rust
29+
#[cfg(target_pointer_width="32")]
30+
fn foo(x: u32) -> u32{
31+
x
32+
}
33+
#[cfg(target_pointer_width="64")]
34+
fn foo(x: u64) -> u64{
35+
x
36+
}
37+
38+
fn main(){
39+
let f: fn(usize)->usize = unsafe{core::mem::transmute(foo as fn(_)->_)};
40+
let x = 0usize;
41+
let y = f(x);
42+
assert_eq!(x,y);
43+
}
44+
```
45+
2846
r[abi.compatibility.char]
2947
The type [`char`] is *abi compatible* with the type [`u32`][integer types].
3048

49+
```rust
50+
fn foo(x: char) -> u32{
51+
x as u32
52+
}
53+
54+
fn main(){
55+
let f: fn(u32)->char = unsafe{core::mem::transmute(foo as fn(_)->_)};
56+
let x = b'A' as u32; // ascii character indecies are the same as Unicode character indecies
57+
let y = f(x);
58+
assert_eq!(y, 'A');
59+
}
60+
```
61+
3162
r[abi.compatibility.pointer]
3263
Two [pointer types], `*mut T` and `*const U`, are *abi compatible* if the *metadata type*s of `T` and `U` are the same type.
3364

@@ -37,12 +68,40 @@ Two [pointer types], `*mut T` and `*const U`, are *abi compatible* if the *metad
3768
> [!NOTE]
3869
> With transitivity, this applies regardless of the mutability of either pointer type
3970
71+
```rust
72+
unsafe fn foo(x: *mut i32){
73+
unsafe{x.write(5);}
74+
}
75+
76+
fn main(){
77+
let f: unsafe fn(*mut ()) = unsafe{core::mem::transmute(foo as unsafe fn(_))}; // Type Erase the function
78+
let mut val = 0;
79+
let ptr = core::ptr::addr_of_mut!(val).cast::<()>(); // Get Opaque Userdata from somewhere
80+
unsafe{f(ptr);}
81+
assert_eq!(val, 5);
82+
}
83+
```
84+
4085
r[abi.compatibility.reference-box]
4186
The types [`&T`], [`&mut T`], [`alloc::boxed::Box<T>`], and [`core::ptr::NonNull<T>`], are *abi compatible* with `*const T`
4287

4388
> [!NOTE]
4489
> With transitivity, they are also *abi compatible* with each other, and with `*mut T`, as well as references/`Box` to different types that have the same *metadata type*.
4590
91+
```rust
92+
fn foo(x: &mut i32){
93+
*x = 5;
94+
}
95+
96+
fn main(){
97+
let f: unsafe fn(*mut ()) = unsafe{core::mem::transmute(foo as fn(_))}; // Type Erase the function
98+
let mut val = 0;
99+
let ptr = core::ptr::addr_of_mut!(val).cast::<()>(); // Get Opaque Userdata from somewhere
100+
unsafe{f(ptr);}
101+
assert_eq!(val, 5);
102+
}
103+
```
104+
46105
r[abi.compatibility.core]
47106
The types [`core::mem::MaybeUninit<T>`], [`core::cell::UnsafeCell<T>`], and [`core::num::NonZero<T>`], are *abi compatible* with `T`.
48107

@@ -55,6 +114,7 @@ Two types, `T` and `U`, are *abi compatible* if both have size 0 and alignment 1
55114
r[abi.compatibility.option]
56115
If `T` is a type listed in [layout.enum.option](https://doc.rust-lang.org/stable/core/option/index.html#representation), then given `S` is a type with size 0 and alignment 1, `T` is *abi compatible* with the types [`core::option::Option<T>`], [`core::result::Result<T,S>`], and [`core::result::Result<S,T>`].
57116

117+
58118
r[abi.compatibility.fn-ptr]
59119
An [`fn`-ptr type] `T` is compatible with an [`fn`-ptr type] `U` if `T` and `U` have *abi compatible* tags.
60120

@@ -97,6 +157,9 @@ A call to a function `f` via a function item or function pointer with a given si
97157

98158
The behaviour a call that is not valid is undefined.
99159

160+
> [!NOTE]
161+
> When parameter/return types do not exactly match, they are converted as though by calling [`core::mem::transmute`]. The representation and validity requirements of the type in the definition/return site still apply, for example, passing `0` to a function pointer `fn(u32)` that points to a function declared as `fn foo(x: NonZeroU32)` is undefined behaviour.
162+
100163
> [!NOTE]
101164
> the ABI tag `extern "Rust"` is the default when the `extern` keyword is not used (either to declare the function within an [`extern` block], or as a [function qualifier][extern functions]). Thus it is safe to call most functions that use simd types.
102165
@@ -129,6 +192,11 @@ The *`used` attribute* may be specified as a built-in attribute, using the [_Met
129192
r[abi.used.restriction]
130193
The `used` attribute shall only be applied to a `static` item. It shall not be applied to a `static` item declared within an [`extern` block].
131194

195+
```rust
196+
#[used]
197+
static FOO: u32 = 0;
198+
```
199+
132200
r[abi.used.application]
133201
A `static` item with the `used` attribute is an *exported item*.
134202

@@ -189,18 +257,72 @@ MetaItemExportName := "export_name" "=" ([STRING_LITERAL] | [RAW_STRING_LITERAL]
189257
r[abi.symbol-name.names]
190258
The *`no_mangle` attribute* and the *`export_name` attribute* shall only be applied to a `static` or `fn` item. The *`export_name` attribute* shall not be applied to an item declared within an [`extern` block].
191259

260+
```rust
261+
#[no_mangle]
262+
extern "C" fn foo(x: i32) -> i32 {
263+
x + 1
264+
}
265+
266+
#[export_name = "bar"]
267+
extern "C" fn baz(x: i32) -> i32 {
268+
x + 2
269+
}
270+
```
271+
272+
```rust,compile_fail
273+
extern "C" {
274+
#[export_name = "foo"]
275+
fn __foo(x: i32) -> i32;
276+
}
277+
```
278+
192279
> [!NOTE]
193280
> They may be applied to an associated `fn` of an `impl` block.
194281
282+
195283
r[abi.symbol-name.exported]
196284
An item with either the *`no_mangle` attrbute* or the *`export_name` attribute* is an *exported item*.
197285

198286
r[abi.symbol-name.no_mangle]
199287
The *`no_mangle` attribute* may be specified as a built-in attribute, using the [_MetaWord_] syntax. The *export name* of an item with the *`no_mangle` attribute* is the declaration name of the item.
200288

289+
```rust
290+
extern "C" {
291+
fn bar() -> i32;
292+
}
293+
mod inner{
294+
#[no_mangle]
295+
extern "C" fn bar() -> i32 {
296+
0
297+
}
298+
}
299+
300+
fn main() {
301+
let y = unsafe {bar()};
302+
assert_eq!(y,0);
303+
}
304+
```
305+
201306
r[abi.symbol-name.export_name]
202307
The *`export_name` attribute* may be specified as a built-in attribute, using the [_MetaNameValueStr_] syntax. The *export name* of an item with the *`no_mangle` attribute* is the content of `STRING_LITERAL`.
203308

309+
```rust
310+
extern "C" {
311+
fn bar() -> i32;
312+
}
313+
mod inner{
314+
#[export_name = "bar"]
315+
extern "C" fn __some_other_item_name() -> i32 {
316+
0
317+
}
318+
}
319+
320+
fn main(){
321+
let y = unsafe {bar()};
322+
assert_eq!(y,0);
323+
}
324+
```
325+
204326
## The `link_section` attribute
205327

206328
r[abi.link_section]
@@ -215,6 +337,13 @@ The *`link_section` attribute* may be specified as a built-in attribute, using t
215337
r[abi.link_section.restriction]
216338
The *`link_section` attribute* shall be aplied to a `static` or `fn` item.
217339

340+
<!-- no_run: don't link. The format of the section name is platform-specific. -->
341+
```rust,no_run
342+
#[no_mangle]
343+
#[link_section = ".example_section"]
344+
pub static VAR1: u32 = 1;
345+
```
346+
218347
r[abi.link_section.def]
219348
An item with the *`link_section` attribute* is placed in the specified section when linking. The section specified shall not violate the constraints on section names on the target, and shall not be invalid for the item type, no diagnostic is required.
220349

@@ -224,12 +353,6 @@ An item with the *`link_section` attribute* is placed in the specified section w
224353
>
225354
> The result of using an invalid section name may be that the section is placed into the section but cannot be used as applicable, or that the section is given additional attributes that may be incompatible when linking.
226355
227-
<!-- no_run: don't link. The format of the section name is platform-specific. -->
228-
```rust,no_run
229-
#[no_mangle]
230-
#[link_section = ".example_section"]
231-
pub static VAR1: u32 = 1;
232-
```
233356

234357
> [!TARGET-SPECIFIC]
235358
> On ELF Platforms, the standard section names, and their attributes are:
@@ -242,6 +365,7 @@ pub static VAR1: u32 = 1;
242365
>
243366
> This is not an exhaustive list, and generally extended versions of these section names such as `.text.foo`, are also defined with the same properties as the base section.
244367
368+
245369
[_MetaWord_]: attributes.md#meta-item-attribute-syntax
246370
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
247371
[`static` items]: items/static-items.md

0 commit comments

Comments
 (0)