ekieri created this revision. ekieri added reviewers: awarzynski, peixin, sscalpone. Herald added projects: Flang, All. ekieri requested review of this revision. Herald added subscribers: cfe-commits, jdoerfert, MaskRay. Herald added a project: clang.
Add --undefined=_QQmain to the link line, so that a Fortran main program will be included in the link job even if it is in an archive (unless we are building a shared object). For now, this is only applied to the Gnu toolchain. We also add a section on the linker invocation to docs/FlangDriver.md. The new tests require llvm-ar to construct an archive we can include in the link job. This is a new dependency for flang/test (which already depends on similar tools such as llvm-objdump). See discussions in https://github.com/llvm/llvm-project/issues/54787 which this patch fixes. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D134821 Files: clang/lib/Driver/ToolChains/Gnu.cpp flang/docs/FlangDriver.md flang/test/CMakeLists.txt flang/test/Driver/link-c-main.c flang/test/Driver/link-f90-main.f90 flang/test/Driver/linker-flags.f90
Index: flang/test/Driver/linker-flags.f90 =================================================================== --- flang/test/Driver/linker-flags.f90 +++ flang/test/Driver/linker-flags.f90 @@ -12,6 +12,9 @@ ! Make sure they're not added. ! RUN: %flang -### -flang-experimental-exec -target aarch64-windows-msvc %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames +! Check linker invocation to generate shared object (only GNU toolchain for now) +! RUN: %flang -### -flang-experimental-exec -shared -target x86_64-linux-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,GNUSO --implicit-check-not _QQmain + ! Compiler invocation to generate the object file ! CHECK-LABEL: {{.*}} "-emit-obj" ! CHECK-SAME: "-o" "[[object_file:.*\.o]]" {{.*}}Inputs/hello.f90 @@ -19,6 +22,7 @@ ! Linker invocation to generate the executable ! GNU-LABEL: "{{.*}}ld" ! GNU-SAME: "[[object_file]]" +! GNU-SAME: --undefined=_QQmain ! GNU-SAME: -lFortran_main ! GNU-SAME: -lFortranRuntime ! GNU-SAME: -lFortranDecimal @@ -46,3 +50,9 @@ ! MSVC-SAME: FortranDecimal.lib ! MSVC-SAME: /subsystem:console ! MSVC-SAME: "[[object_file]]" + +! Linker invocation to generate a shared object +! GNUSO-LABEL: "{{.*}}ld" +! GNUSO-SAME: "[[object_file]]" +! GNUSO-SAME: -lFortranRuntime +! GNUSO-SAME: -lFortranDecimal Index: flang/test/Driver/link-f90-main.f90 =================================================================== --- /dev/null +++ flang/test/Driver/link-f90-main.f90 @@ -0,0 +1,22 @@ +! Test that a fortran main program can be linked to an executable +! by flang. +! +! For now, this test only covers the Gnu toolchain on linux. + +! REQUIRES: x86-registered-target, system-linux + +! RUN: %flang_fc1 -emit-obj %s -o %t.o +! RUN: %flang -target x86_64-unknown-linux-gnu %t.o -o %t.out -flang-experimental-exec +! RUN: llvm-objdump --syms %t.out | FileCheck %s + +! Test that it also works if the program is bundled in an archive. + +! RUN: llvm-ar -r %t.a %t.o +! RUN: %flang -target x86_64-unknown-linux-gnu %t.a -o %ta.out -flang-experimental-exec +! RUN: llvm-objdump --syms %ta.out | FileCheck %s + +end program + +! CHECK-DAG: F .text {{[a-f0-9]+}} main +! CHECK-DAG: F .text {{[a-f0-9]+}} _QQmain +! CHECK-DAG: *UND* {{[a-f0-9]+}} _FortranAProgramStart Index: flang/test/Driver/link-c-main.c =================================================================== --- /dev/null +++ flang/test/Driver/link-c-main.c @@ -0,0 +1,27 @@ +/* +Test that an object file with a c main function can be linked to an executable +by flang. + +For now, this test only covers the Gnu toolchain on linux. + +REQUIRES: x86-registered-target, system-linux, c-compiler + +RUN: %cc -c %s -o %t.o +RUN: %flang -target x86_64-unknown-linux-gnu %t.o -o %t.out -flang-experimental-exec +RUN: llvm-objdump --syms %t.out | FileCheck %s --implicit-check-not Fortran + +Test that it also works if the c-main is bundled in an archive. + +RUN: llvm-ar -r %t.a %t.o +RUN: %flang -target x86_64-unknown-linux-gnu %t.a -o %ta.out -flang-experimental-exec +RUN: llvm-objdump --syms %ta.out | FileCheck %s --implicit-check-not Fortran +*/ + +int main(void) { + return 0; +} + +/* +CHECK-DAG: F .text {{[a-f0-9]+}} main +CHECK-DAG: *UND* {{[a-f0-9]+}} _QQmain +*/ Index: flang/test/CMakeLists.txt =================================================================== --- flang/test/CMakeLists.txt +++ flang/test/CMakeLists.txt @@ -55,6 +55,7 @@ fir-opt tco bbc + llvm-ar llvm-dis llvm-objdump split-file Index: flang/docs/FlangDriver.md =================================================================== --- flang/docs/FlangDriver.md +++ flang/docs/FlangDriver.md @@ -149,13 +149,6 @@ +- 3: backend, {2}, assembler 4: assembler, {3}, object ``` -Note that currently Flang does not support code-generation and `flang-new` will -fail during the second step above with the following error: -```bash -error: code-generation is not available yet -``` -The other phases are printed nonetheless when using `-ccc-print-phases`, as -that reflects what `clangDriver`, the library, will try to create and run. For actions specific to the frontend (e.g. preprocessing or code generation), a command to call the frontend driver is generated (more specifically, an @@ -205,6 +198,40 @@ words, `flang-new -fc1 <input-file>` is equivalent to `flang-new -fc1 -fsyntax-only <input-file>`. +## Linker invocation +Note: Linker invocation through the flang-new driver is so far +experimental. This section describes the currently intended design, and not +necessarily what is implemented. + +Calling +```bash +flang-new prog.f90 +``` +will, on a high level, do two things: +* call the frontend driver to build the object file prog.o, and +* call the system linker to build the executable a.out. + +In both invocations, flang-new will add default options. To see the exact +invocations on your system, you can call +```bash +flang-new -### prog.f90 +``` +The link line will contain a fair number of options, which will depend on your +system. Compared to when linking a c program with clang, the main additions are +(on GNU/linux), +* `--undefined=_QQmain`: A fortran main program will appear in the corresponding + object file as a function called `_QQmain`. This flag lets an object file + containing a fortran main program (i.e., a symbol `_QQmain`) be included in + the linking also when it is bundled in an archive. +* `-lFortran_main`: The Fortran_main archive is part of flang's runtime. It + exports the symbol `main`, i.e., a c main function, which will make some + initial configuration before calling `_QQmain`, and clean up before returning. +* `-lFortranRuntime`: Flang's fortran runtime, containing, for example, + implementations of intrinsic functions. +* `-lFortranDecimal`: Part of flang's runtime, containing routines for parsing + and formatting decimal numbers. +* `-lm`: Link with the math library, on which flang's runtime depends. + ## The `flang-to-external-fc` script The `flang-to-external-fc` wrapper script for `flang-new` was introduced as a development tool and to facilitate testing. The `flang-to-external-fc` wrapper Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -601,6 +601,12 @@ // these dependencies need to be listed before the C runtime below (i.e. // AddRuntTimeLibs). if (D.IsFlangMode()) { + // A Fortran main program will be lowered to a function named _QQmain. Make + // _QQmain an undefined symbol, so that we include it even if it hides + // inside an archive. + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--undefined=_QQmain"); + addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); addFortranRuntimeLibs(ToolChain, CmdArgs); CmdArgs.push_back("-lm");
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits