Skip to content

Commit b964ce2

Browse files
committed
[OpenMP] Add Fortran support for omp_* functions needing adapters
Taking omp_get_uid_from_device and omp_get_device_from_uid as examples. OpenMP 6.0 defines these functions as follows: ``` const char *omp_get_uid_from_device(int device_num); character(:) function omp_get_uid_from_device(device_num) pointer :: omp_get_uid_from_device integer, intent(in) :: device_num ``` and ``` int omp_get_device_from_uid(const char *uid); integer function omp_get_device_from_uid(uid) character(len=*), intent(in) :: uid ``` As a result, we cannot directly map the Fortran API declarations to the C API declarations. We need some adapter code to do the conversion. However, this means that we cannot just define the two functions as omp_* in kmp_ftn_entry.h without clashing with the adapter code. The current situation is less than ideal, as demonstrated by this draft PR, which shall serve as a base for discussing different solution approaches.
1 parent 669683a commit b964ce2

File tree

12 files changed

+445
-33
lines changed

12 files changed

+445
-33
lines changed

openmp/runtime/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ set(LIBOMP_INC_DIR ${LIBOMP_SRC_DIR}/include)
273273
set(LIBOMP_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
274274

275275
# Enabling Fortran if it is needed
276-
if(${LIBOMP_FORTRAN_MODULES})
276+
if(${LIBOMP_FORTRAN_MODULES} OR NOT "${LIBOMP_FORTRAN_MODULES_COMPILER}" STREQUAL "")
277277
enable_language(Fortran)
278278
endif()
279279
# Enable MASM Compiler if it is needed (Windows only)

openmp/runtime/src/CMakeLists.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,48 @@ elseif(${LIBOMP_FORTRAN_MODULES})
422422
set(BUILD_FORTRAN_MODULES True)
423423
endif()
424424

425+
if(BUILD_FORTRAN_MODULES)
426+
if(NOT LIBOMP_FORTRAN_MODULES AND ${LIBOMP_FORTRAN_MODULES_COMPILER} STREQUAL "")
427+
message(FATAL_ERROR
428+
"Generating OpenMP Fortran modules now requires LIBOMP_FORTRAN_MODULES=ON "
429+
"or LIBOMP_FORTRAN_MODULES_COMPILER to be set so the adaptor implementations "
430+
"can be compiled and linked into libomp.")
431+
endif()
432+
target_sources(omp PRIVATE kmp_ftn_support.f90)
433+
set_source_files_properties(kmp_ftn_support.f90
434+
PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_FFLAGS}")
435+
add_dependencies(omp libomp-mod)
436+
# Determine Fortran runtime libraries to link
437+
# For LLVM flang, we need flang_rt.runtime (newer)
438+
set(_LIBOMP_FORTRAN_LIBS "")
439+
if(CMAKE_Fortran_COMPILER_ID MATCHES "LLVMFlang" OR CMAKE_Fortran_COMPILER_ID MATCHES "Flang")
440+
# Derive paths from Fortran compiler location
441+
get_filename_component(_FC_DIR "${CMAKE_Fortran_COMPILER}" DIRECTORY)
442+
get_filename_component(_FC_PREFIX "${_FC_DIR}" DIRECTORY)
443+
444+
# Try to find the flang runtime in clang resource directory
445+
# Path: <prefix>/lib/clang/<version>/lib/<target>/libflang_rt.runtime.a
446+
file(GLOB _FLANG_RT_CANDIDATES
447+
"${_FC_PREFIX}/lib/clang/*/lib/*/libflang_rt.runtime.a"
448+
)
449+
if(_FLANG_RT_CANDIDATES)
450+
list(GET _FLANG_RT_CANDIDATES 0 _FLANG_RT_LIB)
451+
list(APPEND _LIBOMP_FORTRAN_LIBS "${_FLANG_RT_LIB}")
452+
else()
453+
message(WARNING "Could not find LLVM Flang runtime libraries. "
454+
"libomp may fail to link.")
455+
endif()
456+
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
457+
set(_LIBOMP_FORTRAN_LIBS gfortran)
458+
else()
459+
# Fallback to CMake's auto-detected libs
460+
set(_LIBOMP_FORTRAN_LIBS ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES})
461+
endif()
462+
if(_LIBOMP_FORTRAN_LIBS)
463+
target_link_libraries(omp ${_LIBOMP_FORTRAN_LIBS})
464+
endif()
465+
endif()
466+
425467
# Move files to exports/ directory if requested
426468
if(${LIBOMP_COPY_EXPORTS})
427469
include(LibompExports)

