Skip to content

Commit aaab403

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:6403287eff71 into amd-gfx:26000866d891
Local branch amd-gfx 2600086 Merged main:d222c5ec47a0 into amd-gfx:89049b0659eb Remote branch main 6403287 [Flang] [FlangRT] Introduce FlangRT project as solution to Flangs runtime LLVM integration
2 parents 2600086 + 6403287 commit aaab403

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1295
-246
lines changed

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -969,29 +969,41 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC,
969969
llvm::opt::ArgStringList &CmdArgs) {
970970
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
971971
CmdArgs.push_back("Fortran_main.lib");
972-
CmdArgs.push_back("FortranRuntime.lib");
973-
CmdArgs.push_back("FortranDecimal.lib");
972+
CmdArgs.push_back("flang-rt.lib");
974973
} else {
975974
CmdArgs.push_back("-lFortran_main");
976-
CmdArgs.push_back("-lFortranRuntime");
977-
CmdArgs.push_back("-lFortranDecimal");
975+
CmdArgs.push_back("-lflang-rt");
978976
}
979977
}
980978

981979
void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
982980
const llvm::opt::ArgList &Args,
983981
ArgStringList &CmdArgs) {
984-
// Default to the <driver-path>/../lib directory. This works fine on the
985-
// platforms that we have tested so far. We will probably have to re-fine
986-
// this in the future. In particular, on some platforms, we may need to use
987-
// lib64 instead of lib.
988-
SmallString<256> DefaultLibPath =
982+
// Default to the <driver-path>/../lib, <driver-path>/../flang-rt/lib, and
983+
// <driver-path>/../runtimes/runtimes-bins/flang-rt/lib directories. This
984+
// works fine on the platforms that we have tested so far. We will probably
985+
// have to re-fine this in the future. In particular, on some platforms, we
986+
// may need to use lib64 instead of lib.
987+
SmallString<256> BuildLibPath =
988+
llvm::sys::path::parent_path(TC.getDriver().Dir);
989+
SmallString<256> FlangRTLibPath =
990+
llvm::sys::path::parent_path(TC.getDriver().Dir);
991+
SmallString<256> RuntimesLibPath =
989992
llvm::sys::path::parent_path(TC.getDriver().Dir);
990-
llvm::sys::path::append(DefaultLibPath, "lib");
991-
if (TC.getTriple().isKnownWindowsMSVCEnvironment())
992-
CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
993-
else
994-
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
993+
// Search path for Fortran_main and Flang-rt libraries.
994+
llvm::sys::path::append(BuildLibPath, "lib");
995+
llvm::sys::path::append(FlangRTLibPath, "flang-rt/lib");
996+
llvm::sys::path::append(RuntimesLibPath,
997+
"runtimes/runtimes-bins/flang-rt/lib");
998+
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
999+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + BuildLibPath));
1000+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + FlangRTLibPath));
1001+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + RuntimesLibPath));
1002+
} else {
1003+
CmdArgs.push_back(Args.MakeArgString("-L" + BuildLibPath));
1004+
CmdArgs.push_back(Args.MakeArgString("-L" + FlangRTLibPath));
1005+
CmdArgs.push_back(Args.MakeArgString("-L" + RuntimesLibPath));
1006+
}
9951007
}
9961008

9971009
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,

