Skip to content

Commit

Permalink
[flang][nfc] Refactor linker invocation logic (#75534)
Browse files Browse the repository at this point in the history
Refactor how the Fortran runtime libs are added to the linker
invocation. This is a non-functional change.
  • Loading branch information
banach-space committed Dec 15, 2023
1 parent aeb4821 commit 71bbfab
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 65 deletions.
136 changes: 75 additions & 61 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions flang/test/Driver/linker-flags.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 71bbfab

Please sign in to comment.