https://github.com/mjklemm updated https://github.com/llvm/llvm-project/pull/75816
>From 511f3a4537267284554bf6b33470a01d747b8a94 Mon Sep 17 00:00:00 2001 From: Michael Klemm <michael.kl...@amd.com> Date: Sat, 16 Dec 2023 20:15:17 +0100 Subject: [PATCH 1/4] Remove -lFortran_main from the link line when -shared is present --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 45901ee7157f77..5d525d3794ad1d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1133,6 +1133,17 @@ static bool isWholeArchivePresent(const ArgList &Args) { return WholeArchiveActive; } +static bool isSharedLinkage(const ArgList &Args) { + bool FoundSharedFlag = false; + for (auto *Arg : Args.filtered(options::OPT_shared)) { + if (Arg) { + FoundSharedFlag = true; + } + } + + return FoundSharedFlag; +} + /// Add Fortran runtime libs for MSVC static void addFortranRuntimeLibsMSVC(const ArgList &Args, llvm::opt::ArgStringList &CmdArgs) { @@ -1164,6 +1175,17 @@ static void addFortranRuntimeLibsMSVC(const ArgList &Args, // Add FortranMain runtime lib static void addFortranMain(const ToolChain &TC, const ArgList &Args, llvm::opt::ArgStringList &CmdArgs) { + // 0. Shared-library linkage + // If we are attempting to link a shared library, we should not add + // -lFortran_main.a to the link line, as the `main` symbol is not + // required for a shared library and should also be provided by one + // of the translation units of the code that this shared library + // will be linked against eventually. + if (isSharedLinkage(Args)) { + printf("MK: --> shared linkage, do not add -lFortranMain\n"); + return; + } + // 1. MSVC if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { addFortranRuntimeLibsMSVC(Args, CmdArgs); >From 930f2c447daa625d9e6019cd38d82b5750942f5d Mon Sep 17 00:00:00 2001 From: Michael Klemm <michael.kl...@amd.com> Date: Mon, 18 Dec 2023 11:27:59 +0100 Subject: [PATCH 2/4] Update dynamic_linker.f90 test and clean up a bit --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 22 ++++++++++------------ flang/test/Driver/dynamic-linker.f90 | 8 ++++++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 5d525d3794ad1d..05ebd42829c95d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1133,15 +1133,14 @@ static bool isWholeArchivePresent(const ArgList &Args) { return WholeArchiveActive; } +/// Determine if driver is invoked to create a shared object library (-static) static bool isSharedLinkage(const ArgList &Args) { - bool FoundSharedFlag = false; - for (auto *Arg : Args.filtered(options::OPT_shared)) { - if (Arg) { - FoundSharedFlag = true; - } - } + return Args.hasArg(options::OPT_shared); +} - return FoundSharedFlag; +/// Determine if driver is invoked to create a static object library (-shared) +static bool isStaticLinkage(const ArgList &Args) { + return Args.hasArg(options::OPT_static); } /// Add Fortran runtime libs for MSVC @@ -1176,13 +1175,12 @@ static void addFortranRuntimeLibsMSVC(const ArgList &Args, static void addFortranMain(const ToolChain &TC, const ArgList &Args, llvm::opt::ArgStringList &CmdArgs) { // 0. Shared-library linkage - // If we are attempting to link a shared library, we should not add + // If we are attempting to link a library, we should not add // -lFortran_main.a to the link line, as the `main` symbol is not - // required for a shared library and should also be provided by one - // of the translation units of the code that this shared library + // required for a library and should also be provided by one of + // the translation units of the code that this shared library // will be linked against eventually. - if (isSharedLinkage(Args)) { - printf("MK: --> shared linkage, do not add -lFortranMain\n"); + if (isSharedLinkage(Args) || isStaticLinkage(Args)) { return; } diff --git a/flang/test/Driver/dynamic-linker.f90 b/flang/test/Driver/dynamic-linker.f90 index df119c22a2ea51..af07e2483f93fa 100644 --- a/flang/test/Driver/dynamic-linker.f90 +++ b/flang/test/Driver/dynamic-linker.f90 @@ -3,18 +3,22 @@ ! RUN: %flang -### --target=x86_64-linux-gnu -rpath /path/to/dir -shared \ ! RUN: -static %s 2>&1 | FileCheck \ -! RUN: --check-prefixes=GNU-LINKER-OPTIONS %s +! RUN: --check-prefixes=GNU-LINKER-OPTIONS \ +! RUN: --implicit-check-not=GNU-LINKER-OPTIONS-NOT %s ! RUN: %flang -### --target=x86_64-windows-msvc -rpath /path/to/dir -shared \ ! RUN: -static %s 2>&1 | FileCheck \ -! RUN: --check-prefixes=MSVC-LINKER-OPTIONS %s +! RUN: --check-prefixes=MSVC-LINKER-OPTIONS \ +! RUN: --implicit-check-not=MSVC-LINKER-OPTIONS-NOT %s ! TODO: Could the linker have an extension or a suffix? ! GNU-LINKER-OPTIONS: "{{.*}}ld{{(.exe)?}}" ! GNU-LINKER-OPTIONS-SAME: "-shared" ! GNU-LINKER-OPTIONS-SAME: "-static" ! GNU-LINKER-OPTIONS-SAME: "-rpath" "/path/to/dir" +! GNU-LINKER-OPTIONS-NOT: "-lFortran_main.a" ! For MSVC, adding -static does not add any additional linker options. ! MSVC-LINKER-OPTIONS: "{{.*}}link{{(.exe)?}}" ! MSVC-LINKER-OPTIONS-SAME: "-dll" ! MSVC-LINKER-OPTIONS-SAME: "-rpath" "/path/to/dir" +! MSVC-LINKER-OPTIONS-NOT: "/WHOLEARCHIVE:Fortran_main" >From c60a3a7dbd038d9e1cac63cda00674462828c5c6 Mon Sep 17 00:00:00 2001 From: Michael Klemm <michael.kl...@amd.com> Date: Tue, 19 Dec 2023 15:07:14 +0100 Subject: [PATCH 3/4] Write up for Flang creates the link line and the thoughts behind that --- flang/docs/FlangDriver.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index 5231e78335f6ad..bdb3c46455601c 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -163,6 +163,40 @@ forward compiler options to the frontend driver, `flang-new -fc1`. You can read more on the design of `clangDriver` in Clang's [Driver Design & Internals](https://clang.llvm.org/docs/DriverInternals.html). +## Linker Driver +When used as a linker, Flang's frontend driver assembles the command line for an +external linker command (e.g., LLVM's `lld`) and invokes it to create the final +executable by linking static and shared libraries together with all the +translation units supplied as object files. + +By default, the Flang linker driver adds several libraries to the linker +invocation to make sure that all entrypoints for program start +(Fortran's program unit) and runtime routines can be resolved by the linker. +The libraries are: + +* `Fortran_main`: Provides the main entry point `main` that then invokes + `_QQmain` with the Fortran program unit. This library has a dependency to + the `FortranRuntime` library. +* `FortranRuntime`: Provides most of the Flang runtime library. +* `FortranDecimal`: Provides operations for decimal numbers. + +The default is that, when using Flang as the linker, one of the Fortran +translation units provides the program unit and therefore it is assumed that +Fortran is the main code part (calling into C/C++ routines via `BIND +(C)` interfaces). When composing the linker commandline, Flang uses +`--whole-archive` and `--no-whole-archive` (Windows: `/WHOLEARCHIVE:`, +Darwin: *not implemented yet*) to make sure that all for `Fortran_main` is +processed by the linker. This is done to issue a proper error message when +multiple definitions of `main` occur. This happens, for instance, when linking +a code that has a Fortran program unit with a C/C++ code that also defines a +`main` function. + +If the code is C/C++ based and invokes Fortran routines, either use Clang as the +linker driver (supplying `FortranRuntime` and/or `FortranDecimal` to the linker +driver) or use Flang with the `-fno-fortran-main` flag. This flag removes +`Fortran_main` from the linker stage and hence requires one of the C/C++ +translation units to provide a definition of the `main` function. + ## Frontend Driver Flang's frontend driver is the main interface between compiler developers and the Flang frontend. The high-level design is similar to Clang's frontend >From 266687414fd78d8a474d7851cae1009185b68881 Mon Sep 17 00:00:00 2001 From: Michael Klemm <michael.kl...@amd.com> Date: Tue, 19 Dec 2023 15:16:54 +0100 Subject: [PATCH 4/4] Make small addition about static and shared libraries --- flang/docs/FlangDriver.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index bdb3c46455601c..0f9a571f8e0d61 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -197,6 +197,12 @@ driver) or use Flang with the `-fno-fortran-main` flag. This flag removes `Fortran_main` from the linker stage and hence requires one of the C/C++ translation units to provide a definition of the `main` function. +When creating shared or static libraries, `Fortran_main` is automatically +removed from the linker stage. It is assumed that when creating a static or +shared library, the generated library does not need a `main` function, as a +final link stage will occur that will provide the `Fortran_main` library when +creating the final executable. + ## Frontend Driver Flang's frontend driver is the main interface between compiler developers and the Flang frontend. The high-level design is similar to Clang's frontend _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits