[Dwarf-Discuss] Multiple floating point types with the same size but different encodings
Jakub Jelinek
jakub@redhat.com
Mon Jan 24 12:34:01 GMT 2022
Hi!
On powerpc64le-linux, we are in the middle of changing ABI of long double
from the IBM double double format
https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
to IEEE 754 quad (aka binary128)
https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
The big question is how to differentiate between the two in debug info.
E.g. some libraries are written so that they support both types
of long double at the same time (glibc, libstdc++, libgfortran, etc.),
so it isn't just two separate ABIs, process either this or that but
not both.
Currently we emit:
.uleb128 0x3 # (DIE (0x42) DW_TAG_base_type)
.byte 0x10 # DW_AT_byte_size
.byte 0x4 # DW_AT_encoding: DW_ATE_float
.4byte .LASF2 # DW_AT_name: "long double"
for both, both have 16 byte size, but that doesn't allow
consumer to find out how to interpret those bits.
Guess another case would be _Float16 vs. _Bfloat16,
https://en.wikipedia.org/wiki/Half-precision_floating-point_format
vs.
https://en.wikipedia.org/wiki/Bfloat16_floating-point_format
Both types have the same DW_AT_byte_size, both are binary
float (so DW_ATE_float), but they differ e.g. in the precision.
Though, unlike the "long double" case, they will most likely
at least differentiate in DW_AT_name.
>From what I can see, there are HP DW_ATE_* extensions:
/* HP extensions. */
DW_ATE (DW_ATE_HP_float80, 0x80) /* Floating-point (80 bit). */
DW_ATE (DW_ATE_HP_complex_float80, 0x81) /* Complex floating-point (80 bit). */
DW_ATE (DW_ATE_HP_float128, 0x82) /* Floating-point (128 bit). */
DW_ATE (DW_ATE_HP_complex_float128, 0x83) /* Complex fp (128 bit). */
DW_ATE (DW_ATE_HP_floathpintel, 0x84) /* Floating-point (82 bit IA64). */
DW_ATE (DW_ATE_HP_imaginary_float80, 0x85)
DW_ATE (DW_ATE_HP_imaginary_float128, 0x86)
DW_ATE (DW_ATE_HP_VAX_float, 0x88) /* F or G floating. */
DW_ATE (DW_ATE_HP_VAX_float_d, 0x89) /* D floating. */
DW_ATE (DW_ATE_HP_packed_decimal, 0x8a) /* Cobol. */
DW_ATE (DW_ATE_HP_zoned_decimal, 0x8b) /* Cobol. */
DW_ATE (DW_ATE_HP_edited, 0x8c) /* Cobol. */
DW_ATE (DW_ATE_HP_signed_fixed, 0x8d) /* Cobol. */
DW_ATE (DW_ATE_HP_unsigned_fixed, 0x8e) /* Cobol. */
DW_ATE (DW_ATE_HP_VAX_complex_float, 0x8f) /* F or G floating complex. */
DW_ATE (DW_ATE_HP_VAX_complex_float_d, 0x90) /* D floating complex. */
so one possible way is to use some of these.
Though it is complicated by the fact that e.g. GCC or LLVM uses
for _Complex int DW_AT_encoding of 0x80.
Which brings another question, shouldn't we add
DW_ATE_complex_int
as a standard code?
Another possibility would be to introduce e.g.
DW_AT_precision which could differentiate the base types.
IBM double double has standard mantissa precision of 106 bits
(though, it is a weird numerical type where the precision can actually
vary from 53 bits to 2000+), while IEEE754 quad has 113 bits precision.
So, we could add
DW_AT_precision 106 or 113 to the base type (in TUs using just one of them
and not the others easily through DW_FORM_implicit_const).
Thoughts on this?
Jakub
More information about the Dwarf-discuss
mailing list