Per discussion here https://gcc.gnu.org/pipermail/fortran/2021-August/056334.html there seems to be some confusion in the Fortran front end re gfc_real16_is_float128 and gfc_float128_type_node. The C __float128 type must correspond to an IEEE representation and that isn't being checked where those variables are being set. In cases where __float128 interoperability is required, it should be using float128_type_node with some additional check to make sure Fortran recognizes that mode (as in the patch for c_float128 and c_float128_complex attached to the mail linked above). In cases where all that matters is that it's kind=16 and not the same kind as long double, it would be less confusing to rename gfc_float128_type_node to gfc_real16_type_node. Also, note that on PowerPC there are 3 different 128-bit float modes, and the one that is defined to have precision 128 is the explicit IBM encoding, not IEEE, so the check for mode_precision == 128 in gfc_build_real_type is guaranteed not to find the __float128 equivalent on that target. (The long double size on that target is configurable by command-line option but I don't know what actually makes sense from an ABI/CPU support point of view; it's at least conceivable that it could trip over that test, though.)
See linked thread for a longer description, https://gcc.gnu.org/pipermail/fortran/2021-August/thread.html#56315 (the link in comment 0 is in the same thread) However, the following issues exist: * ISO_C_Binding's c_float128 (gfortran vendor extension) has to match __float128 (cf. also comment 0) * ISO_Fortran_env provides: - REAL128 (whose storage size expressed in bits is 128) [since Fortran 2008] - REAL_KINDS - array with supported real kinds (Fortran: no order requirements) In gfortran, it is ordered; e.g. on x86-64 w/ libquadmath: [4,8,10,16]. * gfortran currently uses: – float, double and long double – which used GCC's builtins, the 'f','','l' suffixes (sinf, sin, sinl) and uses in libgfortran those data types - TFmode - Other real types are filtered out. * If long double's mode != TFmode, the FE assumes that TFmode is for __float128 – and sets info->c_float128 / yield gfc_real16_is_float128() = true However, this assumption is wrong in the general case, e.g. PowerPC has __float128 == KFmode and TFmode == 'long double' (There is currently no clash as KFmode is filtered out and TFmode == long double's mode). If a real type is regarded as float128, the FE calls the functions with 'q' suffix (such as sinq), libgfortran uses __float128 for those and there is some implicit assumption that libquadmath is available, which provides those 'q' functions. * Kind values: Currently supported are 4, 8, 10 (80bits; i387), 11 (82bits; IA-64, RFmode), 16 However, kind=11 does not seem to be tested for (and could be better documented) The kind value is generated as: kind = (GET_MODE_PRECISION (mode) + 7) / 8; (The '+ 7' is for IA-64's RFmode to map to kind=11.) Fortran itself does not require IEEE support and the kind numbers are arbitrary, albeit users expect that 4 and 8 exists (and match float/double), some expect that 16 exists and – only with gfortran – kind=10. The proper use is to use either the constants like: REAL128, use REAL_KINDS and the function SELECTED_REAL_KIND [IEEE has to be supported for types where IEEE_SUPPORT_DATATYPE () returns .true.] * Plus PowerPC: #define FLOAT_PRECISION_IFmode 128 #define FLOAT_PRECISION_TFmode 127 #define FLOAT_PRECISION_KFmode 126 with IFmode (IBM 128-bit floating point), TFmode (long double mode), KFmode (explicit __float128). - The current 'kind =' calculation above has kind=16 for all of them. (except that IFmode and TFmode are filtered out) - When adding support for IFmode/KFmode PowerPC mode, the proper library function has to be called (suffix? ABI in libgfortran?) - PowerPC (rs6000) has the command line flags: -mfloat128 Enable/disable the __float128 keyword for IEEE 128-bit floating point and use either software emulation for IEEE 128-bit floating point or hardware instructions. -mabi=ibmlongdouble Change the current ABI to use IBM extended-precision long double. This is not likely to work if your system defaults to using IEEE extended-precision long double. -mabi=ieeelongdouble Change the current ABI to use IEEE extended-precision long double. This is not likely to work if your system defaults to using IBM extended-precision long double. - As kind=16 is explicitly used, it should be supported but, otherwise, the other kinds can be mapped to any kind value, e.g. 15,16,17. There are ABI and compatibility issues – but they should be similar to C/C++.