diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index c4887464e19c..5db87c0c38a7 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -83,20 +83,16 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { unnamed: llvm::UnnamedAddr, fn_type: &'ll Type, ) -> &'ll Value { - // Declare C ABI functions with the visibility used by C by default. - let visibility = if self.tcx.sess.default_hidden_visibility() { - llvm::Visibility::Hidden - } else { - llvm::Visibility::Default - }; - - declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) + // Declare C ABI functions with Default visibility to allow them to link + // dynamically with shared object-provided symbols later on. This is + // needed to link intrinsic-generated calls to e.g. libc.so symbols like + // memcmp. + declare_raw_fn(self, name, llvm::CCallConv, unnamed, llvm::Visibility::Default, fn_type) } /// Declare an entry Function /// - /// The ABI of this function can change depending on the target (although for now the same as - /// `declare_cfn`) + /// The ABI of this function can change depending on the target. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. diff --git a/tests/codegen/default-hidden-visibility.rs b/tests/codegen/default-hidden-visibility.rs index 2bea8f62a40d..f790717f7510 100644 --- a/tests/codegen/default-hidden-visibility.rs +++ b/tests/codegen/default-hidden-visibility.rs @@ -29,3 +29,18 @@ pub static tested_symbol: [u8; 6] = *b"foobar"; // DEFAULT: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant // YES: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = hidden constant // NO: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant + +pub fn do_memcmp(left: &[u8], right: &[u8]) -> i32 { + left.cmp(right) as i32 +} + +// CHECK: define {{.*}} @{{.*}}do_memcmp{{.*}} { +// CHECK: } + +// `do_memcmp` should invoke core::intrinsic::compare_bytes which emits a call +// to the C symbol `memcmp` (at least on x86_64-unknown-linux-gnu). This symbol +// should *not* be `declare hidden`. + +// DEFAULT: declare i32 @memcmp +// YES: declare i32 @memcmp +// NO: declare i32 @memcmp diff --git a/tests/ui/intrinsics/default-hidden-visibility-intrinsic.rs b/tests/ui/intrinsics/default-hidden-visibility-intrinsic.rs new file mode 100644 index 000000000000..cf681c5aafcb --- /dev/null +++ b/tests/ui/intrinsics/default-hidden-visibility-intrinsic.rs @@ -0,0 +1,10 @@ +//@ build-pass +//@ compile-flags: -Zdefault-hidden-visibility=yes +//@ ignore-wasm32 dylibs unsupported, and below does not work +//@ needs-dynamic-linking + +#![crate_type = "dylib"] + +pub fn do_memcmp(left: &[u8], right: &[u8]) -> i32 { + left.cmp(right) as i32 +}