diff mbox series

[v2] libgomp.texi: Document OpenMP's Interoperability Routines

Message ID 96d6109a-e393-4920-9c5b-b9ae36de8cb9@baylibre.com
State New
Headers show
Series [v2] libgomp.texi: Document OpenMP's Interoperability Routines | expand

Commit Message

Tobias Burnus Aug. 23, 2024, 1:03 p.m. UTC
Minor update, mainly because of the 'optional' changes in v3 of the 
patch https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661313.html

The 'optional' affects the omp_get_interop_{int,ptr,str} but also 
omp_target_memcpy_async, omp_target_memcpy_rect_async got a few words.

Additionally, the returned string of omp_get_interop_type_desc is now 
better described (in GCC it is the C/C++ type decl as string or "N/A" or 
NULL). And a couple of notes about calling the routines from inside a 
non-host target region were added.

Tobias Burnus:
> Add documentation for OpenMP's interoperability routines.
>
> This obviously, depends on the actual implementation patch, posted at: 
> https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661035.html 
> (albeit I will post a v2 in a moment).
>
> I am sure there will be comments, suggestions and remarks :-)
>
> Tobias
>
> PS: I am not 100% sure whether adding the implementation detail makes 
> sense or not.
Tobias

Comments

Sandra Loosemore Aug. 26, 2024, 3:58 p.m. UTC | #1
On 8/23/24 07:03, Tobias Burnus wrote:
>> Add documentation for OpenMP's interoperability routines.

I have only a few copy-editing type comments.

> +Implementation remark: In GCC, the Fortran interface differs from the one shown
> +below: the function has C binding, @var{interop} is passed by value and an
> +integer of @code{c_int} kind is returnd, permitting to have the same ABI as the

s/returnd/returned/ (this seems to be the only instance in the patch)

s/permitting to have/which permits use of/g (multiple instances)

> +C function.  This does not affect the usage of the function when GCC's
> +@code{omp_lib} module or @code{omp_lib.h} header is used.

Stepping back to consider this from a higher-level perspective, 
shouldn't the interface documented in the GCC manual reflect what GCC 
implements, rather than what the spec says that is explicitly *not* what 
is implemented?  Or is the way you have documented this consistent with 
the way other libgomp features that don't strictly conform to the spec 
have already been documented?

> +The @code{omp_get_interop_name} function returns the name of the property
> +itself as string; for the properties specified by the OpenMP specification,
> +the name matches the name of the named constant with the @code{omp_ipr_}
> +prefix removed.

That should be @samp{omp_ipr_}, not @code markup.

> +In GCC, this function returns the C/C++ data type for this property or

the name of the C/C++ data type

> +@samp{N/A} if this property is not available for the given foreign runtime.

