]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | // compile-flags: -O --target=avr-unknown-gnu-atmega328 --crate-type=rlib |
3dfed10e XL |
2 | // needs-llvm-components: avr |
3 | ||
4 | // This test validates that function pointers can be stored in global variables | |
5 | // and called upon. It ensures that Rust emits function pointers in the correct | |
6 | // address space to LLVM so that an assertion error relating to casting is | |
7 | // not triggered. | |
8 | // | |
9 | // It also validates that functions can be called through function pointers | |
10 | // through traits. | |
11 | ||
12 | #![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)] | |
13 | #![crate_type = "lib"] | |
14 | #![no_core] | |
15 | ||
16 | #[lang = "sized"] | |
17 | pub trait Sized { } | |
18 | #[lang = "copy"] | |
19 | pub trait Copy { } | |
20 | #[lang = "receiver"] | |
21 | pub trait Receiver { } | |
487cf647 FG |
22 | #[lang = "tuple_trait"] |
23 | pub trait Tuple { } | |
3dfed10e XL |
24 | |
25 | pub struct Result<T, E> { _a: T, _b: E } | |
26 | ||
27 | impl Copy for usize {} | |
29967ef6 | 28 | impl Copy for &usize {} |
3dfed10e XL |
29 | |
30 | #[lang = "drop_in_place"] | |
31 | pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {} | |
32 | ||
33 | #[lang = "fn_once"] | |
487cf647 | 34 | pub trait FnOnce<Args: Tuple> { |
3dfed10e XL |
35 | #[lang = "fn_once_output"] |
36 | type Output; | |
37 | ||
38 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | |
39 | } | |
40 | ||
41 | #[lang = "fn_mut"] | |
487cf647 | 42 | pub trait FnMut<Args: Tuple> : FnOnce<Args> { |
3dfed10e XL |
43 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; |
44 | } | |
45 | ||
46 | #[lang = "fn"] | |
487cf647 | 47 | pub trait Fn<Args: Tuple>: FnOnce<Args> { |
3dfed10e XL |
48 | /// Performs the call operation. |
49 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | |
50 | } | |
51 | ||
3dfed10e XL |
52 | pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box; |
53 | pub static mut STORAGE_BAR: u32 = 12; | |
54 | ||
55 | fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> { | |
56 | let raw_ptr = ptr as *const usize; | |
57 | let _v: usize = unsafe { *raw_ptr }; | |
58 | loop {} | |
59 | } | |
60 | ||
61 | #[inline(never)] | |
62 | #[no_mangle] | |
63 | fn call_through_fn_trait(a: &mut impl Fn<(), Output=()>) { | |
64 | (*a)() | |
65 | } | |
66 | ||
67 | #[inline(never)] | |
68 | fn update_bar_value() { | |
69 | unsafe { | |
70 | STORAGE_BAR = 88; | |
71 | } | |
72 | } | |
73 | ||
f2b60f7d | 74 | // CHECK: define dso_local void @test(){{.+}}addrspace(1) |
3dfed10e XL |
75 | #[no_mangle] |
76 | pub extern "C" fn test() { | |
77 | let mut buf = 7; | |
78 | ||
79 | // A call through the Fn trait must use address space 1. | |
80 | // | |
81 | // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait() | |
82 | call_through_fn_trait(&mut update_bar_value); | |
83 | ||
84 | // A call through a global variable must use address space 1. | |
85 | // CHECK: load {{.*}}addrspace(1){{.+}}FOO | |
86 | unsafe { | |
87 | STORAGE_FOO(&1, &mut buf); | |
88 | } | |
89 | } |