Skip to content

Commit 3394329

Browse files
committed
Add the weak-intrinsics feature
When enabled, the weak-intrinsics feature will cause all intrinsics functions to be marked with weak linkage (i.e. `#[linkage = "weak"]) so that they can be replaced at link time by a stronger symbol. This can be set to use C++ intrinsics from the compiler-rt library, as it will avoid Rust's implementation replacing the compiler-rt implementation as long as the compiler-rt symbols are linked as strong symbols. Typically this requires the compiler-rt library to be explicitly specified in the link command. Addresses rust-lang#525.
1 parent 4677881 commit 3394329

File tree

4 files changed

+141
-24
lines changed

4 files changed

+141
-24
lines changed

Diff for: Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ rustc-dep-of-std = ['compiler-builtins', 'core']
6565
# are not normally public but are required by the `testcrate`
6666
public-test-deps = []
6767

68+
# Marks all intrinsics functions with weak linkage so that they can be
69+
# replaced at link time by another implementation. This is particularly useful
70+
# for mixed Rust/C++ binaries that want to use the C++ intrinsics, otherwise
71+
# linking against the Rust stdlib will replace those from the compiler-rt
72+
# library.
73+
#
74+
# Unlike the "c" feature, the intrinsics are still provided by the Rust
75+
# implementations and each will be used unless a stronger symbol replaces
76+
# it during linking.
77+
weak-intrinsics = []
78+
6879
[[example]]
6980
name = "intrinsics"
7081
required-features = ["compiler-builtins"]

Diff for: src/arm.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ macro_rules! bl {
2020
intrinsics! {
2121
// NOTE This function and the ones below are implemented using assembly because they are using a
2222
// custom calling convention which can't be implemented using a normal Rust function.
23+
#[cfg_attr(all(not(windows), not(target_vendor="apple")), weak)]
2324
#[naked]
2425
#[cfg(not(target_env = "msvc"))]
25-
#[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
2626
pub unsafe extern "C" fn __aeabi_uidivmod() {
2727
core::arch::asm!(
2828
"push {{lr}}",
@@ -36,8 +36,8 @@ intrinsics! {
3636
);
3737
}
3838

39+
#[cfg_attr(all(not(windows), not(target_vendor="apple")), weak)]
3940
#[naked]
40-
#[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
4141
pub unsafe extern "C" fn __aeabi_uldivmod() {
4242
core::arch::asm!(
4343
"push {{r4, lr}}",
@@ -53,8 +53,8 @@ intrinsics! {
5353
);
5454
}
5555

56+
#[cfg_attr(all(not(windows), not(target_vendor="apple")), weak)]
5657
#[naked]
57-
#[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
5858
pub unsafe extern "C" fn __aeabi_idivmod() {
5959
core::arch::asm!(
6060
"push {{r0, r1, r4, lr}}",
@@ -67,8 +67,8 @@ intrinsics! {
6767
);
6868
}
6969

70+
#[cfg_attr(all(not(windows), not(target_vendor="apple")), weak)]
7071
#[naked]
71-
#[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
7272
pub unsafe extern "C" fn __aeabi_ldivmod() {
7373
core::arch::asm!(
7474
"push {{r4, lr}}",
@@ -88,14 +88,14 @@ intrinsics! {
8888
// with custom implementation.
8989
// FIXME: The `*4` and `*8` variants should be defined as aliases.
9090

91+
#[weak]
9192
#[cfg(not(target_os = "ios"))]
92-
#[linkage = "weak"]
9393
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
9494
::mem::memcpy(dest, src, n);
9595
}
9696

97+
#[weak]
9798
#[cfg(not(target_os = "ios"))]
98-
#[linkage = "weak"]
9999
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) {
100100
// We are guaranteed 4-alignment, so accessing at u32 is okay.
101101
let mut dest = dest as *mut u32;
@@ -112,39 +112,39 @@ intrinsics! {
112112
__aeabi_memcpy(dest as *mut u8, src as *const u8, n);
113113
}
114114

115+
#[weak]
115116
#[cfg(not(target_os = "ios"))]
116-
#[linkage = "weak"]
117117
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
118118
__aeabi_memcpy4(dest, src, n);
119119
}
120120

121+
#[weak]
121122
#[cfg(not(target_os = "ios"))]
122-
#[linkage = "weak"]
123123
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
124124
::mem::memmove(dest, src, n);
125125
}
126126

127+
#[weak]
127128
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
128-
#[linkage = "weak"]
129129
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
130130
__aeabi_memmove(dest, src, n);
131131
}
132132

133+
#[weak]
133134
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
134-
#[linkage = "weak"]
135135
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
136136
__aeabi_memmove(dest, src, n);
137137
}
138138

139+
#[weak]
139140
#[cfg(not(target_os = "ios"))]
140-
#[linkage = "weak"]
141141
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
142142
// Note the different argument order
143143
::mem::memset(dest, c, n);
144144
}
145145

146+
#[weak]
146147
#[cfg(not(target_os = "ios"))]
147-
#[linkage = "weak"]
148148
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) {
149149
let mut dest = dest as *mut u32;
150150
let mut n = n;
@@ -161,26 +161,26 @@ intrinsics! {
161161
__aeabi_memset(dest as *mut u8, n, byte as i32);
162162
}
163163

164+
#[weak]
164165
#[cfg(not(target_os = "ios"))]
165-
#[linkage = "weak"]
166166
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
167167
__aeabi_memset4(dest, n, c);
168168
}
169169

170+
#[weak]
170171
#[cfg(not(target_os = "ios"))]
171-
#[linkage = "weak"]
172172
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
173173
__aeabi_memset(dest, n, 0);
174174
}
175175

176+
#[weak]
176177
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
177-
#[linkage = "weak"]
178178
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
179179
__aeabi_memset4(dest, n, 0);
180180
}
181181

182+
#[weak]
182183
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
183-
#[linkage = "weak"]
184184
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
185185
__aeabi_memset4(dest, n, 0);
186186
}

Diff for: src/macros.rs

+108-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ macro_rules! public_test_dep {
2525
/// platforms need and elsewhere in this library it just looks like normal Rust
2626
/// code.
2727
///
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+
///
2834
/// This macro is structured to be invoked with a bunch of functions that looks
2935
/// like:
3036
///
@@ -46,6 +52,10 @@ macro_rules! public_test_dep {
4652
///
4753
/// A quick overview of attributes supported right now are:
4854
///
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.
4959
/// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is
5060
/// ignored if an optimized C version was compiled.
5161
/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and
@@ -57,7 +67,6 @@ macro_rules! public_test_dep {
5767
/// it's a normal ABI elsewhere for returning a 128 bit integer.
5868
/// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM
5969
/// their otherwise typical names to other prefixed ones.
60-
///
6170
macro_rules! intrinsics {
6271
() => ();
6372

@@ -89,6 +98,95 @@ macro_rules! intrinsics {
8998

9099
intrinsics!($($rest)*);
91100
);
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+
);
92190

93191
// Right now there's a bunch of architecture-optimized intrinsics in the
94192
// stock compiler-rt implementation. Not all of these have been ported over
@@ -112,6 +210,7 @@ macro_rules! intrinsics {
112210
$($rest:tt)*
113211
) => (
114212
#[cfg($name = "optimized-c")]
213+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
115214
pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
116215
extern $abi {
117216
fn $name($($argname: $ty),*) $(-> $ret)?;
@@ -211,13 +310,15 @@ macro_rules! intrinsics {
211310
) => (
212311
#[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))]
213312
$(#[$($attr)*])*
313+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
214314
pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
215315
$($body)*
216316
}
217317

218318
#[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))]
219319
pub mod $name {
220320
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
321+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
221322
pub extern $abi fn $name( $($argname: $ty),* )
222323
-> ::macros::win64_128bit_abi_hack::U64x2
223324
{
@@ -258,6 +359,7 @@ macro_rules! intrinsics {
258359
#[cfg(target_arch = "arm")]
259360
pub mod $name {
260361
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
362+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
261363
pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
262364
super::$name($($argname),*)
263365
}
@@ -266,7 +368,7 @@ macro_rules! intrinsics {
266368
#[cfg(target_arch = "arm")]
267369
pub mod $alias {
268370
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
269-
#[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
371+
#[cfg_attr(any(all(not(windows), not(target_vendor="apple"), feature = "weak-intrinsics")), linkage = "weak")]
270372
pub extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
271373
super::$name($($argname),*)
272374
}
@@ -302,6 +404,7 @@ macro_rules! intrinsics {
302404
pub mod $name {
303405
$(#[$($attr)*])*
304406
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
407+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
305408
pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
306409
super::$name($($argname),*)
307410
}
@@ -325,6 +428,7 @@ macro_rules! intrinsics {
325428
#[naked]
326429
$(#[$($attr)*])*
327430
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
431+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
328432
pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
329433
$($body)*
330434
}
@@ -391,6 +495,7 @@ macro_rules! intrinsics {
391495
pub mod $name {
392496
$(#[$($attr)*])*
393497
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
498+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
394499
pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
395500
super::$name($($argname),*)
396501
}
@@ -416,6 +521,7 @@ macro_rules! intrinsics {
416521
pub mod $name {
417522
$(#[$($attr)*])*
418523
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
524+
#[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
419525
pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
420526
super::$name($($argname),*)
421527
}

0 commit comments

Comments
 (0)