@code{"N/A"}, I think.  (It's a string literal, right?)

> +If @var{interop} is @code{omp_interop_none} or for invalid property values,
> +a null pointer is returned. The the effect of running this routine in a

s/The the/The/

> +The @code{omp_get_interop_rc_desc} function returns a string value describing
> +the @var{ret_code} in human readable form.

s/human readable form/human-readable form/

I know the libgomp manual uses different formatting conventions than the 
GCC manual or other Texinfo manuals.  Have you inspected the formatted 
output to make sure it's what you expect and consistent with the rest of 
the document?

-Sandra
Tobias Burnus Aug. 28, 2024, 1:58 p.m. UTC | #2
Hi Sandra,

thanks for your comments.

Sandra Loosemore wrote:
> Stepping back to consider this from a higher-level perspective, 
> shouldn't the interface documented in the GCC manual reflect what GCC 
> implements, rather than what the spec says that is explicitly *not* 
> what is implemented?  Or is the way you have documented this 
> consistent with the way other libgomp features that don't strictly 
> conform to the spec have already been documented?

The idea of the implementation is to be 100% compatible to the OpenMP 
specification in terms of usage – but to deviate in terms of the implied 
ABI.

The issue is really that the specification is more explicit than it 
should be - but it is clear why it is such:

It is much easier and more readable to write: 'subroutine f(x); integer 
:: x' — instead of stating that "subroutine f" exists and takes "x" as 
argument which accepts default-kind integers.

But the first version automatically implies that it is not "subroutine 
f(x) BIND(C)" and not "integer, VALUE :: x".

However, I want to use bind(C) and value in GCC. For a user that 
includes the omp_lib module (or omp_lib.h header), the difference is not 
visible.

* * *

I personally dislike it a lot if vendor documentation of a specific 
standard function deviates in declaration, semantic or accepted 
arguments without telling me that it is modified.

That's the reason I mentioned it in the previously attached patch. 
However, as it only affects the ABI – and does not affect users (unless 
they really care about the internal decl), maybe just not mentioning the 
differences is better?

[RFC] Thus, the question is whether it should be stated in the manual or 
not? (Removed completely or kept commented out?)

AsI wrote in the original email: "PS: I am not 100% sure whether adding 
the implementation detail makes sense or not."

* * *

In the attached patch, I commented it out in the .texi but left it there.

* * *
>> +the name matches the name of the named constant with the 
>> @code{omp_ipr_}
>> +prefix removed.
>
> That should be @samp{omp_ipr_}, not @code markup.

Hmm, I thought that non-white-space strings and in particular 
[A-Za-z0-9_]+ would be permissible for @code and only when going beyond 
one would need something else.

>> +@samp{N/A} if this property is not available for the given foreign 
>> runtime.
>
> @code{"N/A"}, I think.  (It's a string literal, right?)

Well, the result of the function call is a pointer to the string N, /, 
A, \0 – and not to ", N, /, A, ", \0. And while the code indeed uses 
"N/A" it could also do res[0] = 'N'; res[1] = '/', …

Thus, I think @code{"N/A"} (with quotation marks) is slightly 
misleading. — I am happy to use @code{N/A} instead of @samp{N/A}, if 
that seems to be more appropriate, but I am not so happy about @code{"N/A"}.

* * *

> I know the libgomp manual uses different formatting conventions than 
> the GCC manual or other Texinfo manuals.  Have you inspected the 
> formatted output to make sure it's what you expect and consistent with 
> the rest of the document?

It looked okay when glancing over the result in info, PDF and HTML 
format, right now and also when when I posted the previous patch.

New is that I don't explicitly line break lines in the interface. Doing 
so lead before to odd very short lines in the HTML version and possible 
double breaks in the 'info' file if the 'info' line was a bit shorter 
than what was anticipated in the .texi file. As the result of the 
automatic line breaks looks reasonable, I used it as such.

Remarks:

* '@code{  abc}' leads to an indentation in some of the output formats 
but not in all; thus, I have not used it. Some but not all existing code 
uses it. — Using '@ @ @code' would work, but is ugly and not really 
needed, either.

* I think we could consider updating the style eventually to be 
consistent with GCC's style (and move there slowly and step wise).

* Regarding 'abc -- def' vs. 'abc---def', that's a Europeanism. To quote 
the "Oxford Guide to Style": "OUP [Oxford University Press] and most US 
publishers use the unspaced (non-touching) em rule as a parenthetical 
dash; other British publishers use the en rule with space either side."

Tobias

PS: I have partially updated the patch + attached it, but it is not yet 
fully updated; also because we have not yet settled on the items above.
Tobias Burnus Nov. 7, 2024, 3:27 p.m. UTC | #3
As there were no further remarks, I have now committed it as
r15-5017-ge52cfd4bc23de1 with minor changes:

* Referring to v6.0 not TR13 (same section numbers),
* fixed one item in the 5.2 to-do list:
   'declare mapper with iterator and present modifiers' comes from Appendix B
   and we had before additionally
   '|iterator| and|mapper| as map-type modifier in|declare mapper' which duplicated 'iterator'. (The item remains, but now 
only covering 'mapper' as map-type modifier.) |
Comments and follow-up suggestions are still welcome.

See (in about 9 hours for the new version) at:
-https://gcc.gnu.org/onlinedocs/libgomp/OpenMP-5_002e2.html
   for the 'declare_mapper' implementation status
-https://gcc.gnu.org/onlinedocs/libgomp/Runtime-Library-Routines.html
   for the interop routines

Tobias

PS: Previous patch was posted on Wed Aug 28, 2024 to
https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661711.html
Tobias Burnus Nov. 7, 2024, 3:37 p.m. UTC | #4
I intended – but forgot – to actually attach the committed patch. Here 
it is …

Tobias Burnus wrote:
> As there were no further remarks, I have now committed it as
> r15-5017-ge52cfd4bc23de1 with minor changes:
>
> * Referring to v6.0 not TR13 (same section numbers),
> * fixed one item in the 5.2 to-do list:
>    'declare mapper with iterator and present modifiers' comes from Appendix B
>    and we had before additionally
>    '|iterator| and|mapper| as map-type modifier in|declare mapper' which duplicated 'iterator'. (The item remains, but 
> now only covering 'mapper' as map-type modifier.) |
> Comments and follow-up suggestions are still welcome.
>
> See (in about 9 hours for the new version) at:
> -https://gcc.gnu.org/onlinedocs/libgomp/OpenMP-5_002e2.html
>    for the 'declare_mapper' implementation status
> -https://gcc.gnu.org/onlinedocs/libgomp/Runtime-Library-Routines.html
>    for the interop routines
>
> Tobias
>
> PS: Previous patch was posted on Wed Aug 28, 2024 to
> https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661711.html
diff mbox series

Patch

libgomp.texi: Document OpenMP's Interoperability Routines

libgomp/ChangeLog:

	* libgomp.texi (Interoperability Routines): Add.
	(omp_target_memcpy_async, omp_target_memcpy_rect_async):
	Document that depobj_list may be omitted in C++ and Fortran.

diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index fe25d879788..b36b58b6d10 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -656,7 +656,7 @@  specification in version 5.2.
 * Lock Routines::
 * Timing Routines::
 * Event Routine::
-@c * Interoperability Routines::
+* Interoperability Routines::
 * Memory Management Routines::
 @c * Tool Control Routine::
 * Environment Display Routine::
@@ -2134,8 +2134,9 @@  to the destination device's @var{dst} address shifted by @var{dst_offset}.
 Task dependence is expressed by passing an array of depend objects to
 @var{depobj_list}, where the number of array elements is passed as
 @var{depobj_count}; if the count is zero, the @var{depobj_list} argument is
-ignored.  The routine returns zero if the copying process has successfully
-been started and non-zero otherwise.
+ignored.  In C++ and Fortran, the @var{depobj_list} argument can also be
+omitted in that case.   The routine returns zero if the copying process has
+successfully been started and non-zero otherwise.
 
 Running this routine in a @code{target} region except on the initial device
 is not supported.
@@ -2255,7 +2256,8 @@  respectively.  The offset per dimension to the first element to be copied is
 given by the @var{dst_offset} and @var{src_offset} arguments.  Task dependence
 is expressed by passing an array of depend objects to @var{depobj_list}, where
 the number of array elements is passed as @var{depobj_count}; if the count is
-zero, the @var{depobj_list} argument is ignored.  The routine
+zero, the @var{depobj_list} argument is ignored.  In C++ and Fortran, the
+@var{depobj_list} argument can also be omitted in that case.  The routine
 returns zero on success and non-zero otherwise.
 
 The OpenMP specification only requires that @var{num_dims} up to three is
@@ -2884,21 +2886,315 @@  event handle that has already been fulfilled is also undefined.
 
 
 
-@c @node Interoperability Routines
-@c @section Interoperability Routines
-@c
-@c Routines to obtain properties from an @code{omp_interop_t} object.
-@c They have C linkage and do not throw exceptions.
-@c
-@c @menu
-@c * omp_get_num_interop_properties:: <fixme>
-@c * omp_get_interop_int:: <fixme>
-@c * omp_get_interop_ptr:: <fixme>
-@c * omp_get_interop_str:: <fixme>
-@c * omp_get_interop_name:: <fixme>
-@c * omp_get_interop_type_desc:: <fixme>
-@c * omp_get_interop_rc_desc:: <fixme>
-@c @end menu
+@node Interoperability Routines
+@section Interoperability Routines
+
+Routines to obtain properties from an object of OpenMP interop type.
+They have C linkage and do not throw exceptions.
+
+@menu
+* omp_get_num_interop_properties:: Get the number of implementation-specific properties
+* omp_get_interop_int:: Obtain integer-valued interoperability property
+* omp_get_interop_ptr:: Obtain pointer-valued interoperability property
+* omp_get_interop_str:: Obtain string-valued interoperability property
+* omp_get_interop_name:: Obtain the name of an interop_property value as string
+* omp_get_interop_type_desc:: Obtain type and description to an interop_property
+* omp_get_interop_rc_desc:: Obtain error string to an interop_rc error code
+@end menu
+
+
+
+@node omp_get_num_interop_properties
+@subsection @code{omp_get_num_interop_properties} -- Get the number of implementation-specific properties
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_num_interop_properties} function returns the number of
+implementation-defined interoperability properties available for the passed
+@var{interop}, extending the OpenMP-defined properties.  The available OpenMP
+interop_property-type values range from @code{omp_ipr_first} to the value
+returned by @code{omp_get_num_interop_properties} minus one.
+
+No implementation-defined properties are currently defined in GCC.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: the function has C binding, @var{interop} is passed by value and an
+integer of @code{c_int} kind is returnd, permitting to have the same ABI as the
+C function.  This does not affect the usage of the function when GCC's
+@code{omp_lib} module or @code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_num_interop_properties(const omp_interop_t interop)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer function omp_get_num_interop_properties(interop)}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_interop_name}, @ref{omp_get_interop_type_desc}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.1,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.1
+@end table
+
+
+
+@node omp_get_interop_int
+@subsection @code{omp_get_interop_int} -- Obtain integer-valued interoperability property
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_int} function returns the integer value associated
+with the @var{property_id} interoperability property of the passed @var{interop}
+object.  The @var{ret_code} argument is optional, i.e. it can be omitted in C++
+and Fortran or with @code{NULL} as argument in C and C++.  If successful,
+@var{ret_code} (if present) is set to @code{omp_irc_success}.
+
+In GCC, the effect of running this routine in a @code{target} region that is not
+the initial device is unspecified.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: the function has C binding and @var{interop} and @var{property_id} are
+passed by value, permitting to have the same ABI as the C function.  This does
+not affect the usage of the function when GCC's @code{omp_lib} module or
+@code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{omp_intptr_t omp_get_interop_int(const omp_interop_t interop,
+                                   omp_interop_property_t property_id, int *ret_code)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer(c_intptr_t) function omp_get_interop_int(interop,
+                                   property_id, ret_code)}
+@item                   @tab @code{use, intrinsic :: iso_c_binding, only : c_intptr_t}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer(omp_interop_property_kind) property_id}
+@item                   @tab @code{integer(omp_interop_rc_kind), optional, intent(out) :: ret_code}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_interop_ptr}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc}
+@c @ref{Offload-Target Specifics}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.2,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.2
+@end table
+
+
+
+@node omp_get_interop_ptr
+@subsection @code{omp_get_interop_ptr} -- Obtain pointer-valued interoperability property
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_int} function returns the pointer value associated with
+the @var{property_id} interoperability property of the passed @var{interop}
+object.  The @var{ret_code} argument is optional, i.e. it can be omitted in C++
+and Fortran or with @code{NULL} as argument in C and C++.  If successful,
+@var{ret_code} (if present) is set to @code{omp_irc_success}.
+
+In GCC, the effect of running this routine in a @code{target} region that is not
+the initial device is unspecified.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: the function has C binding and @var{interop} and @var{property_id} are
+passed by value, permitting to have the same ABI as the C function.  This does
+not affect the usage of the function when GCC's @code{omp_lib} module or
+@code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{void *omp_get_interop_ptr(const omp_interop_t interop,
+                                   omp_interop_property_t property_id, int *ret_code)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{type(c_ptr) function omp_get_interop_int(interop,
+                                   property_id, ret_code)}
+@item                   @tab @code{use, intrinsic :: iso_c_binding, only : c_ptr}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer(omp_interop_property_kind) property_id}
+@item                   @tab @code{integer(omp_interop_rc_kind), optional, intent(out) :: ret_code}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_interop_int}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc}
+@c @ref{Offload-Target Specifics}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.3,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.3
+@end table
+
+
+
+@node omp_get_interop_str
+@subsection @code{omp_get_interop_str} -- Obtain string-valued interoperability property
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_str} function returns the string value associated with
+the @var{property_id} interoperability property of the passed @var{interop}
+object.  The @var{ret_code} argument is optional, i.e. it can be omitted in C++
+and Fortran or with @code{NULL} as argument in C and C++.  If successful,
+@var{ret_code} (if present) is set to @code{omp_irc_success}.
+
+In GCC, the effect of running this routine in a @code{target} region that is not
+the initial device is unspecified.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: @var{interop} and @var{property_id} are passed by value.  This does not
+affect the usage of the function when GCC's @code{omp_lib} module or
+@code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{const char *omp_get_interop_str(const omp_interop_t interop,
+                                   omp_interop_property_t property_id, int *ret_code)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{character(:) function omp_get_interop_str(interop,
+                                   property_id, ret_code)}
+@item                   @tab @code{pointer :: omp_get_interop_str}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer(omp_interop_property_kind) property_id}
+@item                   @tab @code{integer(omp_interop_rc_kind), optional, intent(out) :: ret_code}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_interop_int}, @ref{omp_get_interop_ptr}, @ref{omp_get_interop_rc_desc}
+@c @ref{Offload-Target Specifics}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.4,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.4
+@end table
+
+
+
+@node omp_get_interop_name
+@subsection @code{omp_get_interop_name} -- Obtain the name of an @code{interop_property} value as string
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_name} function returns the name of the property
+itself as string; for the properties specified by the OpenMP specification,
+the name matches the name of the named constant with the @code{omp_ipr_}
+prefix removed.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: @var{interop} and @var{property_id} are passed by value.  This does not
+affect the usage of the function when GCC's @code{omp_lib} module or
+@code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{const char *omp_get_interop_name(const omp_interop_t interop,
+                                   omp_interop_property_t property_id)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{character(:) function omp_get_interop_name(interop,
+                                   property_id)}
+@item                   @tab @code{pointer :: omp_get_interop_name}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer(omp_interop_property_kind) property_id}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_num_interop_properties}, @ref{omp_get_interop_type_desc}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.5,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.5
+@end table
+
+
+
+@node omp_get_interop_type_desc
+@subsection @code{omp_get_interop_type_desc} -- Obtain type and description to an @code{interop_property}
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_type_desc} function returns a string that describes in
+human-readable form the data type associated with the @var{property_id}
+interoperability property of the passed @var{interop} object.
+
+In GCC, this function returns the C/C++ data type for this property or
+@samp{N/A} if this property is not available for the given foreign runtime.
+If @var{interop} is @code{omp_interop_none} or for invalid property values,
+a null pointer is returned. The the effect of running this routine in a
+@code{target} region that is not the initial device is unspecified.
+
+Implementation remark: In GCC, the Fortran interface differs from the one shown
+below: @var{interop} and @var{property_id} are passed by value.  This does not
+affect the usage of the function when GCC's @code{omp_lib} module or
+@code{omp_lib.h} header is used.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{const char *omp_get_interop_type_desc(const omp_interop_t interop,
+                                   omp_interop_property_t property_id)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{character(:) function omp_get_interop_type_desc(interop,
+                                   property_id)}
+@item                   @tab @code{pointer :: omp_get_interop_type_desc}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer(omp_interop_property_kind) property_id}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_get_num_interop_properties}, @ref{omp_get_interop_name}
+@c @ref{Offload-Target Specifics}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.6,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.6
+@end table
+
+
+
+@node omp_get_interop_rc_desc
+@subsection @code{omp_get_interop_rc_desc} -- Obtain error string to an @code{interop_rc} error code
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_interop_rc_desc} function returns a string value describing
+the @var{ret_code} in human readable form.
+
+The behavior is unspecified if value of @var{ret_code} was not set by an
+interoperability routine invoked for @var{interop}.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{const char *omp_get_interop_rc_desc(const omp_interop_t interop,
+                                   omp_interop_rc_t ret_code)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{character(:) function omp_get_interop_rc_desc(interop,
+                                   property_id, ret_code)}
+@item                   @tab @code{pointer :: omp_get_interop_rc_desc}
+@item                   @tab @code{integer(omp_interop_kind), intent(in) :: interop}
+@item                   @tab @code{integer (omp_interop_rc_kind) ret_code}
+@end multitable
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.7,
+@uref{https://www.openmp.org, OpenMP specification TR13}, Section 26.7
+@end table
+
+
 
 @node Memory Management Routines
 @section Memory Management Routines