about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-11-21 14:11:10 +0100
committerGitHub <noreply@github.com>2022-11-21 14:11:10 +0100
commitcc2397b2cd654833b3f02a4153819a9be3824860 (patch)
tree318cddc1d368e560c3f0121023c574419f3589cd /compiler/rustc_codegen_llvm/src
parentb39e0c23bb6b285754b6b38a731846c69b4c3269 (diff)
parent67e746cc688ec6f02a446c6e17d269ce81c1737b (diff)
downloadrust-cc2397b2cd654833b3f02a4153819a9be3824860.tar.gz
rust-cc2397b2cd654833b3f02a4153819a9be3824860.zip
Rollup merge of #104511 - dpaoliello:privateglobalworkaround, r=michaelwoerister
Mark functions created for `raw-dylib` on x86 with DllImport storage class

Fix for #104453

## Issue Details
On x86 Windows, LLVM uses 'L' as the prefix for any private global symbols (`PrivateGlobalPrefix`), so when the `raw-dylib` feature creates an undecorated function symbol that begins with an 'L' LLVM misinterprets that as a private global symbol that it created and so fails the compilation at a later stage since such a symbol must have a definition.

## Fix Details
Mark the function we are creating for `raw-dylib` with `DllImport` storage class (this was already being done for MSVC at a later point for `callee::get_fn` but not for GNU (due to "backwards compatibility")): this will cause LLVM to prefix the name with `__imp_` and so it won't mistake it for a private global symbol.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs15
1 files changed, 14 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index 6f0d1b7ce84..70ff5c9617b 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -83,7 +83,20 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
         let llfn = if tcx.sess.target.arch == "x86" &&
             let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym)
         {
-            cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi)
+            // Fix for https://github.com/rust-lang/rust/issues/104453
+            // On x86 Windows, LLVM uses 'L' as the prefix for any private
+            // global symbols, so when we create an undecorated function symbol
+            // that begins with an 'L' LLVM misinterprets that as a private
+            // global symbol that it created and so fails the compilation at a
+            // later stage since such a symbol must have a definition.
+            //
+            // To avoid this, we set the Storage Class to "DllImport" so that
+            // LLVM will prefix the name with `__imp_`. Ideally, we'd like the
+            // existing logic below to set the Storage Class, but it has an
+            // exemption for MinGW for backwards compatability.
+            let llfn = cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi);
+            unsafe { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); }
+            llfn
         } else {
             cx.declare_fn(sym, fn_abi)
         };