-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[flang][nfc] Refactor linker invocation logic #75534
Conversation
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-flang-driver Author: Andrzej Warzyński (banach-space) ChangesRefactor how the Fortran runtime libs are added to the linker Full diff: https://github.com/llvm/llvm-project/pull/75534.diff 2 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 3d1df58190ce05..35f3db31db9b8f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1116,73 +1116,87 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
return true;
}
+/// Determines if --whole-archive is active in the list of arguments.
+static bool isWholeArchivePresent(const ArgList &Args) {
+ bool WholeArchiveActive = false;
+ for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
+ if (Arg) {
+ for (StringRef ArgValue : Arg->getValues()) {
+ if (ArgValue == "--whole-archive")
+ WholeArchiveActive = true;
+ if (ArgValue == "--no-whole-archive")
+ WholeArchiveActive = false;
+ }
+ }
+ }
+
+ return WholeArchiveActive;
+}
+
+/// Add Fortran runtime libs for MSVC
+static void addFortranRuntimeLibsMSVC(const ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+ if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+ RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+ }
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MT:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
+ break;
+ case options::OPT__SLASH_MD:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
+ break;
+ }
+}
+
+/// Add Fortran runtime libs
void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) {
- // These are handled earlier on Windows by telling the frontend driver to add
- // the correct libraries to link against as dependents in the object file.
-
- // if -fno-fortran-main has been passed, skip linking Fortran_main.a
- bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
+ // 1. Link FortranRuntime and FortranDecimal
+ // These are handled earlier on Windows by telling the frontend driver to
+ // add the correct libraries to link against as dependents in the object
+ // file.
if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
- if (LinkFortranMain) {
- // The --whole-archive option needs to be part of the link line to
- // make sure that the main() function from Fortran_main.a is pulled
- // in by the linker. Determine if --whole-archive is active when
- // flang will try to link Fortran_main.a. If it is, don't add the
- // --whole-archive flag to the link line. If it's not, add a proper
- // --whole-archive/--no-whole-archive bracket to the link line.
- bool WholeArchiveActive = false;
- for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
- if (Arg) {
- for (StringRef ArgValue : Arg->getValues()) {
- if (ArgValue == "--whole-archive")
- WholeArchiveActive = true;
- if (ArgValue == "--no-whole-archive")
- WholeArchiveActive = false;
- }
- }
- }
+ CmdArgs.push_back("-lFortranRuntime");
+ CmdArgs.push_back("-lFortranDecimal");
+ }
- // TODO: Find an equivalent of `--whole-archive` for Darwin.
- if (!WholeArchiveActive && !TC.getTriple().isMacOSX()) {
- CmdArgs.push_back("--whole-archive");
- CmdArgs.push_back("-lFortran_main");
- CmdArgs.push_back("--no-whole-archive");
- } else {
- CmdArgs.push_back("-lFortran_main");
- }
+ // 2. Link FortranMain
+ // If -fno-fortran-main has been passed, skip linking Fortran_main.a
+ if (Args.hasArg(options::OPT_no_fortran_main))
+ return;
- // Perform regular linkage of the remaining runtime libraries.
- CmdArgs.push_back("-lFortranRuntime");
- CmdArgs.push_back("-lFortranDecimal");
- }
- } else {
- if (LinkFortranMain) {
- unsigned RTOptionID = options::OPT__SLASH_MT;
- if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
- RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
- .Case("static", options::OPT__SLASH_MT)
- .Case("static_dbg", options::OPT__SLASH_MTd)
- .Case("dll", options::OPT__SLASH_MD)
- .Case("dll_dbg", options::OPT__SLASH_MDd)
- .Default(options::OPT__SLASH_MT);
- }
- switch (RTOptionID) {
- case options::OPT__SLASH_MT:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
- break;
- case options::OPT__SLASH_MTd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
- break;
- case options::OPT__SLASH_MD:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
- break;
- case options::OPT__SLASH_MDd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
- break;
- }
- }
+ // 2.1. MSVC
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ addFortranRuntimeLibsMSVC(Args, CmdArgs);
+ return;
}
+
+ // 2.2. GNU and similar
+ // The --whole-archive option needs to be part of the link line to make
+ // sure that the main() function from Fortran_main.a is pulled in by the
+ // linker. However, it shouldn't be used if it's already active.
+ // TODO: Find an equivalent of `--whole-archive` for Darwin.
+ if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX()) {
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back("-lFortran_main");
+ CmdArgs.push_back("--no-whole-archive");
+ return;
+ }
+
+ CmdArgs.push_back("-lFortran_main");
}
void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index ea91946316cfaa..31e7ab71aacdb1 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -28,23 +28,23 @@
! executable and may find the GNU linker from MinGW or Cygwin.
! UNIX-LABEL: "{{.*}}ld{{(\.exe)?}}"
! UNIX-SAME: "[[object_file]]"
-! UNIX-SAME: "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lFortranRuntime" "-lFortranDecimal" "-lm"
+! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal" "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lm"
! DARWIN-LABEL: "{{.*}}ld{{(\.exe)?}}"
! DARWIN-SAME: "[[object_file]]"
-! DARWIN-SAME: -lFortran_main
! DARWIN-SAME: -lFortranRuntime
! DARWIN-SAME: -lFortranDecimal
+! DARWIN-SAME: -lFortran_main
! HAIKU-LABEL: "{{.*}}ld{{(\.exe)?}}"
! HAIKU-SAME: "[[object_file]]"
-! HAIKU-SAME: "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lFortranRuntime" "-lFortranDecimal"
+! HAIKU-SAME: "-lFortranRuntime" "-lFortranDecimal" "--whole-archive" "-lFortran_main" "--no-whole-archive"
! MINGW-LABEL: "{{.*}}ld{{(\.exe)?}}"
! MINGW-SAME: "[[object_file]]"
-! MINGW-SAME: -lFortran_main
! MINGW-SAME: -lFortranRuntime
! MINGW-SAME: -lFortranDecimal
+! MINGW-SAME: -lFortran_main
! NOTE: This also matches lld-link (when CLANG_DEFAULT_LINKER=lld) and
! any .exe suffix that is added when resolving to the full path of
|
@llvm/pr-subscribers-clang Author: Andrzej Warzyński (banach-space) ChangesRefactor how the Fortran runtime libs are added to the linker Full diff: https://github.com/llvm/llvm-project/pull/75534.diff 2 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 3d1df58190ce05..35f3db31db9b8f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1116,73 +1116,87 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
return true;
}
+/// Determines if --whole-archive is active in the list of arguments.
+static bool isWholeArchivePresent(const ArgList &Args) {
+ bool WholeArchiveActive = false;
+ for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
+ if (Arg) {
+ for (StringRef ArgValue : Arg->getValues()) {
+ if (ArgValue == "--whole-archive")
+ WholeArchiveActive = true;
+ if (ArgValue == "--no-whole-archive")
+ WholeArchiveActive = false;
+ }
+ }
+ }
+
+ return WholeArchiveActive;
+}
+
+/// Add Fortran runtime libs for MSVC
+static void addFortranRuntimeLibsMSVC(const ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+ if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+ RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+ }
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MT:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
+ break;
+ case options::OPT__SLASH_MD:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
+ break;
+ }
+}
+
+/// Add Fortran runtime libs
void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) {
- // These are handled earlier on Windows by telling the frontend driver to add
- // the correct libraries to link against as dependents in the object file.
-
- // if -fno-fortran-main has been passed, skip linking Fortran_main.a
- bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
+ // 1. Link FortranRuntime and FortranDecimal
+ // These are handled earlier on Windows by telling the frontend driver to
+ // add the correct libraries to link against as dependents in the object
+ // file.
if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
- if (LinkFortranMain) {
- // The --whole-archive option needs to be part of the link line to
- // make sure that the main() function from Fortran_main.a is pulled
- // in by the linker. Determine if --whole-archive is active when
- // flang will try to link Fortran_main.a. If it is, don't add the
- // --whole-archive flag to the link line. If it's not, add a proper
- // --whole-archive/--no-whole-archive bracket to the link line.
- bool WholeArchiveActive = false;
- for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
- if (Arg) {
- for (StringRef ArgValue : Arg->getValues()) {
- if (ArgValue == "--whole-archive")
- WholeArchiveActive = true;
- if (ArgValue == "--no-whole-archive")
- WholeArchiveActive = false;
- }
- }
- }
+ CmdArgs.push_back("-lFortranRuntime");
+ CmdArgs.push_back("-lFortranDecimal");
+ }
- // TODO: Find an equivalent of `--whole-archive` for Darwin.
- if (!WholeArchiveActive && !TC.getTriple().isMacOSX()) {
- CmdArgs.push_back("--whole-archive");
- CmdArgs.push_back("-lFortran_main");
- CmdArgs.push_back("--no-whole-archive");
- } else {
- CmdArgs.push_back("-lFortran_main");
- }
+ // 2. Link FortranMain
+ // If -fno-fortran-main has been passed, skip linking Fortran_main.a
+ if (Args.hasArg(options::OPT_no_fortran_main))
+ return;
- // Perform regular linkage of the remaining runtime libraries.
- CmdArgs.push_back("-lFortranRuntime");
- CmdArgs.push_back("-lFortranDecimal");
- }
- } else {
- if (LinkFortranMain) {
- unsigned RTOptionID = options::OPT__SLASH_MT;
- if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
- RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
- .Case("static", options::OPT__SLASH_MT)
- .Case("static_dbg", options::OPT__SLASH_MTd)
- .Case("dll", options::OPT__SLASH_MD)
- .Case("dll_dbg", options::OPT__SLASH_MDd)
- .Default(options::OPT__SLASH_MT);
- }
- switch (RTOptionID) {
- case options::OPT__SLASH_MT:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
- break;
- case options::OPT__SLASH_MTd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
- break;
- case options::OPT__SLASH_MD:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
- break;
- case options::OPT__SLASH_MDd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
- break;
- }
- }
+ // 2.1. MSVC
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ addFortranRuntimeLibsMSVC(Args, CmdArgs);
+ return;
}
+
+ // 2.2. GNU and similar
+ // The --whole-archive option needs to be part of the link line to make
+ // sure that the main() function from Fortran_main.a is pulled in by the
+ // linker. However, it shouldn't be used if it's already active.
+ // TODO: Find an equivalent of `--whole-archive` for Darwin.
+ if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX()) {
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back("-lFortran_main");
+ CmdArgs.push_back("--no-whole-archive");
+ return;
+ }
+
+ CmdArgs.push_back("-lFortran_main");
}
void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index ea91946316cfaa..31e7ab71aacdb1 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -28,23 +28,23 @@
! executable and may find the GNU linker from MinGW or Cygwin.
! UNIX-LABEL: "{{.*}}ld{{(\.exe)?}}"
! UNIX-SAME: "[[object_file]]"
-! UNIX-SAME: "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lFortranRuntime" "-lFortranDecimal" "-lm"
+! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal" "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lm"
! DARWIN-LABEL: "{{.*}}ld{{(\.exe)?}}"
! DARWIN-SAME: "[[object_file]]"
-! DARWIN-SAME: -lFortran_main
! DARWIN-SAME: -lFortranRuntime
! DARWIN-SAME: -lFortranDecimal
+! DARWIN-SAME: -lFortran_main
! HAIKU-LABEL: "{{.*}}ld{{(\.exe)?}}"
! HAIKU-SAME: "[[object_file]]"
-! HAIKU-SAME: "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lFortranRuntime" "-lFortranDecimal"
+! HAIKU-SAME: "-lFortranRuntime" "-lFortranDecimal" "--whole-archive" "-lFortran_main" "--no-whole-archive"
! MINGW-LABEL: "{{.*}}ld{{(\.exe)?}}"
! MINGW-SAME: "[[object_file]]"
-! MINGW-SAME: -lFortran_main
! MINGW-SAME: -lFortranRuntime
! MINGW-SAME: -lFortranDecimal
+! MINGW-SAME: -lFortran_main
! NOTE: This also matches lld-link (when CLANG_DEFAULT_LINKER=lld) and
! any .exe suffix that is added when resolving to the full path of
|
|
Refactor how the Fortran runtime libs are added to the linker invocation. This is a non-functional change.
966e22e
to
b0b3bc4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks for the refactoring. This makes the code much easier to digest!
This reverts commit 71bbfab. Breaks check-flang on x86_64 host.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this change, I can no longer use flang-new to create an executable program. When I try, I get the following output:
[psteinfeld@ice4 build]$ flang-new hello.f90
/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/../../../../bin/ld: /local/home/psteinfeld/up/build/lib/libFortran_main.a(Fortran_main.c.o): in function `main':
Fortran_main.c:(.text.startup.main+0xf): undefined reference to `_FortranAProgramStart'
/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/../../../../bin/ld: Fortran_main.c:(.text.startup.main+0x19): undefined reference to `_FortranAProgramEndStatement'
flang-new: error: linker command failed with exit code 1 (use -v to see invocation)
Sorry about that Pete :( This has already been reverted, so things should work just fine if you pull and rebuild. Not sure why pre-commit CI didn't catch that. |
Refactor how the Fortran runtime libs are added to the linker invocation. This is a non-functional change. This is an updated version of llvm#75534. This iteration makes sure that FortranMain.a comes before FortranRuntme.a (the former depends on the latter).
Updated version: #75648 |
Refactor how the Fortran runtime libs are added to the linker invocation. This is a non-functional change. This is an updated version of #75534. This iteration makes sure that FortranMain.a comes before FortranRuntme.a (the former depends on the latter).
Refactor how the Fortran runtime libs are added to the linker
invocation. This is a non-functional change.