]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
1 | //! Macros shared throughout the compiler-builtins implementation |
2 | ||
17df50a5 XL |
3 | /// Changes the visibility to `pub` if feature "public-test-deps" is set |
4 | #[cfg(not(feature = "public-test-deps"))] | |
5 | macro_rules! public_test_dep { | |
6 | ($(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*) => { | |
7 | $(#[$($meta)*])* pub(crate) $ident $($tokens)* | |
8 | }; | |
9 | } | |
10 | ||
11 | /// Changes the visibility to `pub` if feature "public-test-deps" is set | |
12 | #[cfg(feature = "public-test-deps")] | |
13 | macro_rules! public_test_dep { | |
14 | {$(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*} => { | |
15 | $(#[$($meta)*])* pub $ident $($tokens)* | |
16 | }; | |
17 | } | |
18 | ||
041b39d2 XL |
19 | /// The "main macro" used for defining intrinsics. |
20 | /// | |
21 | /// The compiler-builtins library is super platform-specific with tons of crazy | |
22 | /// little tweaks for various platforms. As a result it *could* involve a lot of | |
23 | /// #[cfg] and macro soup, but the intention is that this macro alleviates a lot | |
24 | /// of that complexity. Ideally this macro has all the weird ABI things | |
25 | /// platforms need and elsewhere in this library it just looks like normal Rust | |
26 | /// code. | |
27 | /// | |
49aad941 FG |
28 | /// When the weak-intrinsics feature is enabled, all intrinsics functions are |
29 | /// marked with #[linkage = "weak"] so that they can be replaced by another | |
30 | /// implementation at link time. This is particularly useful for mixed Rust/C++ | |
31 | /// binaries that want to use the C++ intrinsics, otherwise linking against the | |
32 | /// Rust stdlib will replace those from the compiler-rt library. | |
33 | /// | |
041b39d2 XL |
34 | /// This macro is structured to be invoked with a bunch of functions that looks |
35 | /// like: | |
36 | /// | |
37 | /// intrinsics! { | |
38 | /// pub extern "C" fn foo(a: i32) -> u32 { | |
39 | /// // ... | |
40 | /// } | |
41 | /// | |
42 | /// #[nonstandard_attribute] | |
43 | /// pub extern "C" fn bar(a: i32) -> u32 { | |
44 | /// // ... | |
45 | /// } | |
46 | /// } | |
47 | /// | |
48 | /// Each function is defined in a manner that looks like a normal Rust function. | |
49 | /// The macro then accepts a few nonstandard attributes that can decorate | |
50 | /// various functions. Each of the attributes is documented below with what it | |
51 | /// can do, and each of them slightly tweaks how further expansion happens. | |
52 | /// | |
53 | /// A quick overview of attributes supported right now are: | |
54 | /// | |
49aad941 FG |
55 | /// * `weak` - indicates that the function should always be given weak linkage. |
56 | /// This attribute must come before other attributes, as the other attributes | |
57 | /// will generate the final output function and need to have `weak` modify | |
58 | /// them. | |
48663c56 XL |
59 | /// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is |
60 | /// ignored if an optimized C version was compiled. | |
041b39d2 XL |
61 | /// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and |
62 | /// the specified ABI everywhere else. | |
63 | /// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the | |
64 | /// `"unadjusted"` abi on Win64 and the specified abi elsewhere. | |
65 | /// * `win64_128bit_abi_hack` - this attribute is used for 128-bit integer | |
66 | /// intrinsics where the ABI is slightly tweaked on Windows platforms, but | |
67 | /// it's a normal ABI elsewhere for returning a 128 bit integer. | |
68 | /// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM | |
69 | /// their otherwise typical names to other prefixed ones. | |
041b39d2 XL |
70 | macro_rules! intrinsics { |
71 | () => (); | |
72 | ||
923072b8 FG |
73 | // Support cfg_attr: |
74 | ( | |
75 | #[cfg_attr($e:meta, $($attr:tt)*)] | |
76 | $(#[$($attrs:tt)*])* | |
77 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
78 | $($body:tt)* | |
79 | } | |
80 | $($rest:tt)* | |
81 | ) => ( | |
82 | #[cfg($e)] | |
83 | intrinsics! { | |
84 | #[$($attr)*] | |
85 | $(#[$($attrs)*])* | |
86 | pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? { | |
87 | $($body)* | |
88 | } | |
89 | } | |
90 | ||
91 | #[cfg(not($e))] | |
92 | intrinsics! { | |
93 | $(#[$($attrs)*])* | |
94 | pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? { | |
95 | $($body)* | |
96 | } | |
97 | } | |
98 | ||
99 | intrinsics!($($rest)*); | |
100 | ); | |
49aad941 FG |
101 | // Same as above but for unsafe. |
102 | ( | |
103 | #[cfg_attr($e:meta, $($attr:tt)*)] | |
104 | $(#[$($attrs:tt)*])* | |
105 | pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
106 | $($body:tt)* | |
107 | } | |
108 | $($rest:tt)* | |
109 | ) => ( | |
110 | #[cfg($e)] | |
111 | intrinsics! { | |
112 | #[$($attr)*] | |
113 | $(#[$($attrs)*])* | |
114 | pub unsafe extern $abi fn $name($($argname: $ty),*) $(-> $ret)? { | |
115 | $($body)* | |
116 | } | |
117 | } | |
118 | ||
119 | #[cfg(not($e))] | |
120 | intrinsics! { | |
121 | $(#[$($attrs)*])* | |
122 | pub unsafe extern $abi fn $name($($argname: $ty),*) $(-> $ret)? { | |
123 | $($body)* | |
124 | } | |
125 | } | |
126 | ||
127 | intrinsics!($($rest)*); | |
128 | ); | |
129 | ||
130 | // Explicit weak linkage gets dropped when weak-intrinsics is on since it | |
131 | // will be added unconditionally to all intrinsics and would conflict | |
132 | // otherwise. | |
133 | ( | |
134 | #[weak] | |
135 | $(#[$($attr:tt)*])* | |
136 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
137 | $($body:tt)* | |
138 | } | |
139 | ||
140 | $($rest:tt)* | |
141 | ) => ( | |
142 | #[cfg(feature = "weak-intrinsics")] | |
143 | intrinsics! { | |
144 | $(#[$($attr)*])* | |
145 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
146 | $($body)* | |
147 | } | |
148 | } | |
149 | ||
150 | #[cfg(not(feature = "weak-intrinsics"))] | |
151 | intrinsics! { | |
152 | $(#[$($attr)*])* | |
153 | #[linkage = "weak"] | |
154 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
155 | $($body)* | |
156 | } | |
157 | } | |
158 | ||
159 | intrinsics!($($rest)*); | |
160 | ); | |
161 | // Same as above but for unsafe. | |
162 | ( | |
163 | #[weak] | |
164 | $(#[$($attr:tt)*])* | |
165 | pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
166 | $($body:tt)* | |
167 | } | |
168 | ||
169 | $($rest:tt)* | |
170 | ) => ( | |
171 | #[cfg(feature = "weak-intrinsics")] | |
172 | intrinsics! { | |
173 | $(#[$($attr)*])* | |
174 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
175 | $($body)* | |
176 | } | |
177 | } | |
178 | ||
179 | #[cfg(not(feature = "weak-intrinsics"))] | |
180 | intrinsics! { | |
181 | $(#[$($attr)*])* | |
182 | #[linkage = "weak"] | |
183 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
184 | $($body)* | |
185 | } | |
186 | } | |
187 | ||
188 | intrinsics!($($rest)*); | |
189 | ); | |
923072b8 | 190 | |
041b39d2 XL |
191 | // Right now there's a bunch of architecture-optimized intrinsics in the |
192 | // stock compiler-rt implementation. Not all of these have been ported over | |
193 | // to Rust yet so when the `c` feature of this crate is enabled we fall back | |
194 | // to the architecture-specific versions which should be more optimized. The | |
195 | // purpose of this macro is to easily allow specifying this. | |
196 | // | |
48663c56 XL |
197 | // The `#[maybe_use_optimized_c_shim]` attribute indicates that this |
198 | // intrinsic may have an optimized C version. In these situations the build | |
199 | // script, if the C code is enabled and compiled, will emit a cfg directive | |
200 | // to get passed to rustc for our compilation. If that cfg is set we skip | |
201 | // the Rust implementation, but if the attribute is not enabled then we | |
202 | // compile in the Rust implementation. | |
041b39d2 | 203 | ( |
48663c56 | 204 | #[maybe_use_optimized_c_shim] |
041b39d2 | 205 | $(#[$($attr:tt)*])* |
5099ac24 | 206 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
041b39d2 XL |
207 | $($body:tt)* |
208 | } | |
209 | ||
210 | $($rest:tt)* | |
211 | ) => ( | |
48663c56 | 212 | #[cfg($name = "optimized-c")] |
49aad941 | 213 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 | 214 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 | 215 | extern $abi { |
5099ac24 | 216 | fn $name($($argname: $ty),*) $(-> $ret)?; |
041b39d2 XL |
217 | } |
218 | unsafe { | |
219 | $name($($argname),*) | |
220 | } | |
221 | } | |
222 | ||
48663c56 | 223 | #[cfg(not($name = "optimized-c"))] |
041b39d2 XL |
224 | intrinsics! { |
225 | $(#[$($attr)*])* | |
5099ac24 | 226 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
227 | $($body)* |
228 | } | |
229 | } | |
230 | ||
231 | intrinsics!($($rest)*); | |
232 | ); | |
233 | ||
234 | // We recognize the `#[aapcs_on_arm]` attribute here and generate the | |
235 | // same intrinsic but force it to have the `"aapcs"` calling convention on | |
236 | // ARM and `"C"` elsewhere. | |
237 | ( | |
238 | #[aapcs_on_arm] | |
239 | $(#[$($attr:tt)*])* | |
5099ac24 | 240 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
041b39d2 XL |
241 | $($body:tt)* |
242 | } | |
243 | ||
244 | $($rest:tt)* | |
245 | ) => ( | |
246 | #[cfg(target_arch = "arm")] | |
247 | intrinsics! { | |
248 | $(#[$($attr)*])* | |
5099ac24 | 249 | pub extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
250 | $($body)* |
251 | } | |
252 | } | |
253 | ||
254 | #[cfg(not(target_arch = "arm"))] | |
255 | intrinsics! { | |
256 | $(#[$($attr)*])* | |
5099ac24 | 257 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
258 | $($body)* |
259 | } | |
260 | } | |
261 | ||
262 | intrinsics!($($rest)*); | |
263 | ); | |
264 | ||
265 | // Like aapcs above we recognize an attribute for the "unadjusted" abi on | |
266 | // win64 for some methods. | |
267 | ( | |
268 | #[unadjusted_on_win64] | |
269 | $(#[$($attr:tt)*])* | |
5099ac24 | 270 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
041b39d2 XL |
271 | $($body:tt)* |
272 | } | |
273 | ||
274 | $($rest:tt)* | |
275 | ) => ( | |
f2b60f7d | 276 | #[cfg(all(any(windows, all(target_os = "uefi", target_arch = "x86_64")), target_pointer_width = "64"))] |
041b39d2 XL |
277 | intrinsics! { |
278 | $(#[$($attr)*])* | |
5099ac24 | 279 | pub extern "unadjusted" fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
280 | $($body)* |
281 | } | |
282 | } | |
283 | ||
f2b60f7d | 284 | #[cfg(not(all(any(windows, all(target_os = "uefi", target_arch = "x86_64")), target_pointer_width = "64")))] |
041b39d2 XL |
285 | intrinsics! { |
286 | $(#[$($attr)*])* | |
5099ac24 | 287 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
288 | $($body)* |
289 | } | |
290 | } | |
291 | ||
292 | intrinsics!($($rest)*); | |
293 | ); | |
294 | ||
295 | // Some intrinsics on win64 which return a 128-bit integer have an.. unusual | |
296 | // calling convention. That's managed here with this "abi hack" which alters | |
297 | // the generated symbol's ABI. | |
298 | // | |
299 | // This will still define a function in this crate with the given name and | |
300 | // signature, but the actual symbol for the intrinsic may have a slightly | |
301 | // different ABI on win64. | |
302 | ( | |
303 | #[win64_128bit_abi_hack] | |
304 | $(#[$($attr:tt)*])* | |
5099ac24 | 305 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
041b39d2 XL |
306 | $($body:tt)* |
307 | } | |
308 | ||
309 | $($rest:tt)* | |
310 | ) => ( | |
f2b60f7d | 311 | #[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))] |
041b39d2 | 312 | $(#[$($attr)*])* |
49aad941 | 313 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 | 314 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
315 | $($body)* |
316 | } | |
317 | ||
f2b60f7d | 318 | #[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))] |
041b39d2 | 319 | pub mod $name { |
ba9703b0 | 320 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] |
49aad941 | 321 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
ba9703b0 XL |
322 | pub extern $abi fn $name( $($argname: $ty),* ) |
323 | -> ::macros::win64_128bit_abi_hack::U64x2 | |
324 | { | |
5099ac24 | 325 | let e: $($ret)? = super::$name($($argname),*); |
ba9703b0 | 326 | ::macros::win64_128bit_abi_hack::U64x2::from(e) |
041b39d2 XL |
327 | } |
328 | } | |
329 | ||
f2b60f7d | 330 | #[cfg(not(all(any(windows, target_os = "uefi"), target_arch = "x86_64")))] |
041b39d2 XL |
331 | intrinsics! { |
332 | $(#[$($attr)*])* | |
5099ac24 | 333 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
334 | $($body)* |
335 | } | |
336 | } | |
337 | ||
338 | intrinsics!($($rest)*); | |
339 | ); | |
340 | ||
341 | // A bunch of intrinsics on ARM are aliased in the standard compiler-rt | |
342 | // build under `__aeabi_*` aliases, and LLVM will call these instead of the | |
343 | // original function. The aliasing here is used to generate these symbols in | |
344 | // the object file. | |
345 | ( | |
346 | #[arm_aeabi_alias = $alias:ident] | |
347 | $(#[$($attr:tt)*])* | |
5099ac24 | 348 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
041b39d2 XL |
349 | $($body:tt)* |
350 | } | |
351 | ||
352 | $($rest:tt)* | |
353 | ) => ( | |
354 | #[cfg(target_arch = "arm")] | |
5099ac24 | 355 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
356 | $($body)* |
357 | } | |
358 | ||
359 | #[cfg(target_arch = "arm")] | |
360 | pub mod $name { | |
ba9703b0 | 361 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] |
49aad941 | 362 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 | 363 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
ba9703b0 XL |
364 | super::$name($($argname),*) |
365 | } | |
366 | } | |
367 | ||
368 | #[cfg(target_arch = "arm")] | |
369 | pub mod $alias { | |
370 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] | |
49aad941 | 371 | #[cfg_attr(any(all(not(windows), not(target_vendor="apple"), feature = "weak-intrinsics")), linkage = "weak")] |
5099ac24 | 372 | pub extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? { |
ba9703b0 | 373 | super::$name($($argname),*) |
041b39d2 XL |
374 | } |
375 | } | |
376 | ||
377 | #[cfg(not(target_arch = "arm"))] | |
378 | intrinsics! { | |
379 | $(#[$($attr)*])* | |
5099ac24 FG |
380 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
381 | $($body)* | |
382 | } | |
383 | } | |
384 | ||
385 | intrinsics!($($rest)*); | |
386 | ); | |
387 | ||
388 | // C mem* functions are only generated when the "mem" feature is enabled. | |
389 | ( | |
390 | #[mem_builtin] | |
391 | $(#[$($attr:tt)*])* | |
392 | pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
393 | $($body:tt)* | |
394 | } | |
395 | ||
396 | $($rest:tt)* | |
397 | ) => ( | |
398 | $(#[$($attr)*])* | |
399 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
400 | $($body)* | |
401 | } | |
402 | ||
403 | #[cfg(feature = "mem")] | |
404 | pub mod $name { | |
405 | $(#[$($attr)*])* | |
406 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] | |
49aad941 | 407 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 FG |
408 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
409 | super::$name($($argname),*) | |
410 | } | |
411 | } | |
412 | ||
413 | intrinsics!($($rest)*); | |
414 | ); | |
415 | ||
416 | // Naked functions are special: we can't generate wrappers for them since | |
417 | // they use a custom calling convention. | |
418 | ( | |
419 | #[naked] | |
420 | $(#[$($attr:tt)*])* | |
421 | pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
422 | $($body:tt)* | |
423 | } | |
424 | ||
425 | $($rest:tt)* | |
426 | ) => ( | |
427 | pub mod $name { | |
428 | #[naked] | |
429 | $(#[$($attr)*])* | |
430 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] | |
49aad941 | 431 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 | 432 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
433 | $($body)* |
434 | } | |
435 | } | |
436 | ||
437 | intrinsics!($($rest)*); | |
438 | ); | |
439 | ||
923072b8 FG |
440 | // For division and modulo, AVR uses a custom calling convention¹ that does |
441 | // not match our definitions here. Ideally we would just use hand-written | |
442 | // naked functions, but that's quite a lot of code to port² - so for the | |
443 | // time being we are just ignoring the problematic functions, letting | |
444 | // avr-gcc (which is required to compile to AVR anyway) link them from | |
445 | // libgcc. | |
446 | // | |
447 | // ¹ https://gcc.gnu.org/wiki/avr-gcc (see "Exceptions to the Calling | |
448 | // Convention") | |
449 | // ² https://github.com/gcc-mirror/gcc/blob/31048012db98f5ec9c2ba537bfd850374bdd771f/libgcc/config/avr/lib1funcs.S | |
450 | ( | |
451 | #[avr_skip] | |
452 | $(#[$($attr:tt)*])* | |
453 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
454 | $($body:tt)* | |
455 | } | |
456 | ||
457 | $($rest:tt)* | |
458 | ) => ( | |
459 | #[cfg(not(target_arch = "avr"))] | |
460 | intrinsics! { | |
461 | $(#[$($attr)*])* | |
462 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
463 | $($body)* | |
464 | } | |
465 | } | |
466 | ||
467 | intrinsics!($($rest)*); | |
468 | ); | |
469 | ||
ba9703b0 | 470 | // This is the final catch-all rule. At this point we generate an |
041b39d2 | 471 | // intrinsic with a conditional `#[no_mangle]` directive to avoid |
ba9703b0 XL |
472 | // interfering with duplicate symbols and whatnot during testing. |
473 | // | |
474 | // The implementation is placed in a separate module, to take advantage | |
475 | // of the fact that rustc partitions functions into code generation | |
476 | // units based on module they are defined in. As a result we will have | |
477 | // a separate object file for each intrinsic. For further details see | |
478 | // corresponding PR in rustc https://github.com/rust-lang/rust/pull/70846 | |
041b39d2 XL |
479 | // |
480 | // After the intrinsic is defined we just continue with the rest of the | |
481 | // input we were given. | |
482 | ( | |
483 | $(#[$($attr:tt)*])* | |
5099ac24 FG |
484 | pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { |
485 | $($body:tt)* | |
486 | } | |
487 | ||
488 | $($rest:tt)* | |
489 | ) => ( | |
490 | $(#[$($attr)*])* | |
491 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { | |
492 | $($body)* | |
493 | } | |
494 | ||
495 | pub mod $name { | |
496 | $(#[$($attr)*])* | |
497 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] | |
49aad941 | 498 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 FG |
499 | pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
500 | super::$name($($argname),*) | |
501 | } | |
502 | } | |
503 | ||
504 | intrinsics!($($rest)*); | |
505 | ); | |
506 | ||
507 | // Same as the above for unsafe functions. | |
508 | ( | |
509 | $(#[$($attr:tt)*])* | |
510 | pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { | |
041b39d2 XL |
511 | $($body:tt)* |
512 | } | |
513 | ||
514 | $($rest:tt)* | |
515 | ) => ( | |
516 | $(#[$($attr)*])* | |
5099ac24 | 517 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
041b39d2 XL |
518 | $($body)* |
519 | } | |
520 | ||
ba9703b0 XL |
521 | pub mod $name { |
522 | $(#[$($attr)*])* | |
523 | #[cfg_attr(not(feature = "mangled-names"), no_mangle)] | |
49aad941 | 524 | #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")] |
5099ac24 | 525 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { |
ba9703b0 XL |
526 | super::$name($($argname),*) |
527 | } | |
528 | } | |
529 | ||
041b39d2 XL |
530 | intrinsics!($($rest)*); |
531 | ); | |
532 | } | |
533 | ||
534 | // Hack for LLVM expectations for ABI on windows. This is used by the | |
535 | // `#[win64_128bit_abi_hack]` attribute recognized above | |
f2b60f7d | 536 | #[cfg(all(any(windows, target_os = "uefi"), target_pointer_width = "64"))] |
041b39d2 XL |
537 | pub mod win64_128bit_abi_hack { |
538 | #[repr(simd)] | |
539 | pub struct U64x2(u64, u64); | |
540 | ||
541 | impl From<i128> for U64x2 { | |
542 | fn from(i: i128) -> U64x2 { | |
5869c6ff | 543 | use int::DInt; |
041b39d2 | 544 | let j = i as u128; |
5869c6ff | 545 | U64x2(j.lo(), j.hi()) |
041b39d2 XL |
546 | } |
547 | } | |
548 | ||
549 | impl From<u128> for U64x2 { | |
550 | fn from(i: u128) -> U64x2 { | |
5869c6ff XL |
551 | use int::DInt; |
552 | U64x2(i.lo(), i.hi()) | |
041b39d2 XL |
553 | } |
554 | } | |
555 | } |