openmp/runtime/src/exports_so.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ VERSION {
2929
ompt_libomp_connect; # OMPT libomptarget interface
3030

3131
ompc_*; # omp.h renames some standard functions to ompc_*.
32+
_QMomp_*; # Fortran module procedures (flang name mangling).
3233
kmp_*; # Intel extensions.
3334
kmpc_*; # Intel extensions.
3435
__kmpc_*; # Functions called by compiler-generated code.

openmp/runtime/src/include/omp_lib.F90.var

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,18 @@
904904
integer, intent(in) :: resources(*)
905905
end function omp_get_submemspace
906906

907+
function omp_get_uid_from_device(device_num) result(uid)
908+
use omp_lib_kinds
909+
integer (kind=omp_integer_kind), intent(in) :: device_num
910+
character (:), pointer :: uid
911+
end function omp_get_uid_from_device
912+
913+
function omp_get_device_from_uid(uid) result(device_num)
914+
use omp_lib_kinds
915+
character (len=*), intent(in) :: uid
916+
integer (kind=omp_integer_kind) :: device_num
917+
end function omp_get_device_from_uid
918+
907919
! ***
908920
! *** kmp_* entry points
909921
! ***
@@ -1150,6 +1162,8 @@
11501162
public :: omp_realloc
11511163
public :: omp_free
11521164
public :: omp_in_explicit_task
1165+
public :: omp_get_uid_from_device
1166+
public :: omp_get_device_from_uid
11531167
public :: kmp_set_stacksize
11541168
public :: kmp_set_stacksize_s
11551169
public :: kmp_set_blocktime

openmp/runtime/src/include/omp_lib.h.var

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,17 @@
976976
integer, intent(in) :: resources(*)
977977
end function omp_get_submemspace
978978

979+
function omp_get_uid_from_device(device_num) result(uid)
980+
import
981+
integer (kind=omp_integer_kind), intent(in) :: device_num
982+
character (:), pointer :: uid
983+
end function omp_get_uid_from_device
984+
985+
function omp_get_device_from_uid(uid) result(device_num)
986+
import
987+
character (len=*), intent(in) :: uid
988+
integer (kind=omp_integer_kind) :: device_num
989+
end function omp_get_device_from_uid
979990

980991
! ***
981992
! *** kmp_* entry points

openmp/runtime/src/kmp_ftn_cdecl.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,54 @@ char const __kmp_version_ftncdecl[] =
2929
#define FTN_STDCALL /* no stdcall */
3030
#include "kmp_ftn_os.h"
3131
#include "kmp_ftn_entry.h"
32+
33+
#if KMP_FTN_ENTRIES == KMP_FTN_PLAIN
34+
#define FTN_GET_UID_FROM_DEVICE omp_get_uid_from_device
35+
#define FTN_GET_DEVICE_FROM_UID omp_get_device_from_uid
36+
#endif
37+
#if KMP_FTN_ENTRIES == KMP_FTN_APPEND
38+
#define FTN_GET_UID_FROM_DEVICE omp_get_uid_from_device_
39+
#define FTN_GET_DEVICE_FROM_UID omp_get_device_from_uid_
40+
#endif
41+
#if KMP_FTN_ENTRIES == KMP_FTN_UPPER
42+
#define FTN_GET_UID_FROM_DEVICE OMP_GET_UID_FROM_DEVICE
43+
#define FTN_GET_DEVICE_FROM_UID OMP_GET_DEVICE_FROM_UID
44+
#endif
45+
#if KMP_FTN_ENTRIES == KMP_FTN_UAPPEND
46+
#define FTN_GET_UID_FROM_DEVICE OMP_GET_UID_FROM_DEVICE_
47+
#define FTN_GET_DEVICE_FROM_UID OMP_GET_DEVICE_FROM_UID_
48+
#endif
49+
50+
extern "C" {
51+
const char *FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_UID_FROM_DEVICE)(int device_num)
52+
KMP_WEAK_ATTRIBUTE_EXTERNAL;
53+
const char *FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_UID_FROM_DEVICE)(int device_num) {
54+
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
55+
return nullptr;
56+
#else
57+
const char *(*fptr)(int);
58+
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_uid_from_device")))
59+
return (*fptr)(device_num);
60+
// Returns the same string as used by libomptarget
61+
return "HOST";
62+
#endif
63+
}
64+
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_DEVICE_FROM_UID)(const char *device_uid)
65+
KMP_WEAK_ATTRIBUTE_EXTERNAL;
66+
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_DEVICE_FROM_UID)(const char *device_uid) {
67+
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
68+
return omp_invalid_device;
69+
#else
70+
int (*fptr)(const char *);
71+
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_device_from_uid")))
72+
return (*fptr)(device_uid);
73+
return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)();
74+
#endif
75+
}
76+
77+
KMP_VERSION_SYMBOL(FTN_GET_UID_FROM_DEVICE, 60, "OMP_6.0");
78+
KMP_VERSION_SYMBOL(FTN_GET_DEVICE_FROM_UID, 60, "OMP_6.0");
79+
} // extern "C"
3280
#else
3381
"no";
3482
#endif /* KMP_FTN_ENTRIES */

