Skip to content

Commit 8ab15ce

Browse files
committed
Add tests to abi chapter
1 parent bb40f83 commit 8ab15ce

File tree

1 file changed

+138
-2
lines changed

1 file changed

+138
-2
lines changed

src/abi.md

Lines changed: 138 additions & 2 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,81 @@ 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+
326+
r[abi.symbol-name.safety]
327+
These attributes are unsafe as an unmangled symbol may collide with another symbol
328+
with the same name (or with a well-known symbol), leading to undefined behavior.
329+
330+
```rust
331+
#[unsafe(no_mangle)]
332+
extern "C" fn foo() {}
333+
```
334+
204335
## The `link_section` attribute
205336

206337
r[abi.link_section]
@@ -212,8 +343,9 @@ MetaItemLinkSection := "link_section" "=" ([STRING_LITERAL] | [RAW_STRING_LITERA
212343
r[abi.link_section.syntax]
213344
The *`link_section` attribute* may be specified as a built-in attribute, using the [_MetaNameValueStr_] syntax.
214345

215-
r[abi.link_section.restriction]
216-
The *`link_section` attribute* shall be aplied to a `static` or `fn` item.
346+
r[abi.link_section.application]
347+
The *`link_section` attribute* shall be applied to a `static` or `fn` item.
348+
217349

218350
r[abi.link_section.def]
219351
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.
@@ -224,6 +356,9 @@ An item with the *`link_section` attribute* is placed in the specified section w
224356
>
225357
> 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.
226358
359+
r[abi.link_section.safety]
360+
This attribute is unsafe as it allows users to place data and code into sections of memory not expecting them, such as mutable data into read-only areas.
361+
227362
<!-- no_run: don't link. The format of the section name is platform-specific. -->
228363
```rust,no_run
229364
#[unsafe(no_mangle)]
@@ -242,6 +377,7 @@ pub static VAR1: u32 = 1;
242377
>
243378
> 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.
244379
380+
245381
[_MetaWord_]: attributes.md#meta-item-attribute-syntax
246382
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
247383
[`static` items]: items/static-items.md

0 commit comments

Comments
 (0)