[clang] f9f2fdc - [clang] [MinGW] Add the option -fno-auto-import

Martin Storsjö via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 1 12:41:08 PDT 2023


Author: Martin Storsjö
Date: 2023-09-01T22:39:38+03:00
New Revision: f9f2fdcf03d9a64741e24a5d480842551163ef4d

URL: https://github.com/llvm/llvm-project/commit/f9f2fdcf03d9a64741e24a5d480842551163ef4d
DIFF: https://github.com/llvm/llvm-project/commit/f9f2fdcf03d9a64741e24a5d480842551163ef4d.diff

LOG: [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

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

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Driver/Options.td
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/MinGW.cpp
    clang/test/CodeGen/dso-local-executable.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e9c4010665b7c8b..895cd43ed1e8150 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -300,6 +300,14 @@ Windows Support
   ``MSInheritanceAttr`` attributes to class template instantiations created
   for explicit template instantiation declarations.
 
+- The ``-fno-auto-import`` option was added for MinGW targets. The option both
+  affects code generation (inhibiting generating indirection via ``.refptr``
+  stubs for potentially auto imported symbols, generating smaller and more
+  efficient code) and linking (making the linker error out on such cases).
+  If the option only is used during code generation but not when linking,
+  linking may succeed but the resulting executables may expose issues at
+  runtime.
+
 LoongArch Support
 ^^^^^^^^^^^^^^^^^
 

diff  --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index f9e9326e5c43eb1..d7588fd430764cb 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -38,6 +38,7 @@ CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
 CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new
 CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable.
 CODEGENOPT(Autolink          , 1, 1) ///< -fno-autolink
+CODEGENOPT(AutoImport        , 1, 1) ///< -fno-auto-import
 CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
 CODEGENOPT(Backchain         , 1, 0) ///< -mbackchain
 CODEGENOPT(ControlFlowGuardNoChecks  , 1, 0) ///< -cfguard-no-checks

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3d73e24a4dc5af8..fa6b69c1c7236dd 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1469,6 +1469,17 @@ defm autolink : BoolFOption<"autolink",
           "Disable generation of linker directives for automatic library linking">,
   PosFlag<SetTrue>>;
 
+let Flags = [TargetSpecific] in {
+defm auto_import : BoolFOption<"auto-import",
+  CodeGenOpts<"AutoImport">, DefaultTrue,
+  NegFlag<SetFalse, [], [ClangOption, CC1Option],
+          "MinGW specific. Disable support for automatic dllimport in code generation "
+          "and linking">,
+  PosFlag<SetTrue, [], [], "MinGW specific. Enable code generation support for "
+          "automatic dllimport, and enable support for it in the linker. "
+          "Enabled by default.">>;
+} // let Flags = [TargetSpecific]
+
 // In the future this option will be supported by other offloading
 // languages and accept other values such as CPU/GPU architectures,
 // offload kinds and target aliases.

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 07bce12d7e6689d..3d3a5c4d2f54e31 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1419,6 +1419,7 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
     return false;
 
   const llvm::Triple &TT = CGM.getTriple();
+  const auto &CGOpts = CGM.getCodeGenOpts();
   if (TT.isWindowsGNUEnvironment()) {
     // In MinGW, variables without DLLImport can still be automatically
     // imported from a DLL by the linker; don't mark variables that
@@ -1429,7 +1430,8 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
     // such variables can't be marked as DSO local. (Native TLS variables
     // can't be dllimported at all, though.)
     if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) &&
-        (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS))
+        (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS) &&
+        CGOpts.AutoImport)
       return false;
   }
 
@@ -1452,7 +1454,6 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
     return false;
 
   // If this is not an executable, don't assume anything is local.
-  const auto &CGOpts = CGM.getCodeGenOpts();
   llvm::Reloc::Model RM = CGOpts.RelocationModel;
   const auto &LOpts = CGM.getLangOpts();
   if (RM != llvm::Reloc::Static && !LOpts.PIE) {

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 0653c4c09ebc514..da5edda6b385bc6 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5623,6 +5623,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("-mms-bitfields");
   }
 
+  if (Triple.isWindowsGNUEnvironment()) {
+    Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
+                       options::OPT_fno_auto_import);
+  }
+
   // Non-PIC code defaults to -fdirect-access-external-data while PIC code
   // defaults to -fno-direct-access-external-data. Pass the option if 
diff erent
   // from the default.

diff  --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 4674e7fa268fa9b..5af7ea985a28a18 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -169,6 +169,10 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
     CmdArgs.push_back("--no-demangle");
 
+  if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import,
+                    true))
+    CmdArgs.push_back("--disable-auto-import");
+
   if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) {
     StringRef GuardArgs = A->getValue();
     if (GuardArgs == "none")

diff  --git a/clang/test/CodeGen/dso-local-executable.c b/clang/test/CodeGen/dso-local-executable.c
index 5514f7f04ad7571..15575d3927f23d1 100644
--- a/clang/test/CodeGen/dso-local-executable.c
+++ b/clang/test/CodeGen/dso-local-executable.c
@@ -9,12 +9,14 @@
 // COFF-DAG: define dso_local ptr @zed()
 // COFF-DAG: declare dllimport void @import_func()
 
-// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS %s
-// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS %s
+// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS,MINGW-AUTO-IMPORT %s
+// 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
+// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS,MINGW-AUTO-IMPORT %s
 // MINGW:      @baz = dso_local global i32 42
 // MINGW-NEXT: @import_var = external dllimport global i32
 // MINGW-NEXT: @weak_bar = extern_weak global i32
-// MINGW-NEXT: @bar = external global i32
+// MINGW-AUTO-IMPORT-NEXT: @bar = external global i32
+// MINGW-NO-AUTO-IMPORT-NEXT: @bar = external dso_local global i32
 // MINGW-NEXT: @local_thread_var = dso_local thread_local global i32 42
 // MINGW-NATIVE_TLS-NEXT: @thread_var = external dso_local thread_local global i32
 // MINGW-EMUTLS-NEXT: @thread_var = external thread_local global i32

diff  --git a/clang/test/Driver/mingw-auto-import.c b/clang/test/Driver/mingw-auto-import.c
new file mode 100644
index 000000000000000..f52df704f206c6f
--- /dev/null
+++ b/clang/test/Driver/mingw-auto-import.c
@@ -0,0 +1,15 @@
+// By default, we don't pass any -fauto-import to -cc1, as that's the default.
+//
+// RUN: %clang --target=x86_64-w64-windows-gnu -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s
+// RUN: %clang --target=x86_64-w64-windows-gnu -fno-auto-import -fauto-import -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s
+// DEFAULT: "-cc1"
+// DEFAULT-NOT: no-auto-import
+// DEFAULT-NOT: --disable-auto-import
+
+// When compiling with -fno-auto-import, we pass -fno-auto-import to -cc1
+// and --disable-auto-import to the linker.
+//
+// RUN: %clang --target=x86_64-w64-windows-gnu -fauto-import -fno-auto-import -### %s 2>&1 | FileCheck --check-prefixes=NO_AUTOIMPORT %s
+// NO_AUTOIMPORT: "-cc1"
+// NO_AUTOIMPORT: "-fno-auto-import"
+// NO_AUTOIMPORT: "--disable-auto-import"


        


More information about the cfe-commits mailing list