openmp/runtime/src/kmp_ftn_entry.h

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,33 +1550,6 @@ int FTN_STDCALL FTN_GET_DEVICE_NUM(void) KMP_WEAK_ATTRIBUTE_EXTERNAL;
15501550
int FTN_STDCALL FTN_GET_DEVICE_NUM(void) {
15511551
return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)();
15521552
}
1553-
const char *FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_UID_FROM_DEVICE)(int device_num)
1554-
KMP_WEAK_ATTRIBUTE_EXTERNAL;
1555-
const char *FTN_STDCALL
1556-
KMP_EXPAND_NAME(FTN_GET_UID_FROM_DEVICE)(int device_num) {
1557-
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1558-
return nullptr;
1559-
#else
1560-
const char *(*fptr)(int);
1561-
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_uid_from_device")))
1562-
return (*fptr)(device_num);
1563-
// Returns the same string as used by libomptarget
1564-
return "HOST";
1565-
#endif
1566-
}
1567-
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_DEVICE_FROM_UID)(const char *device_uid)
1568-
KMP_WEAK_ATTRIBUTE_EXTERNAL;
1569-
int FTN_STDCALL
1570-
KMP_EXPAND_NAME(FTN_GET_DEVICE_FROM_UID)(const char *device_uid) {
1571-
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1572-
return omp_invalid_device;
1573-
#else
1574-
int (*fptr)(const char *);
1575-
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_device_from_uid")))
1576-
return (*fptr)(device_uid);
1577-
return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)();
1578-
#endif
1579-
}
15801553

