about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Paoliello <danpao@microsoft.com>2022-11-16 15:34:12 -0800
committerDaniel Paoliello <danpao@microsoft.com>2022-11-18 11:38:31 -0800
commit67e746cc688ec6f02a446c6e17d269ce81c1737b (patch)
treec436aa87c223c12ff2ae1441a3614961de3b33c4
parente69336efe035c274f2ee66922cd9cac6015956ea (diff)
downloadrust-67e746cc688ec6f02a446c6e17d269ce81c1737b.tar.gz
rust-67e746cc688ec6f02a446c6e17d269ce81c1737b.zip
Workaround for private global symbol issue
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs15
-rw-r--r--src/test/run-make/raw-dylib-import-name-type/driver.rs8
-rw-r--r--src/test/run-make/raw-dylib-import-name-type/extern.c5
-rw-r--r--src/test/run-make/raw-dylib-import-name-type/extern.gnu.def1
-rw-r--r--src/test/run-make/raw-dylib-import-name-type/extern.msvc.def1
-rw-r--r--src/test/run-make/raw-dylib-import-name-type/output.txt1
6 files changed, 30 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)
         };
diff --git a/src/test/run-make/raw-dylib-import-name-type/driver.rs b/src/test/run-make/raw-dylib-import-name-type/driver.rs
index a38849fc813..9a3cd9ebe1b 100644
--- a/src/test/run-make/raw-dylib-import-name-type/driver.rs
+++ b/src/test/run-make/raw-dylib-import-name-type/driver.rs
@@ -3,6 +3,7 @@
 
 #[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
 extern "C" {
+    fn LooksLikeAPrivateGlobal(i: i32);
     fn cdecl_fn_undecorated(i: i32);
     #[link_name = "cdecl_fn_undecorated2"]
     fn cdecl_fn_undecorated_renamed(i: i32);
@@ -84,6 +85,13 @@ extern {
 
 pub fn main() {
     unsafe {
+        // Regression test for #104453
+        // On x86 LLVM uses 'L' as the prefix for private globals (PrivateGlobalPrefix), which
+        // causes it to believe that undecorated functions starting with 'L' are actually temporary
+        // symbols that it generated, which causes a later check to fail as the symbols we are
+        // creating don't have definitions (whereas all temporary symbols do).
+        LooksLikeAPrivateGlobal(13);
+
         cdecl_fn_undecorated(1);
         cdecl_fn_undecorated_renamed(10);
         cdecl_fn_noprefix(2);
diff --git a/src/test/run-make/raw-dylib-import-name-type/extern.c b/src/test/run-make/raw-dylib-import-name-type/extern.c
index 195126d5129..23c1e489e5e 100644
--- a/src/test/run-make/raw-dylib-import-name-type/extern.c
+++ b/src/test/run-make/raw-dylib-import-name-type/extern.c
@@ -1,6 +1,11 @@
 #include <stdio.h>
 #include <stdint.h>
 
+void _cdecl LooksLikeAPrivateGlobal(int i) {
+    printf("LooksLikeAPrivateGlobal(%d)\n", i);
+    fflush(stdout);
+}
+
 void _cdecl cdecl_fn_undecorated(int i) {
     printf("cdecl_fn_undecorated(%d)\n", i);
     fflush(stdout);
diff --git a/src/test/run-make/raw-dylib-import-name-type/extern.gnu.def b/src/test/run-make/raw-dylib-import-name-type/extern.gnu.def
index a523c959a47..498e90e862d 100644
--- a/src/test/run-make/raw-dylib-import-name-type/extern.gnu.def
+++ b/src/test/run-make/raw-dylib-import-name-type/extern.gnu.def
@@ -1,5 +1,6 @@
 LIBRARY extern
 EXPORTS
+    LooksLikeAPrivateGlobal
     cdecl_fn_undecorated
     cdecl_fn_undecorated2
     cdecl_fn_noprefix
diff --git a/src/test/run-make/raw-dylib-import-name-type/extern.msvc.def b/src/test/run-make/raw-dylib-import-name-type/extern.msvc.def
index dbff32d4c90..cddb88bb8b5 100644
--- a/src/test/run-make/raw-dylib-import-name-type/extern.msvc.def
+++ b/src/test/run-make/raw-dylib-import-name-type/extern.msvc.def
@@ -1,5 +1,6 @@
 LIBRARY extern
 EXPORTS
+    LooksLikeAPrivateGlobal
     cdecl_fn_undecorated
     cdecl_fn_undecorated2
     cdecl_fn_noprefix
diff --git a/src/test/run-make/raw-dylib-import-name-type/output.txt b/src/test/run-make/raw-dylib-import-name-type/output.txt
index 707faf403ae..a2a2bfeec7d 100644
--- a/src/test/run-make/raw-dylib-import-name-type/output.txt
+++ b/src/test/run-make/raw-dylib-import-name-type/output.txt
@@ -1,3 +1,4 @@
+LooksLikeAPrivateGlobal(13)
 cdecl_fn_undecorated(1)
 cdecl_fn_undecorated2(10)
 cdecl_fn_noprefix(2)