Skip to content

Commit f9f2fdc

Browse files
committed
[clang] [MinGW] Add the option -fno-auto-import
In GCC, the .refptr stubs are only generated for x86_64, and only for code models medium and larger (and medium is the default for x86_64 since this was introduced). They can be omitted for projects that are conscious about performance and size, and don't need automatically importing dll data members, by passing -mcmodel=small. In Clang/LLVM, such .refptr stubs are generated for any potentially symbol reference that might end up autoimported. The .refptr stubs are emitted for three separate reasons: - Without .refptr stubs, undefined symbols are mostly referenced with 32 bit wide relocations. If the symbol ends up autoimported from a different DLL, a 32 bit relative offset might not be enough to reference data in a different DLL, depending on runtime loader layout. - Without .refptr stubs, the runtime pseudo relocation mechanism will need to temporarily make sections read-write-executable if there are such relocations in the text section - On ARM and AArch64, the immediate addressing encoded into instructions isn't in the form of a plain 32 bit relative offset, but is expressed with various bits scattered throughout two instructions - the mingw runtime pseudo relocation mechanism doesn't support updating offsets in that form. If autoimporting is known not to be needed, the user can now compile with -fno-auto-import, avoiding the extra overhead of the .refptr stubs. However, omitting them is potentially fragile as the code might still rely on automatically importing some symbol without the developer knowing. If this happens, linking still usually will succeed, but users may encounter issues at runtime. Therefore, if the new option -fno-auto-import is passed to the compiler when driving linking, it passes the flag --disable-auto-import to the linker, making sure that no symbols actually are autoimported when the generated code doesn't expect it. Differential Revision: https://reviews.llvm.org/D61670
1 parent 898bf53 commit f9f2fdc

File tree

8 files changed

+52
-5
lines changed

8 files changed

+52
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ Windows Support
300300
``MSInheritanceAttr`` attributes to class template instantiations created
301301
for explicit template instantiation declarations.
302302

303+
- The ``-fno-auto-import`` option was added for MinGW targets. The option both
304+
affects code generation (inhibiting generating indirection via ``.refptr``
305+
stubs for potentially auto imported symbols, generating smaller and more
306+
efficient code) and linking (making the linker error out on such cases).
307+
If the option only is used during code generation but not when linking,
308+
linking may succeed but the resulting executables may expose issues at
309+
runtime.
310+
303311
LoongArch Support
304312
^^^^^^^^^^^^^^^^^
305313

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
3838
CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new
3939
CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable.
4040
CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
41+
CODEGENOPT(AutoImport , 1, 1) ///< -fno-auto-import
4142
CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
4243
CODEGENOPT(Backchain , 1, 0) ///< -mbackchain
4344
CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks

clang/include/clang/Driver/Options.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,17 @@ defm autolink : BoolFOption<"autolink",
14691469
"Disable generation of linker directives for automatic library linking">,
14701470
PosFlag<SetTrue>>;
14711471

1472+
let Flags = [TargetSpecific] in {
1473+
defm auto_import : BoolFOption<"auto-import",
1474+
CodeGenOpts<"AutoImport">, DefaultTrue,
1475+
NegFlag<SetFalse, [], [ClangOption, CC1Option],
1476+
"MinGW specific. Disable support for automatic dllimport in code generation "
1477+
"and linking">,
1478+
PosFlag<SetTrue, [], [], "MinGW specific. Enable code generation support for "
1479+
"automatic dllimport, and enable support for it in the linker. "
1480+
"Enabled by default.">>;
1481+
} // let Flags = [TargetSpecific]
1482+
14721483
// In the future this option will be supported by other offloading
14731484
// languages and accept other values such as CPU/GPU architectures,
14741485
// offload kinds and target aliases.

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,7 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
14191419
return false;
14201420