flang-rt/CMakeLists.txt

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# CMake build for the Flang runtime libraries
2+
# The source for the flang runtime libraries (FortranDecimalRT, FortranRuntime)
3+
# exist in the flang top-level directory.
4+
# Flang-rt is only scaffolding and does not provide any additional source files.
5+
6+
cmake_minimum_required(VERSION 3.20.0)
7+
8+
#===============================================================================
9+
# Configure CMake
10+
#===============================================================================
11+
set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
12+
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
13+
NO_POLICY_SCOPE)
14+
15+
set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)
16+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
17+
18+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/flang-rt/bin)
19+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
20+
${CMAKE_BINARY_DIR}/flang-rt/lib)
21+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
22+
${CMAKE_BINARY_DIR}/flang-rt/lib)
23+
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR}/flang-rt)
24+
25+
set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
26+
set(FLANG_RT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
27+
28+
#===============================================================================
29+
# Setup Options and Defaults
30+
#===============================================================================
31+
option(FLANG_RT_ENABLE_SHARED "Build flang-rt as a shared library." OFF)
32+
option(FLANG_RT_ENABLE_STATIC "Build flang-rt as a static library." OFF)
33+
34+
option(FLANG_RT_INCLUDE_TESTS
35+
"Generate build targets for the Flang-rt unit tests." ${LLVM_INCLUDE_TESTS})
36+
37+
# MLIR_DIR must be passed on invocation of flang-rt because it is needed for the Flang package.
38+
if(NOT DEFINED MLIR_DIR OR MLIR_DIR STREQUAL "")
39+
message(FATAL_ERROR "MLIR_DIR must be set to the directory of the MLIRConfig cmake file in order to find the MLIR package.")
40+
endif()
41+
# Flang-rt requires a pre-built/installed version of flang that requires MLIR.
42+
find_package(MLIR REQUIRED HINTS "${MLIR_DIR}")
43+
44+
# FLANG_DIR must be passed on invocation of flang-rt.
45+
if(NOT DEFINED FLANG_DIR OR FLANG_DIR STREQUAL "")
46+
message(FATAL_ERROR "FLANG_DIR must be set to the directory of the FlangConfig cmake file in order to find the Flang package.")
47+
endif()
48+
# Flang-rt requires a pre-built/installed version of flang.
49+
# Flang-rt uses flang/Common headers.
50+
# Finding this package exposes FLANG_SOURCE_DIR, FLANG_BINARY_DIR, and FLANG_INCLUDE_DIRS to Flang-rt
51+
find_package(Flang REQUIRED HINTS "${FLANG_DIR}")
52+
# If the user specifies a relative path to LLVM_DIR, the calls to include
53+
# LLVM modules fail. Append the absolute path to LLVM_DIR instead.
54+
get_filename_component(FLANG_DIR_ABSOLUTE ${FLANG_DIR} REALPATH)
55+
list(APPEND CMAKE_MODULE_PATH ${FLANG_DIR_ABSOLUTE})
56+
57+
set(LLVM_COMMON_CMAKE_UTILS "${FLANG_RT_SOURCE_DIR}/../cmake")
58+
set(LLVM_CMAKE_UTILS "${LLVM_BUILD_MAIN_SOURCE_DIR}/cmake")
59+
set(CLANG_CMAKE_UTILS "${FLANG_RT_SOURCE_DIR}/../clang/cmake")
60+
61+
if (FLANG_RT_INCLUDE_TESTS)
62+
# LLVM_DIR must be passed on invocation of flang-rt when tests are enabled.
63+
if(NOT DEFINED LLVM_DIR OR LLVM_DIR STREQUAL "")
64+
message(FATAL_ERROR "LLVM_DIR must be set to the directory of the LLVMConfig cmake file in order to find the LLVM package.")
65+
endif()
66+
# We need a pre-built/installed version of LLVM for gtest.
67+
find_package(LLVM REQUIRED HINTS "${LLVM_DIR}")
68+
# If the user specifies a relative path to LLVM_DIR, the calls to include
69+
# LLVM modules fail. Append the absolute path to LLVM_DIR instead.
70+
get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH)
71+
list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR_ABSOLUTE})
72+
73+
add_compile_definitions(FLANG_RT_INCLUDE_TESTS=1)
74+
75+
if (DEFINED FLANG_BINARY_DIR)
76+
set(FLANG_BINARY_DIR ${FLANG_BINARY_DIR} CACHE PATH "Path to the Flang build directory" FORCE)
77+
else()
78+
message(FATAL_ERROR "FLANG_BINARY_DIR must be defined or passed by the user when building tests.")
79+
endif()
80+
set(FLANG_RT_TEST_COMPILER ${FLANG_BINARY_DIR}/bin/flang-new
81+
CACHE PATH "Compiler to use for testing")
82+
set(FLANG_RT_GTEST_AVAIL 1)
83+
endif()
84+
85+
# Add path for custom modules
86+
list(INSERT CMAKE_MODULE_PATH 0
87+
"${FLANG_SOURCE_DIR}/cmake"
88+
"${FLANG_SOURCE_DIR}/cmake/modules"
89+
"${CLANG_CMAKE_UTILS}/modules"
90+
"${LLVM_CMAKE_UTILS}/modules"
91+
)
92+
93+
include(AddClang)
94+
include(AddFlang)
95+
include(TestBigEndian)
96+
test_big_endian(IS_BIGENDIAN)
97+
if (IS_BIGENDIAN)
98+
add_compile_definitions(FLANG_BIG_ENDIAN=1)
99+
else ()
100+
add_compile_definitions(FLANG_LITTLE_ENDIAN=1)
101+
endif ()
102+
103+
# Flang's include directories are needed for flang/Common.
104+
include_directories(SYSTEM ${FLANG_INCLUDE_DIRS})
105+
106+
# LLVM's include directories are needed for gtest.
107+
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
108+
109+
#===============================================================================
110+
# Add Subdirectories
111+
#===============================================================================
112+
set(FORTRAN_DECIMAL_SRC "${FLANG_SOURCE_DIR}/lib/Decimal")
113+
set(FORTRAN_RUNTIME_SRC "${FLANG_SOURCE_DIR}/runtime")
114+
set(FORTRAN_MAIN_SRC "${FLANG_SOURCE_DIR}/runtime/FortranMain")
115+
116+
add_subdirectory(${FORTRAN_DECIMAL_SRC} FortranDecimalRT)
117+
add_subdirectory(${FORTRAN_RUNTIME_SRC} FortranRuntime)
118+
add_subdirectory(${FORTRAN_MAIN_SRC} FortranMain)
119+
120+
if (FLANG_RT_INCLUDE_TESTS)
121+
add_subdirectory(test)
122+
if (FLANG_RT_GTEST_AVAIL)
123+
add_subdirectory(unittests)
124+
endif()
125+
endif()
126+
127+
#===============================================================================
128+
# Create Flang-rt wrapper library
129+
#===============================================================================
130+
# Build as shared by default if no linkage type option set.
131+
if (NOT FLANG_RT_ENABLE_SHARED AND NOT FLANG_RT_ENABLE_STATIC)
132+
add_library(flang-rt SHARED $<TARGET_OBJECTS:obj.FortranDecimalRT>
133+
$<TARGET_OBJECTS:obj.FortranRuntime>)
134+
endif()
135+
if (FLANG_RT_ENABLE_SHARED)
136+
add_library(flang-rt SHARED $<TARGET_OBJECTS:obj.FortranDecimalRT>
137+
$<TARGET_OBJECTS:obj.FortranRuntime>)
138+
endif()
139+
if (FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
140+
add_library(flang-rt STATIC $<TARGET_OBJECTS:obj.FortranDecimalRT>
141+
$<TARGET_OBJECTS:obj.FortranRuntime>)
142+
endif()
143+
# When building both static and shared, we need to append _static to the name
144+
# to avoid naming conflicts.
145+
if (FLANG_RT_ENABLE_STATIC AND FLANG_RT_ENABLE_SHARED)
146+
add_library(flang-rt_static STATIC $<TARGET_OBJECTS:obj.FortranDecimalRT>
147+
$<TARGET_OBJECTS:obj.FortranRuntime>)
148+
endif()

flang-rt/docs/GettingStarted.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<!--===- docs/GettingStarted.md
2+
3+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
See https://llvm.org/LICENSE.txt for license information.
5+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
-->
8+
9+
# Flang-rt Runtime Library
10+
11+
```eval_rst
12+
.. contents::
13+
:local:
14+
```
15+
## What is Flang-rt
16+
Flang-rt is the runtime library project for Flang. The Flang driver requires
17+
the Fortran_main and Flang-rt libraries at runtime in order to generate
18+
user executables. Building this Flang-rt project will build both Fortran_main
19+
and the Flang-rt library, which is comprised of the FortranRuntime and
20+
FortranDecimalRT libraries.
21+
22+
### Fortran_main
23+
Fortran_main is left out of the Flang-rt library because it is required to
24+
always be static unlike the link type of the Flang-rt library which can be
25+
configured. Fortran_main implements the main entry point into Fortran's
26+
`PROGRAM` in Flang by being the bridge between object files generated by Flang
27+
and the C runtime that takes care of program set-up at system-level. For
28+
every Fortran `PROGRAM`, Flang generates the `_QQmain` function.
29+
Fortran_main implements the C `main` function that simply calls
30+
`_QQmain`.
31+
32+
### FortranDecimalRT
33+
In order to decouple the common dependency between compiler and runtime,
34+
[FortranDecimal's sources](../../flang/lib/Decimal/CMakeLists.txt) are built
35+
separately for the compiler and the runtime. When the library is built for
36+
Flang-rt, the name FortranDecimalRT is used to avoid naming conflicts and
37+
confusion.
38+
39+
### FortranRuntime
40+
This is the core runtime library in Flang-rt. The sources for this library
41+
currently still exist in the
42+
[Flang source directory](../../flang/runtime/CMakeLists.txt). We hope to
43+
migrate the sources to the Flang-rt directory in the future in order to further
44+
decouple the runtime from the Flang compiler.
45+
46+
## Building Flang-rt
47+
Like other LLVM runtimes, Flang-rt can be built by targetting the
48+
[runtimes LLVM target](../../runtimes/CMakelists.txt). It can also be built
49+
when targetting the [llvm target](../../llvm/CMakeLists.txt) as an enabled
50+
runtime. Flang-rt will implicitly be added as an enabled runtime when Flang
51+
is an enabled project built by llvm. Flang-rt does not support standalone
52+
builds.
53+
54+
In the future, we may be interested in supporting in optionally building
55+
Flang-rt when doing a Flang standalone build.
56+
57+
### Building with the llvm target
58+
Assuming you are building Flang-rt to use with Flang, see
59+
[Flang's Getting Started guide](../../flang/docs/GettingStarted.md) for more
60+
information. To build Flang-rt when building the Flang compiler, once you have
61+
the llvm-project source ready, make a clean build directory. Let root be the
62+
root directory that you cloned llvm-project into.
63+
```bash
64+
cd root
65+
rm -rf build
66+
mkdir build
67+
cd build
68+
```
69+
Now invoke the cmake configuration command for llvm that would build Flang with
70+
Flang-rt.
71+
```bash
72+
cmake \
73+
-G Ninja \
74+
-DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt" \
75+
-DCMAKE_CXX_STANDARD=17 \
76+
-DLLVM_INSTALL_UTILS=On \
77+
# New Flang-rt flags for enabled link types
78+
-DFLANG_RT_ENABLE_STATIC=On \
79+
-DFLANG_RT_ENABLE_SHARED=On \
80+
# We need to enable GTest if we want to run Flang-rt's testsuites
81+
-DLLVM_INSTALL_GTEST=On \
82+
-DFLANG_ENABLE_WERROR=On \
83+
-DLLVM_LIT_ARGS=-v \
84+
-DCMAKE_BUILD_TYPE=Release \
85+
-DLLVM_ENABLE_PROJECTS="clang;flang;lld;mlir;openmp" \
86+
../llvm-project/llvm
87+
```
88+
Flang requires other llvm projects (see LLVM_ENABLE_PROJECTS and the [Flang
89+
Getting Started Guide](../../flang/docs/GettingStarted.md) for more specifics
90+
on building Flang.
91+
92+
By targetting the LLVM project, we are letting LLVM infrastructure handle
93+
invoking the runtimes target that will build Flang-rt. This includes finding
94+
the cmake packages for Clang, LLVM, Flang and MLIR that Flang-rt depends on.
95+
96+
### Building with the runtimes target
97+
If you already have a pre-built/installed version of LLVM, Flang, Clang and
98+
MLIR, and would like to build Flang-rt without rebuilding the sources for these
99+
other projects. You can simply target the runtimes project directly and passing
100+
the paths to the directories of these files. If you built LLVM as we did above
101+
with default build directories, your runtimes invocation should look something
102+
like:
103+
```bash
104+
cd build
105+
BUILDDIR=`pwd`
106+
107+
cmake \
108+
-G Ninja \
109+
-DCMAKE_CXX_STANDARD=17 \
110+
# New Flang-rt flags for enabled link types
111+
-DFLANG_RT_ENABLE_SHARED=On \
112+
-DFLANG_RT_ENABLE_STATIC=On \
113+
-DLLVM_LIT_ARGS=-v \
114+
-DCMAKE_BUILD_TYPE=Release \
115+
-DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$LD_LIBRARY_PATH" \
116+
-DLLVM_TARGETS_TO_BUILD=host \
117+
-DLLVM_EXTERNAL_LIT=$BUILD_DIR/bin/llvm-lit \
118+
# We need to specify the paths to the cmake packages of the dependencies
119+
-DLLVM_DIR=$BUILD_DIR/lib/cmake/llvm \
120+
-DMLIR_DIR=$BUILD_DIR/lib/cmake/mlir \
121+
-DFLANG_DIR=$BUILD_DIR/lib/cmake/flang \
122+
-DLLVM_ENABLE_RUNTIMES="flang-rt" \
123+
../llvm-project/runtimes/
124+
```
125+
126+
## Library locations
127+
When building the llvm target with flang as an enabled project, the Flang-rt
128+
library will be built to `$BUILDDIR/runtimes/runtimes-bins/flang-rt/lib`. When
129+
building the runtimes target with flang-rt as an enabled runtime, the libraries
130+
will be built to `$BUILDDIR/flang-rt/lib` by default. In either configuration,
131+
the Fortran_main library will be built to `$BUILDDIR/lib` by default.
132+
133+
## Using Flang-rt
134+
The two build paths mentioned above get implicitly added as library paths at the
135+
invocation of the driver. If Flang-rt is a shared library, you must make the
136+
dynamic linker aware of where to look. One method to do so is to set the
137+
environment variable `LD_LIBRARY_PATH` include the path to Flang-rt's directory.
138+
139+
## Options
140+
Flang-rt introduces 2 CMake options used to configure the library's link type:
141+
```
142+
option(FLANG_RT_ENABLE_SHARED "Build flang-rt as a shared library." OFF)
143+
option(FLANG_RT_ENABLE_STATIC "Build flang-rt as a static library." OFF)
144+
```
145+
Both can be specified if you want to build both shared and static versions of
146+
the Flang-rt runtime. If both are specified, the static library will be named
147+
Flang-rt_static.a to avoid naming conflicts, as per the LLVM standard.
148+
149+
## Usage Examples
150+
```bash
151+
# Example of using Flang with the shared Flang-rt runtime
152+
# First we need to explicitly tell the dynamic linker where to find Flang-rt
153+
# since it was built as shared.
154+
$ $ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$BUILDDIR/runtimes/runtimes-bins/flang-rt/lib"
155+
$ flang-new -ffree-form hello.f95 -o hello
156+
```

0 commit comments

Comments
 (0)