15811554
// Compiler will ensure that this is only called from host in sequential region
15821555
int FTN_STDCALL KMP_EXPAND_NAME(FTN_PAUSE_RESOURCE)(kmp_pause_status_t kind,
@@ -1933,10 +1906,6 @@ KMP_VERSION_SYMBOL(FTN_SET_AFFINITY_FORMAT, 50, "OMP_5.0");
19331906
// KMP_VERSION_SYMBOL(FTN_GET_SUPPORTED_ACTIVE_LEVELS, 50, "OMP_5.0");
19341907
// KMP_VERSION_SYMBOL(FTN_FULFILL_EVENT, 50, "OMP_5.0");
19351908

1936-
// OMP_6.0 versioned symbols
1937-
KMP_VERSION_SYMBOL(FTN_GET_UID_FROM_DEVICE, 60, "OMP_6.0");
1938-
KMP_VERSION_SYMBOL(FTN_GET_DEVICE_FROM_UID, 60, "OMP_6.0");
1939-
19401909
#endif // KMP_USE_VERSION_SYMBOLS
19411910

19421911
#ifdef __cplusplus

openmp/runtime/src/kmp_ftn_extra.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,54 @@ char const __kmp_version_ftnextra[] =
2727
#define FTN_STDCALL /* nothing to do */
2828
#include "kmp_ftn_os.h"
2929
#include "kmp_ftn_entry.h"
30+
31+
#if KMP_FTN_ENTRIES == KMP_FTN_PLAIN
32+
#define FTN_KMP_GET_UID_FROM_DEVICE __kmp_get_uid_from_device
33+
#define FTN_KMP_GET_DEVICE_FROM_UID __kmp_get_device_from_uid
34+
#endif
35+
#if KMP_FTN_ENTRIES == KMP_FTN_APPEND
36+
#define FTN_KMP_GET_UID_FROM_DEVICE __kmp_get_uid_from_device_
37+
#define FTN_KMP_GET_DEVICE_FROM_UID __kmp_get_device_from_uid_
38+
#endif
39+
#if KMP_FTN_ENTRIES == KMP_FTN_UPPER
40+
#define FTN_KMP_GET_UID_FROM_DEVICE __KMP_GET_UID_FROM_DEVICE
41+
#define FTN_KMP_GET_DEVICE_FROM_UID __KMP_GET_DEVICE_FROM_UID
42+
#endif
43+
#if KMP_FTN_ENTRIES == KMP_FTN_UAPPEND
44+
#define FTN_KMP_GET_UID_FROM_DEVICE __KMP_GET_UID_FROM_DEVICE_
45+
#define FTN_KMP_GET_DEVICE_FROM_UID __KMP_GET_DEVICE_FROM_UID_
46+
#endif
47+
48+
extern "C" {
49+
const char *FTN_STDCALL KMP_EXPAND_NAME(FTN_KMP_GET_UID_FROM_DEVICE)(int device_num)
50+
KMP_WEAK_ATTRIBUTE_EXTERNAL;
51+
const char *FTN_STDCALL KMP_EXPAND_NAME(FTN_KMP_GET_UID_FROM_DEVICE)(int device_num) {
52+
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
53+
return nullptr;
54+
#else
55+
const char *(*fptr)(int);
56+
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_uid_from_device")))
57+
return (*fptr)(device_num);
58+
// Returns the same string as used by libomptarget
59+
return "HOST";
60+
#endif
61+
}
62+
int FTN_STDCALL KMP_EXPAND_NAME(FTN_KMP_GET_DEVICE_FROM_UID)(const char *device_uid)
63+
KMP_WEAK_ATTRIBUTE_EXTERNAL;
64+
int FTN_STDCALL KMP_EXPAND_NAME(FTN_KMP_GET_DEVICE_FROM_UID)(const char *device_uid) {
65+
#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
66+
return omp_invalid_device;
67+
#else
68+
int (*fptr)(const char *);
69+
if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_device_from_uid")))
70+
return (*fptr)(device_uid);
71+
return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)();
72+
#endif
73+
}
74+
75+
KMP_VERSION_SYMBOL(FTN_KMP_GET_UID_FROM_DEVICE, 60, "OMP_6.0");
76+
KMP_VERSION_SYMBOL(FTN_KMP_GET_DEVICE_FROM_UID, 60, "OMP_6.0");
77+
} // extern "C"
3078
#else
3179
"no";
3280
#endif /* KMP_FTN_ENTRIES */

0 commit comments

Comments
 (0)