14211421
const llvm::Triple &TT = CGM.getTriple();
1422+
const auto &CGOpts = CGM.getCodeGenOpts();
14221423
if (TT.isWindowsGNUEnvironment()) {
14231424
// In MinGW, variables without DLLImport can still be automatically
14241425
// imported from a DLL by the linker; don't mark variables that
@@ -1429,7 +1430,8 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
14291430
// such variables can't be marked as DSO local. (Native TLS variables
14301431
// can't be dllimported at all, though.)
14311432
if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) &&
1432-
(!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS))
1433+
(!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS) &&
1434+
CGOpts.AutoImport)
14331435
return false;
14341436
}
14351437

@@ -1452,7 +1454,6 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
14521454
return false;
14531455

14541456
// If this is not an executable, don't assume anything is local.
1455-
const auto &CGOpts = CGM.getCodeGenOpts();
14561457
llvm::Reloc::Model RM = CGOpts.RelocationModel;
14571458
const auto &LOpts = CGM.getLangOpts();
14581459
if (RM != llvm::Reloc::Static && !LOpts.PIE) {

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5623,6 +5623,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
56235623
CmdArgs.push_back("-mms-bitfields");
56245624
}
56255625

5626+
if (Triple.isWindowsGNUEnvironment()) {
5627+
Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
5628+
options::OPT_fno_auto_import);
5629+
}
5630+
56265631
// Non-PIC code defaults to -fdirect-access-external-data while PIC code
56275632
// defaults to -fno-direct-access-external-data. Pass the option if different
56285633
// from the default.

clang/lib/Driver/ToolChains/MinGW.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
169169
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
170170
CmdArgs.push_back("--no-demangle");
171171

172+
if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import,
173+
true))
174+
CmdArgs.push_back("--disable-auto-import");
175+
172176
if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) {
173177
StringRef GuardArgs = A->getValue();
174178
if (GuardArgs == "none")

clang/test/CodeGen/dso-local-executable.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
// COFF-DAG: define dso_local ptr @zed()
1010
// COFF-DAG: declare dllimport void @import_func()
1111

12-
// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS %s
13-
// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS %s
12+
// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS,MINGW-AUTO-IMPORT %s
13+
// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -fno-auto-import | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS,MINGW-NO-AUTO-IMPORT %s
14+
// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS,MINGW-AUTO-IMPORT %s
1415
// MINGW: @baz = dso_local global i32 42
1516
// MINGW-NEXT: @import_var = external dllimport global i32
1617
// MINGW-NEXT: @weak_bar = extern_weak global i32
17-
// MINGW-NEXT: @bar = external global i32
18+
// MINGW-AUTO-IMPORT-NEXT: @bar = external global i32
19+
// MINGW-NO-AUTO-IMPORT-NEXT: @bar = external dso_local global i32
1820
// MINGW-NEXT: @local_thread_var = dso_local thread_local global i32 42
1921
// MINGW-NATIVE_TLS-NEXT: @thread_var = external dso_local thread_local global i32
2022
// MINGW-EMUTLS-NEXT: @thread_var = external thread_local global i32

clang/test/Driver/mingw-auto-import.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// By default, we don't pass any -fauto-import to -cc1, as that's the default.
2+
//
3+
// RUN: %clang --target=x86_64-w64-windows-gnu -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s
4+
// RUN: %clang --target=x86_64-w64-windows-gnu -fno-auto-import -fauto-import -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s
5+
// DEFAULT: "-cc1"
6+
// DEFAULT-NOT: no-auto-import
7+
// DEFAULT-NOT: --disable-auto-import
8+
9+
// When compiling with -fno-auto-import, we pass -fno-auto-import to -cc1
10+
// and --disable-auto-import to the linker.
11+
//
12+
// RUN: %clang --target=x86_64-w64-windows-gnu -fauto-import -fno-auto-import -### %s 2>&1 | FileCheck --check-prefixes=NO_AUTOIMPORT %s
13+
// NO_AUTOIMPORT: "-cc1"
14+
// NO_AUTOIMPORT: "-fno-auto-import"
15+
// NO_AUTOIMPORT: "--disable-auto-import"

0 commit comments

Comments
 (0)