Currently, the system module files needed when compiling a Fortran source in /flang/module are built when compiling flang itself. The instructions for this are in /flang/tools/f18[1]. This has some issues:
-
Some of the .f90 files are target-dependent. While AFAIU .mod files are in principle target-triple-independent, some contain #ifdefs for specific targets. This includes:
iso_c_binding.f90(C ABI is obviously target-dependent),__fortran_ieee_exceptions.f90, andieee_arithmetic.f90(floating point support varies between targets). -
__ppc_intrinsics.f90andmma.f90are only compiled if the LLVM PowerPC backend is enabled, since otherwise Flang will reject it. -
Module dependency resolution is done manually in the CMakeLists.txt using a
if-elseifcascade. -
Does not work when cross-compiling.
-
For building
omp_lib.mod. requiresLLVM_ENABLE_PROJECTS=openmp. This is because it looks foromp_var.F90in openmp’s build directory because it is the output of openmp’s configure phase. WithLLVM_ENABLE_RUNTIMES=openmp, openmp’s build dir is somewhere else, and might not even be present if building openmp standalone (in contrast to a bootstrapping build).LLVM_ENABLE_PROJECTS=openmpwill eventually be deprecated and we currently have no other way to buildomp_lib.mod. Also note thatomp_var.F90importsiso_c_binding.
Require LLVM_RUNTIME_TARGETS=default
Low effort solution where we can assume to find omp_lib.F90 at ${CMAKE_BUILD_DIR}/runtimes/runtimes-bins/openmp/runtime/src.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Solves only 5.
Only works with bootstrapping-builds, not standalone-runtime builds.
Must build runtime default target, even if only interested in cross-compilation
What’s currently upstream in main
There are additional sets of build instructions at
openmp/runtime/src/CMakeLists.txt#L378-L383
and
openmp/runtime/src/CMakeLists.txt#L400-L406
The first is activated with custom code in llvm/runtimes/CMakeLists.txt. With LLVM_RUNTIMES_TARGETS=default, the omp_lib.mod is emitted to runtimes/runtimes-bins/openmp/runtime/src/omp_lib.mod. Because the flang-driver needs to find omp_lib.mod when running tests, that path is added using -J. The actual path is hardcoded.
This wasn’t working for me because check-flang does not depend on building the runtimes. So just running ninja check-flang in a newly configured build directory would fail a lot of OpenMP tests. The CMake output is also “Not building omp_lib.mod, no OpenMP runtime in LLVM_ENABLED_PROJECTS”.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Solves only 5.
Only works with bootstrapping-builds, not standalone-runtime builds.
Must build runtime default target, even if only interested in cross-compilation
When building another LLVM_RUNTIME_TARGETS, onninja installtheomp_lib.modfiles for each target will overwrite each other.
Remove the configure-time dependency to openmp
Some placeholders in the file omp_lib.F90.var are replaced with values from the build configuration:
- Version of the OpenMP runtime library (
libomp.so):kmp_version_major,kmp_version_minor,kmp_version_build,kmp_build_date. - Version of the OpenMP standard supported:
openmp_version
I think what version libomp.so is does not even belong into the header file. Its version may be different from when an OpenMP program is compiled and when it is executed. For instance, an OS update may update libomp.so but the application will not notice since it the header value is fixed. Should be replaced by a reference to a global variable defined in libomp.so using e.g. bind(C).
According to the OpenMP spec, openmp_version is the equivalent to the macro _OPENMP in C, i.e. it is defined by version of OpenMP the compiler supports, not the runtime library or its header. It still might be regarded acceptable since both of them together are the OpenMP implementation. However, to avoid the configure-dependency, could be replaced by a built-in like __builtin_openmp_version that the compiler replaces when compiling to the .mod file.
With these changes, flang could instead compile openmp/runtime/include/omp_lib.F90 from the source tree directly.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
“more correct” than current approach
Solves only 5.
Build the .mod files in the runtimes, not by LLVM_ENABLE_PROJECTS=flang
Instead of the flang build looking for the .f90 files, make the runtimes look for the flang compiler to build their .mod files. That is, LLVM_ENABLE_RUNTIMES=openmp would build omp_lib.mod, and LLVM_ENABLE_RUNTIMES=flang-rt builds the .mod files from flang/module. It already builds the .o file from iso_fortran_env_impl.f90. Therefore I would move the files from /flang/module to Flang-RT.
The target-dependent modules also need to be install into target-triple-dependent paths or they would overwrite each other. That is, the driver needs to be changed to look for modules files in per-target directory. For gfortran, this is already the case. On my Ubuntu system, gfortran’s .mod files are located at /usr/lib/gcc/x86_64-linux-gnu/13/finclude/.
The necessary infrastructure is largely already created in #110217. That is, openmp and flang-rt can instruct the LLVM_ENABLE_RUNTIMES system to make flang available as Fortran compiler.
Solves 1: Different module files for each target
Solves 2: PowerPC module files only included on PowerPC target
Solves 3: Dependency resolution done by CMake
Solves 4: Cross-compilation done by LLVM_ENABLE_RUNTIMES bootstrapping build
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Redundant non-target dependent module files
Modules only become available when compiling openmp/flang-rt
Does not yet work without changes to Flang
This is what I already tried in the first drafts of #110217, but removed this part because I encountered some problems:
-
CMake by default passes pre-processed sources (which are already available because CMake uses it for its dependency analysis), but Flang cannot always compile its own preprocessor output [sic!]. Fortunately, CMake has a workaround, or just adding some line breaks into will solve this issue.
-
Compiling modules requires builtin modules, even if those are the builtin modules themselves. Fortunately, CMake already has a solution: Fortran_BUILDING_INSTRINSIC_MODULES. This option was actually added for Classic Flang.
-
CMake assumes that the output of the compilation step is a
.ofile, but with-fsyntax-only[2] no object file is being emitted. Unmitigated, CMake/ninja will rebuild the module files every time. We could just emit an empty object files for module-only sources, but unfortunately crashes on one some of the builtin modules, e.g.iso_fortran_env.f90because the value of__builtin_numeric_storage_size()cannot be emitted into an object file (it is not a constant but depends on compiler switches passed to Flang). This is also the reason whyiso_fortran_env_impl.f90exists. -
Flang crashes while compiling
__fortran_builtins.modwith the error
error: loc(".../flang/module/__fortran_builtins.f90":203:5): runtime derived type info descriptor was not generated
There is already is a flag that allows emit the object file: -mllvm -ignore-missing-type-desc