Skip to content

Mark functions created for raw-dylib on x86 with DllImport storage class #104511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion compiler/rustc_codegen_llvm/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
};
Expand Down
8 changes: 8 additions & 0 deletions src/test/run-make/raw-dylib-import-name-type/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions src/test/run-make/raw-dylib-import-name-type/extern.c
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
LIBRARY extern
EXPORTS
LooksLikeAPrivateGlobal
cdecl_fn_undecorated
cdecl_fn_undecorated2
cdecl_fn_noprefix
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
LIBRARY extern
EXPORTS
LooksLikeAPrivateGlobal
cdecl_fn_undecorated
cdecl_fn_undecorated2
cdecl_fn_noprefix
Expand Down
1 change: 1 addition & 0 deletions src/test/run-make/raw-dylib-import-name-type/output.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
LooksLikeAPrivateGlobal(13)
cdecl_fn_undecorated(1)
cdecl_fn_undecorated2(10)
cdecl_fn_noprefix(2)
Expand Down