Skip to content

Commit cc2397b

Browse files
authored
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.
2 parents b39e0c2 + 67e746c commit cc2397b

File tree

6 files changed

+30
-1
lines changed

6 files changed

+30
-1
lines changed

compiler/rustc_codegen_llvm/src/callee.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,20 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
8383
let llfn = if tcx.sess.target.arch == "x86" &&
8484
let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym)
8585
{
86-
cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi)
86+
// Fix for https://github.com/rust-lang/rust/issues/104453
87+
// On x86 Windows, LLVM uses 'L' as the prefix for any private
88+
// global symbols, so when we create an undecorated function symbol
89+
// that begins with an 'L' LLVM misinterprets that as a private
90+
// global symbol that it created and so fails the compilation at a
91+
// later stage since such a symbol must have a definition.
92+
//
93+
// To avoid this, we set the Storage Class to "DllImport" so that
94+
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
95+
// existing logic below to set the Storage Class, but it has an
96+
// exemption for MinGW for backwards compatability.
97+
let llfn = cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi);
98+
unsafe { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); }
99+
llfn
87100
} else {
88101
cx.declare_fn(sym, fn_abi)
89102
};

src/test/run-make/raw-dylib-import-name-type/driver.rs

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
55
extern "C" {
6+
fn LooksLikeAPrivateGlobal(i: i32);
67
fn cdecl_fn_undecorated(i: i32);
78
#[link_name = "cdecl_fn_undecorated2"]
89
fn cdecl_fn_undecorated_renamed(i: i32);
@@ -84,6 +85,13 @@ extern {
8485

8586
pub fn main() {
8687
unsafe {
88+
// Regression test for #104453
89+
// On x86 LLVM uses 'L' as the prefix for private globals (PrivateGlobalPrefix), which
90+
// causes it to believe that undecorated functions starting with 'L' are actually temporary
91+
// symbols that it generated, which causes a later check to fail as the symbols we are
92+
// creating don't have definitions (whereas all temporary symbols do).
93+
LooksLikeAPrivateGlobal(13);
94+
8795
cdecl_fn_undecorated(1);
8896
cdecl_fn_undecorated_renamed(10);
8997
cdecl_fn_noprefix(2);

src/test/run-make/raw-dylib-import-name-type/extern.c

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#include <stdio.h>
22
#include <stdint.h>
33

4+
void _cdecl LooksLikeAPrivateGlobal(int i) {
5+
printf("LooksLikeAPrivateGlobal(%d)\n", i);
6+
fflush(stdout);
7+
}
8+
49
void _cdecl cdecl_fn_undecorated(int i) {
510
printf("cdecl_fn_undecorated(%d)\n", i);
611
fflush(stdout);

src/test/run-make/raw-dylib-import-name-type/extern.gnu.def

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
LIBRARY extern
22
EXPORTS
3+
LooksLikeAPrivateGlobal
34
cdecl_fn_undecorated
45
cdecl_fn_undecorated2
56
cdecl_fn_noprefix

src/test/run-make/raw-dylib-import-name-type/extern.msvc.def

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
LIBRARY extern
22
EXPORTS
3+
LooksLikeAPrivateGlobal
34
cdecl_fn_undecorated
45
cdecl_fn_undecorated2
56
cdecl_fn_noprefix

src/test/run-make/raw-dylib-import-name-type/output.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
LooksLikeAPrivateGlobal(13)
12
cdecl_fn_undecorated(1)
23
cdecl_fn_undecorated2(10)
34
cdecl_fn_noprefix(2)

0 commit comments

Comments
 (0)