1 // By compiling this file we check that all the intrinsics we care about continue to be provided by
2 // the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop
3 // compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail
4 // to link due to the missing intrinsic (symbol).
5 
6 #![allow(unused_features)]
7 #![cfg_attr(thumb, no_main)]
8 #![deny(dead_code)]
9 #![feature(bench_black_box)]
10 #![feature(lang_items)]
11 #![feature(start)]
12 #![feature(allocator_api)]
13 #![no_std]
14 
15 extern crate panic_handler;
16 
17 #[cfg(all(not(thumb), not(windows), not(target_arch = "wasm32")))]
18 #[link(name = "c")]
19 extern "C" {}
20 
21 // Every function in this module maps will be lowered to an intrinsic by LLVM, if the platform
22 // doesn't have native support for the operation used in the function. ARM has a naming convention
23 // convention for its intrinsics that's different from other architectures; that's why some function
24 // have an additional comment: the function name is the ARM name for the intrinsic and the comment
25 // in the non-ARM name for the intrinsic.
26 mod intrinsics {
27     // trunccdfsf2
aeabi_d2f(x: f64) -> f3228     pub fn aeabi_d2f(x: f64) -> f32 {
29         // This is only implemented in C currently, so only test it there.
30         #[cfg(feature = "c")]
31         return x as f32;
32         #[cfg(not(feature = "c"))]
33         {
34             drop(x);
35             0.0
36         }
37     }
38 
39     // fixdfsi
aeabi_d2i(x: f64) -> i3240     pub fn aeabi_d2i(x: f64) -> i32 {
41         x as i32
42     }
43 
44     // fixdfdi
aeabi_d2l(x: f64) -> i6445     pub fn aeabi_d2l(x: f64) -> i64 {
46         x as i64
47     }
48 
49     // fixunsdfsi
aeabi_d2uiz(x: f64) -> u3250     pub fn aeabi_d2uiz(x: f64) -> u32 {
51         x as u32
52     }
53 
54     // fixunsdfdi
aeabi_d2ulz(x: f64) -> u6455     pub fn aeabi_d2ulz(x: f64) -> u64 {
56         x as u64
57     }
58 
59     // adddf3
aeabi_dadd(a: f64, b: f64) -> f6460     pub fn aeabi_dadd(a: f64, b: f64) -> f64 {
61         a + b
62     }
63 
64     // eqdf2
aeabi_dcmpeq(a: f64, b: f64) -> bool65     pub fn aeabi_dcmpeq(a: f64, b: f64) -> bool {
66         a == b
67     }
68 
69     // gtdf2
aeabi_dcmpgt(a: f64, b: f64) -> bool70     pub fn aeabi_dcmpgt(a: f64, b: f64) -> bool {
71         a > b
72     }
73 
74     // ltdf2
aeabi_dcmplt(a: f64, b: f64) -> bool75     pub fn aeabi_dcmplt(a: f64, b: f64) -> bool {
76         a < b
77     }
78 
79     // divdf3
aeabi_ddiv(a: f64, b: f64) -> f6480     pub fn aeabi_ddiv(a: f64, b: f64) -> f64 {
81         a / b
82     }
83 
84     // muldf3
aeabi_dmul(a: f64, b: f64) -> f6485     pub fn aeabi_dmul(a: f64, b: f64) -> f64 {
86         a * b
87     }
88 
89     // subdf3
aeabi_dsub(a: f64, b: f64) -> f6490     pub fn aeabi_dsub(a: f64, b: f64) -> f64 {
91         a - b
92     }
93 
94     // extendsfdf2
aeabi_f2d(x: f32) -> f6495     pub fn aeabi_f2d(x: f32) -> f64 {
96         x as f64
97     }
98 
99     // fixsfsi
aeabi_f2iz(x: f32) -> i32100     pub fn aeabi_f2iz(x: f32) -> i32 {
101         x as i32
102     }
103 
104     // fixsfdi
aeabi_f2lz(x: f32) -> i64105     pub fn aeabi_f2lz(x: f32) -> i64 {
106         x as i64
107     }
108 
109     // fixunssfsi
aeabi_f2uiz(x: f32) -> u32110     pub fn aeabi_f2uiz(x: f32) -> u32 {
111         x as u32
112     }
113 
114     // fixunssfdi
aeabi_f2ulz(x: f32) -> u64115     pub fn aeabi_f2ulz(x: f32) -> u64 {
116         x as u64
117     }
118 
119     // addsf3
aeabi_fadd(a: f32, b: f32) -> f32120     pub fn aeabi_fadd(a: f32, b: f32) -> f32 {
121         a + b
122     }
123 
124     // eqsf2
aeabi_fcmpeq(a: f32, b: f32) -> bool125     pub fn aeabi_fcmpeq(a: f32, b: f32) -> bool {
126         a == b
127     }
128 
129     // gtsf2
aeabi_fcmpgt(a: f32, b: f32) -> bool130     pub fn aeabi_fcmpgt(a: f32, b: f32) -> bool {
131         a > b
132     }
133 
134     // ltsf2
aeabi_fcmplt(a: f32, b: f32) -> bool135     pub fn aeabi_fcmplt(a: f32, b: f32) -> bool {
136         a < b
137     }
138 
139     // divsf3
aeabi_fdiv(a: f32, b: f32) -> f32140     pub fn aeabi_fdiv(a: f32, b: f32) -> f32 {
141         a / b
142     }
143 
144     // mulsf3
aeabi_fmul(a: f32, b: f32) -> f32145     pub fn aeabi_fmul(a: f32, b: f32) -> f32 {
146         a * b
147     }
148 
149     // subsf3
aeabi_fsub(a: f32, b: f32) -> f32150     pub fn aeabi_fsub(a: f32, b: f32) -> f32 {
151         a - b
152     }
153 
154     // floatsidf
aeabi_i2d(x: i32) -> f64155     pub fn aeabi_i2d(x: i32) -> f64 {
156         x as f64
157     }
158 
159     // floatsisf
aeabi_i2f(x: i32) -> f32160     pub fn aeabi_i2f(x: i32) -> f32 {
161         x as f32
162     }
163 
aeabi_idiv(a: i32, b: i32) -> i32164     pub fn aeabi_idiv(a: i32, b: i32) -> i32 {
165         a.wrapping_div(b)
166     }
167 
aeabi_idivmod(a: i32, b: i32) -> i32168     pub fn aeabi_idivmod(a: i32, b: i32) -> i32 {
169         a % b
170     }
171 
172     // floatdidf
aeabi_l2d(x: i64) -> f64173     pub fn aeabi_l2d(x: i64) -> f64 {
174         x as f64
175     }
176 
177     // floatdisf
aeabi_l2f(x: i64) -> f32178     pub fn aeabi_l2f(x: i64) -> f32 {
179         x as f32
180     }
181 
182     // divdi3
aeabi_ldivmod(a: i64, b: i64) -> i64183     pub fn aeabi_ldivmod(a: i64, b: i64) -> i64 {
184         a / b
185     }
186 
187     // muldi3
aeabi_lmul(a: i64, b: i64) -> i64188     pub fn aeabi_lmul(a: i64, b: i64) -> i64 {
189         a.wrapping_mul(b)
190     }
191 
192     // floatunsidf
aeabi_ui2d(x: u32) -> f64193     pub fn aeabi_ui2d(x: u32) -> f64 {
194         x as f64
195     }
196 
197     // floatunsisf
aeabi_ui2f(x: u32) -> f32198     pub fn aeabi_ui2f(x: u32) -> f32 {
199         x as f32
200     }
201 
aeabi_uidiv(a: u32, b: u32) -> u32202     pub fn aeabi_uidiv(a: u32, b: u32) -> u32 {
203         a / b
204     }
205 
aeabi_uidivmod(a: u32, b: u32) -> u32206     pub fn aeabi_uidivmod(a: u32, b: u32) -> u32 {
207         a % b
208     }
209 
210     // floatundidf
aeabi_ul2d(x: u64) -> f64211     pub fn aeabi_ul2d(x: u64) -> f64 {
212         x as f64
213     }
214 
215     // floatundisf
aeabi_ul2f(x: u64) -> f32216     pub fn aeabi_ul2f(x: u64) -> f32 {
217         x as f32
218     }
219 
220     // udivdi3
aeabi_uldivmod(a: u64, b: u64) -> u64221     pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 {
222         a * b
223     }
224 
moddi3(a: i64, b: i64) -> i64225     pub fn moddi3(a: i64, b: i64) -> i64 {
226         a % b
227     }
228 
mulodi4(a: i64, b: i64) -> i64229     pub fn mulodi4(a: i64, b: i64) -> i64 {
230         a * b
231     }
232 
umoddi3(a: u64, b: u64) -> u64233     pub fn umoddi3(a: u64, b: u64) -> u64 {
234         a % b
235     }
236 
muloti4(a: u128, b: u128) -> Option<u128>237     pub fn muloti4(a: u128, b: u128) -> Option<u128> {
238         a.checked_mul(b)
239     }
240 
multi3(a: u128, b: u128) -> u128241     pub fn multi3(a: u128, b: u128) -> u128 {
242         a.wrapping_mul(b)
243     }
244 
ashlti3(a: u128, b: usize) -> u128245     pub fn ashlti3(a: u128, b: usize) -> u128 {
246         a >> b
247     }
248 
ashrti3(a: u128, b: usize) -> u128249     pub fn ashrti3(a: u128, b: usize) -> u128 {
250         a << b
251     }
252 
lshrti3(a: i128, b: usize) -> i128253     pub fn lshrti3(a: i128, b: usize) -> i128 {
254         a >> b
255     }
256 
udivti3(a: u128, b: u128) -> u128257     pub fn udivti3(a: u128, b: u128) -> u128 {
258         a / b
259     }
260 
umodti3(a: u128, b: u128) -> u128261     pub fn umodti3(a: u128, b: u128) -> u128 {
262         a % b
263     }
264 
divti3(a: i128, b: i128) -> i128265     pub fn divti3(a: i128, b: i128) -> i128 {
266         a / b
267     }
268 
modti3(a: i128, b: i128) -> i128269     pub fn modti3(a: i128, b: i128) -> i128 {
270         a % b
271     }
272 
udivsi3(a: u32, b: u32) -> u32273     pub fn udivsi3(a: u32, b: u32) -> u32 {
274         a / b
275     }
276 }
277 
run()278 fn run() {
279     use core::hint::black_box as bb;
280     use intrinsics::*;
281 
282     bb(aeabi_d2f(bb(2.)));
283     bb(aeabi_d2i(bb(2.)));
284     bb(aeabi_d2l(bb(2.)));
285     bb(aeabi_d2uiz(bb(2.)));
286     bb(aeabi_d2ulz(bb(2.)));
287     bb(aeabi_dadd(bb(2.), bb(3.)));
288     bb(aeabi_dcmpeq(bb(2.), bb(3.)));
289     bb(aeabi_dcmpgt(bb(2.), bb(3.)));
290     bb(aeabi_dcmplt(bb(2.), bb(3.)));
291     bb(aeabi_ddiv(bb(2.), bb(3.)));
292     bb(aeabi_dmul(bb(2.), bb(3.)));
293     bb(aeabi_dsub(bb(2.), bb(3.)));
294     bb(aeabi_f2d(bb(2.)));
295     bb(aeabi_f2iz(bb(2.)));
296     bb(aeabi_f2lz(bb(2.)));
297     bb(aeabi_f2uiz(bb(2.)));
298     bb(aeabi_f2ulz(bb(2.)));
299     bb(aeabi_fadd(bb(2.), bb(3.)));
300     bb(aeabi_fcmpeq(bb(2.), bb(3.)));
301     bb(aeabi_fcmpgt(bb(2.), bb(3.)));
302     bb(aeabi_fcmplt(bb(2.), bb(3.)));
303     bb(aeabi_fdiv(bb(2.), bb(3.)));
304     bb(aeabi_fmul(bb(2.), bb(3.)));
305     bb(aeabi_fsub(bb(2.), bb(3.)));
306     bb(aeabi_i2d(bb(2)));
307     bb(aeabi_i2f(bb(2)));
308     bb(aeabi_idiv(bb(2), bb(3)));
309     bb(aeabi_idivmod(bb(2), bb(3)));
310     bb(aeabi_l2d(bb(2)));
311     bb(aeabi_l2f(bb(2)));
312     bb(aeabi_ldivmod(bb(2), bb(3)));
313     bb(aeabi_lmul(bb(2), bb(3)));
314     bb(aeabi_ui2d(bb(2)));
315     bb(aeabi_ui2f(bb(2)));
316     bb(aeabi_uidiv(bb(2), bb(3)));
317     bb(aeabi_uidivmod(bb(2), bb(3)));
318     bb(aeabi_ul2d(bb(2)));
319     bb(aeabi_ul2f(bb(2)));
320     bb(aeabi_uldivmod(bb(2), bb(3)));
321     bb(moddi3(bb(2), bb(3)));
322     bb(mulodi4(bb(2), bb(3)));
323     bb(umoddi3(bb(2), bb(3)));
324     bb(muloti4(bb(2), bb(2)));
325     bb(multi3(bb(2), bb(2)));
326     bb(ashlti3(bb(2), bb(2)));
327     bb(ashrti3(bb(2), bb(2)));
328     bb(lshrti3(bb(2), bb(2)));
329     bb(udivti3(bb(2), bb(2)));
330     bb(umodti3(bb(2), bb(2)));
331     bb(divti3(bb(2), bb(2)));
332     bb(modti3(bb(2), bb(2)));
333     bb(udivsi3(bb(2), bb(2)));
334 
335     something_with_a_dtor(&|| assert_eq!(bb(1), 1));
336 
337     extern "C" {
338         fn rust_begin_unwind(x: usize);
339     }
340     // if bb(false) {
341     unsafe {
342         rust_begin_unwind(0);
343     }
344     // }
345 }
346 
something_with_a_dtor(f: &dyn Fn())347 fn something_with_a_dtor(f: &dyn Fn()) {
348     struct A<'a>(&'a (dyn Fn() + 'a));
349 
350     impl<'a> Drop for A<'a> {
351         fn drop(&mut self) {
352             (self.0)();
353         }
354     }
355     let _a = A(f);
356     f();
357 }
358 
359 #[cfg(not(thumb))]
360 #[start]
main(_: isize, _: *const *const u8) -> isize361 fn main(_: isize, _: *const *const u8) -> isize {
362     run();
363     0
364 }
365 
366 #[cfg(thumb)]
367 #[no_mangle]
_start() -> !368 pub fn _start() -> ! {
369     run();
370     loop {}
371 }
372 
373 #[cfg(windows)]
374 #[link(name = "kernel32")]
375 #[link(name = "msvcrt")]
376 extern "C" {}
377 
378 // ARM targets need these symbols
379 #[no_mangle]
__aeabi_unwind_cpp_pr0()380 pub fn __aeabi_unwind_cpp_pr0() {}
381 
382 #[no_mangle]
__aeabi_unwind_cpp_pr1()383 pub fn __aeabi_unwind_cpp_pr1() {}
384 
385 #[cfg(not(windows))]
386 #[allow(non_snake_case)]
387 #[no_mangle]
_Unwind_Resume()388 pub fn _Unwind_Resume() {}
389 
390 #[cfg(not(windows))]
391 #[lang = "eh_personality"]
392 #[no_mangle]
eh_personality()393 pub extern "C" fn eh_personality() {}
394 
395 #[cfg(all(windows, target_env = "gnu"))]
396 mod mingw_unwinding {
397     #[no_mangle]
rust_eh_personality()398     pub fn rust_eh_personality() {}
399     #[no_mangle]
rust_eh_unwind_resume()400     pub fn rust_eh_unwind_resume() {}
401     #[no_mangle]
rust_eh_register_frames()402     pub fn rust_eh_register_frames() {}
403     #[no_mangle]
rust_eh_unregister_frames()404     pub fn rust_eh_unregister_frames() {}
405 }
406