intrinsics.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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. #![allow(unused_features)]
  6. #![cfg_attr(thumb, no_main)]
  7. #![deny(dead_code)]
  8. #![feature(asm)]
  9. #![feature(compiler_builtins_lib)]
  10. #![feature(lang_items)]
  11. #![feature(start)]
  12. #![feature(allocator_api)]
  13. #![no_std]
  14. extern crate panic_handler;
  15. #[cfg(all(not(thumb), not(windows)))]
  16. #[link(name = "c")]
  17. extern {}
  18. // Every function in this module maps will be lowered to an intrinsic by LLVM, if the platform
  19. // doesn't have native support for the operation used in the function. ARM has a naming convention
  20. // convention for its intrinsics that's different from other architectures; that's why some function
  21. // have an additional comment: the function name is the ARM name for the intrinsic and the comment
  22. // in the non-ARM name for the intrinsic.
  23. mod intrinsics {
  24. // trunccdfsf2
  25. pub fn aeabi_d2f(x: f64) -> f32 {
  26. x as f32
  27. }
  28. // fixdfsi
  29. pub fn aeabi_d2i(x: f64) -> i32 {
  30. x as i32
  31. }
  32. // fixdfdi
  33. pub fn aeabi_d2l(x: f64) -> i64 {
  34. x as i64
  35. }
  36. // fixunsdfsi
  37. pub fn aeabi_d2uiz(x: f64) -> u32 {
  38. x as u32
  39. }
  40. // fixunsdfdi
  41. pub fn aeabi_d2ulz(x: f64) -> u64 {
  42. x as u64
  43. }
  44. // adddf3
  45. pub fn aeabi_dadd(a: f64, b: f64) -> f64 {
  46. a + b
  47. }
  48. // eqdf2
  49. pub fn aeabi_dcmpeq(a: f64, b: f64) -> bool {
  50. a == b
  51. }
  52. // gtdf2
  53. pub fn aeabi_dcmpgt(a: f64, b: f64) -> bool {
  54. a > b
  55. }
  56. // ltdf2
  57. pub fn aeabi_dcmplt(a: f64, b: f64) -> bool {
  58. a < b
  59. }
  60. // divdf3
  61. pub fn aeabi_ddiv(a: f64, b: f64) -> f64 {
  62. a / b
  63. }
  64. // muldf3
  65. pub fn aeabi_dmul(a: f64, b: f64) -> f64 {
  66. a * b
  67. }
  68. // subdf3
  69. pub fn aeabi_dsub(a: f64, b: f64) -> f64 {
  70. a - b
  71. }
  72. // extendsfdf2
  73. pub fn aeabi_f2d(x: f32) -> f64 {
  74. x as f64
  75. }
  76. // fixsfsi
  77. pub fn aeabi_f2iz(x: f32) -> i32 {
  78. x as i32
  79. }
  80. // fixsfdi
  81. pub fn aeabi_f2lz(x: f32) -> i64 {
  82. x as i64
  83. }
  84. // fixunssfsi
  85. pub fn aeabi_f2uiz(x: f32) -> u32 {
  86. x as u32
  87. }
  88. // fixunssfdi
  89. pub fn aeabi_f2ulz(x: f32) -> u64 {
  90. x as u64
  91. }
  92. // addsf3
  93. pub fn aeabi_fadd(a: f32, b: f32) -> f32 {
  94. a + b
  95. }
  96. // eqsf2
  97. pub fn aeabi_fcmpeq(a: f32, b: f32) -> bool {
  98. a == b
  99. }
  100. // gtsf2
  101. pub fn aeabi_fcmpgt(a: f32, b: f32) -> bool {
  102. a > b
  103. }
  104. // ltsf2
  105. pub fn aeabi_fcmplt(a: f32, b: f32) -> bool {
  106. a < b
  107. }
  108. // divsf3
  109. pub fn aeabi_fdiv(a: f32, b: f32) -> f32 {
  110. a / b
  111. }
  112. // mulsf3
  113. pub fn aeabi_fmul(a: f32, b: f32) -> f32 {
  114. a * b
  115. }
  116. // subsf3
  117. pub fn aeabi_fsub(a: f32, b: f32) -> f32 {
  118. a - b
  119. }
  120. // floatsidf
  121. pub fn aeabi_i2d(x: i32) -> f64 {
  122. x as f64
  123. }
  124. // floatsisf
  125. pub fn aeabi_i2f(x: i32) -> f32 {
  126. x as f32
  127. }
  128. pub fn aeabi_idiv(a: i32, b: i32) -> i32 {
  129. a.wrapping_div(b)
  130. }
  131. pub fn aeabi_idivmod(a: i32, b: i32) -> i32 {
  132. a % b
  133. }
  134. // floatdidf
  135. pub fn aeabi_l2d(x: i64) -> f64 {
  136. x as f64
  137. }
  138. // floatdisf
  139. pub fn aeabi_l2f(x: i64) -> f32 {
  140. x as f32
  141. }
  142. // divdi3
  143. pub fn aeabi_ldivmod(a: i64, b: i64) -> i64 {
  144. a / b
  145. }
  146. // muldi3
  147. pub fn aeabi_lmul(a: i64, b: i64) -> i64 {
  148. a.wrapping_mul(b)
  149. }
  150. // floatunsidf
  151. pub fn aeabi_ui2d(x: u32) -> f64 {
  152. x as f64
  153. }
  154. // floatunsisf
  155. pub fn aeabi_ui2f(x: u32) -> f32 {
  156. x as f32
  157. }
  158. pub fn aeabi_uidiv(a: u32, b: u32) -> u32 {
  159. a / b
  160. }
  161. pub fn aeabi_uidivmod(a: u32, b: u32) -> u32 {
  162. a % b
  163. }
  164. // floatundidf
  165. pub fn aeabi_ul2d(x: u64) -> f64 {
  166. x as f64
  167. }
  168. // floatundisf
  169. pub fn aeabi_ul2f(x: u64) -> f32 {
  170. x as f32
  171. }
  172. // udivdi3
  173. pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 {
  174. a * b
  175. }
  176. pub fn moddi3(a: i64, b: i64) -> i64 {
  177. a % b
  178. }
  179. pub fn mulodi4(a: i64, b: i64) -> i64 {
  180. a * b
  181. }
  182. pub fn umoddi3(a: u64, b: u64) -> u64 {
  183. a % b
  184. }
  185. pub fn muloti4(a: u128, b: u128) -> Option<u128> {
  186. a.checked_mul(b)
  187. }
  188. pub fn multi3(a: u128, b: u128) -> u128 {
  189. a.wrapping_mul(b)
  190. }
  191. pub fn ashlti3(a: u128, b: usize) -> u128 {
  192. a >> b
  193. }
  194. pub fn ashrti3(a: u128, b: usize) -> u128 {
  195. a << b
  196. }
  197. pub fn lshrti3(a: i128, b: usize) -> i128 {
  198. a >> b
  199. }
  200. pub fn udivti3(a: u128, b: u128) -> u128 {
  201. a / b
  202. }
  203. pub fn umodti3(a: u128, b: u128) -> u128 {
  204. a % b
  205. }
  206. pub fn divti3(a: i128, b: i128) -> i128 {
  207. a / b
  208. }
  209. pub fn modti3(a: i128, b: i128) -> i128 {
  210. a % b
  211. }
  212. }
  213. fn run() {
  214. use intrinsics::*;
  215. // A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO
  216. fn bb<T>(dummy: T) -> T {
  217. unsafe { asm!("" : : "r"(&dummy)) }
  218. dummy
  219. }
  220. bb(aeabi_d2f(bb(2.)));
  221. bb(aeabi_d2i(bb(2.)));
  222. bb(aeabi_d2l(bb(2.)));
  223. bb(aeabi_d2uiz(bb(2.)));
  224. bb(aeabi_d2ulz(bb(2.)));
  225. bb(aeabi_dadd(bb(2.), bb(3.)));
  226. bb(aeabi_dcmpeq(bb(2.), bb(3.)));
  227. bb(aeabi_dcmpgt(bb(2.), bb(3.)));
  228. bb(aeabi_dcmplt(bb(2.), bb(3.)));
  229. bb(aeabi_ddiv(bb(2.), bb(3.)));
  230. bb(aeabi_dmul(bb(2.), bb(3.)));
  231. bb(aeabi_dsub(bb(2.), bb(3.)));
  232. bb(aeabi_f2d(bb(2.)));
  233. bb(aeabi_f2iz(bb(2.)));
  234. bb(aeabi_f2lz(bb(2.)));
  235. bb(aeabi_f2uiz(bb(2.)));
  236. bb(aeabi_f2ulz(bb(2.)));
  237. bb(aeabi_fadd(bb(2.), bb(3.)));
  238. bb(aeabi_fcmpeq(bb(2.), bb(3.)));
  239. bb(aeabi_fcmpgt(bb(2.), bb(3.)));
  240. bb(aeabi_fcmplt(bb(2.), bb(3.)));
  241. bb(aeabi_fdiv(bb(2.), bb(3.)));
  242. bb(aeabi_fmul(bb(2.), bb(3.)));
  243. bb(aeabi_fsub(bb(2.), bb(3.)));
  244. bb(aeabi_i2d(bb(2)));
  245. bb(aeabi_i2f(bb(2)));
  246. bb(aeabi_idiv(bb(2), bb(3)));
  247. bb(aeabi_idivmod(bb(2), bb(3)));
  248. bb(aeabi_l2d(bb(2)));
  249. bb(aeabi_l2f(bb(2)));
  250. bb(aeabi_ldivmod(bb(2), bb(3)));
  251. bb(aeabi_lmul(bb(2), bb(3)));
  252. bb(aeabi_ui2d(bb(2)));
  253. bb(aeabi_ui2f(bb(2)));
  254. bb(aeabi_uidiv(bb(2), bb(3)));
  255. bb(aeabi_uidivmod(bb(2), bb(3)));
  256. bb(aeabi_ul2d(bb(2)));
  257. bb(aeabi_ul2f(bb(2)));
  258. bb(aeabi_uldivmod(bb(2), bb(3)));
  259. bb(moddi3(bb(2), bb(3)));
  260. bb(mulodi4(bb(2), bb(3)));
  261. bb(umoddi3(bb(2), bb(3)));
  262. bb(muloti4(bb(2), bb(2)));
  263. bb(multi3(bb(2), bb(2)));
  264. bb(ashlti3(bb(2), bb(2)));
  265. bb(ashrti3(bb(2), bb(2)));
  266. bb(lshrti3(bb(2), bb(2)));
  267. bb(udivti3(bb(2), bb(2)));
  268. bb(umodti3(bb(2), bb(2)));
  269. bb(divti3(bb(2), bb(2)));
  270. bb(modti3(bb(2), bb(2)));
  271. something_with_a_dtor(&|| assert_eq!(bb(1), 1));
  272. extern {
  273. fn rust_begin_unwind();
  274. }
  275. // if bb(false) {
  276. unsafe { rust_begin_unwind(); }
  277. // }
  278. }
  279. fn something_with_a_dtor(f: &Fn()) {
  280. struct A<'a>(&'a (Fn() + 'a));
  281. impl<'a> Drop for A<'a> {
  282. fn drop(&mut self) {
  283. (self.0)();
  284. }
  285. }
  286. let _a = A(f);
  287. f();
  288. }
  289. #[cfg(not(thumb))]
  290. #[start]
  291. fn main(_: isize, _: *const *const u8) -> isize {
  292. run();
  293. 0
  294. }
  295. #[cfg(thumb)]
  296. #[no_mangle]
  297. pub fn _start() -> ! {
  298. run();
  299. loop {}
  300. }
  301. #[cfg(windows)]
  302. #[link(name = "kernel32")]
  303. #[link(name = "msvcrt")]
  304. extern {}
  305. // ARM targets need these symbols
  306. #[no_mangle]
  307. pub fn __aeabi_unwind_cpp_pr0() {}
  308. #[no_mangle]
  309. pub fn __aeabi_unwind_cpp_pr1() {}
  310. #[cfg(not(windows))]
  311. #[allow(non_snake_case)]
  312. #[no_mangle]
  313. pub fn _Unwind_Resume() {}
  314. #[cfg(not(windows))]
  315. #[lang = "eh_personality"]
  316. #[no_mangle]
  317. pub extern "C" fn eh_personality() {}
  318. #[cfg(all(windows, target_env = "gnu"))]
  319. mod mingw_unwidning {
  320. #[no_mangle]
  321. pub fn rust_eh_personality() {}
  322. #[no_mangle]
  323. pub fn rust_eh_unwind_resume() {}
  324. }