macros.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. macro_rules! intrinsics {
  2. () => ();
  3. // Anything which has a `not(feature = "c")` we'll generate a shim function
  4. // which calls out to the C function if the `c` feature is enabled.
  5. // Otherwise if the `c` feature isn't enabled then we'll just have a normal
  6. // intrinsic.
  7. (
  8. #[use_c_shim_if($($cfg_clause:tt)*)]
  9. $(#[$attr:meta])*
  10. pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
  11. $($body:tt)*
  12. }
  13. $($rest:tt)*
  14. ) => (
  15. #[cfg(all(feature = "c", not($($cfg_clause)*)))]
  16. $(#[$attr])*
  17. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  18. extern $abi {
  19. fn $name($($argname: $ty),*) -> $ret;
  20. }
  21. unsafe {
  22. $name($($argname),*)
  23. }
  24. }
  25. #[cfg(not(all(feature = "c", not($($cfg_clause)*))))]
  26. intrinsics! {
  27. $(#[$attr])*
  28. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  29. $($body)*
  30. }
  31. }
  32. intrinsics!($($rest)*);
  33. );
  34. // We recognize the `#[aapcs_on_arm]` attribute here and generate the
  35. // same intrinsic but force it to have the `"aapcs"` calling convention on
  36. // ARM and `"C"` elsewhere.
  37. (
  38. #[aapcs_on_arm]
  39. $(#[$attr:meta])*
  40. pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
  41. $($body:tt)*
  42. }
  43. $($rest:tt)*
  44. ) => (
  45. #[cfg(target_arch = "arm")]
  46. intrinsics! {
  47. $(#[$attr])*
  48. pub extern "aapcs" fn $name( $($argname: $ty),* ) -> $ret {
  49. $($body)*
  50. }
  51. }
  52. #[cfg(not(target_arch = "arm"))]
  53. intrinsics! {
  54. $(#[$attr])*
  55. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  56. $($body)*
  57. }
  58. }
  59. intrinsics!($($rest)*);
  60. );
  61. // Like aapcs above we recognize an attribute for the "unadjusted" abi on
  62. // win64 for some methods.
  63. (
  64. #[unadjusted_on_win64]
  65. $(#[$attr:meta])*
  66. pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
  67. $($body:tt)*
  68. }
  69. $($rest:tt)*
  70. ) => (
  71. #[cfg(all(windows, target_pointer_width = "64"))]
  72. intrinsics! {
  73. $(#[$attr])*
  74. pub extern "unadjusted" fn $name( $($argname: $ty),* ) -> $ret {
  75. $($body)*
  76. }
  77. }
  78. #[cfg(not(all(windows, target_pointer_width = "64")))]
  79. intrinsics! {
  80. $(#[$attr])*
  81. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  82. $($body)*
  83. }
  84. }
  85. intrinsics!($($rest)*);
  86. );
  87. // Another attribute we recognize is an "abi hack" for win64 to get the 128
  88. // bit calling convention correct.
  89. (
  90. #[win64_128bit_abi_hack]
  91. $(#[$attr:meta])*
  92. pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
  93. $($body:tt)*
  94. }
  95. $($rest:tt)*
  96. ) => (
  97. #[cfg(all(windows, target_pointer_width = "64"))]
  98. $(#[$attr])*
  99. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  100. $($body)*
  101. }
  102. #[cfg(all(windows, target_pointer_width = "64"))]
  103. pub mod $name {
  104. intrinsics! {
  105. pub extern $abi fn $name( $($argname: $ty),* )
  106. -> ::macros::win64_abi_hack::U64x2
  107. {
  108. let e: $ret = super::$name($($argname),*);
  109. ::macros::win64_abi_hack::U64x2::from(e)
  110. }
  111. }
  112. }
  113. #[cfg(not(all(windows, target_pointer_width = "64")))]
  114. intrinsics! {
  115. $(#[$attr])*
  116. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  117. $($body)*
  118. }
  119. }
  120. intrinsics!($($rest)*);
  121. );
  122. (
  123. $(#[$attr:meta])*
  124. pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
  125. $($body:tt)*
  126. }
  127. $($rest:tt)*
  128. ) => (
  129. $(#[$attr])*
  130. #[cfg_attr(not(test), no_mangle)]
  131. pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
  132. $($body)*
  133. }
  134. intrinsics!($($rest)*);
  135. );
  136. }
  137. // Hack for LLVM expectations for ABI on windows
  138. #[cfg(all(windows, target_pointer_width="64"))]
  139. pub mod win64_abi_hack {
  140. #[repr(simd)]
  141. pub struct U64x2(u64, u64);
  142. impl From<i128> for U64x2 {
  143. fn from(i: i128) -> U64x2 {
  144. use int::LargeInt;
  145. let j = i as u128;
  146. U64x2(j.low(), j.high())
  147. }
  148. }
  149. impl From<u128> for U64x2 {
  150. fn from(i: u128) -> U64x2 {
  151. use int::LargeInt;
  152. U64x2(i.low(), i.high())
  153. }
  154. }
  155. }