From 866d73019bd4d1804f7e09409322e6605b81780b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 26 Jan 2022 19:42:31 +0100 Subject: [PATCH] dwarf2out: For ppc64le IEEE quad long double, emit DW_TAG_typedef to _Float128 [PR104194] On Mon, Jan 24, 2022 at 11:26:27PM +0100, Jakub Jelinek via Gcc-patches wrote: > Yet another short term solution might be not use DW_TAG_base_type > for the IEEE quad long double, but instead pretend it is a DW_TAG_typedef > with DW_AT_name "long double" to __float128 DW_TAG_base_type. > I bet gdb would even handle it without any changes, but of course, it would > be larger than the other proposed changes. Here it is implemented. Testcases I've played with are e.g.: __ibm128 a; long double b; _Complex long double c; static __attribute__((noinline)) int foo (long double d) { long double e = d + 1.0L; return 0; } int main () { a = 1.0; b = 2.0; c = 5.0 + 6.0i; return foo (7.0L); } and real(kind=16) :: a complex(kind=16) :: b a = 1.0 b = 2.0 end Printing the values of the variables works well, p &b or p &c shows pointer to the correct type, just ptype b or ptype c prints _Float128 instead of long double or complex _Float128 instead of complex long double. Even worse in fortran where obviously _Float128 or complex _Float128 aren't valid types, but as GDB knows them by name, it is just ptype that is weird. 2022-01-26 Jakub Jelinek PR debug/104194 * dwarf2out.cc (long_double_as_float128): New function. (modified_type_die): For powerpc64le IEEE 754 quad long double and complex long double emit those as DW_TAG_typedef to _Float128 or complex _Float128 base type. --- gcc/dwarf2out.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index a5a7f63..ad1d804 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -13568,6 +13568,47 @@ qualified_die_p (dw_die_ref die, int *mask, unsigned int depth) return type; } +/* If TYPE is long double or complex long double that + should be emitted as artificial typedef to _Float128 or + complex _Float128, return the type it should be emitted as. + This is done in case the target already supports 16-byte + composite floating point type (ibm_extended_format). */ + +static tree +long_double_as_float128 (tree type) +{ + if (type != long_double_type_node + && type != complex_long_double_type_node) + return NULL_TREE; + + machine_mode mode, fmode; + if (TREE_CODE (type) == COMPLEX_TYPE) + mode = TYPE_MODE (TREE_TYPE (type)); + else + mode = TYPE_MODE (type); + if (known_eq (GET_MODE_SIZE (mode), 16) && !MODE_COMPOSITE_P (mode)) + FOR_EACH_MODE_IN_CLASS (fmode, MODE_FLOAT) + if (known_eq (GET_MODE_SIZE (fmode), 16) + && MODE_COMPOSITE_P (fmode)) + { + if (type == long_double_type_node) + { + if (float128_type_node + && (TYPE_MODE (float128_type_node) + == TYPE_MODE (type))) + return float128_type_node; + return NULL_TREE; + } + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE + && (TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i)) + == TYPE_MODE (type))) + return COMPLEX_FLOATN_NX_TYPE_NODE (i); + } + + return NULL_TREE; +} + /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging entry that chains the modifiers specified by CV_QUALS in front of the given type. REVERSE is true if the type is to be interpreted in the @@ -13848,7 +13889,32 @@ modified_type_die (tree type, int cv_quals, bool reverse, } else if (is_base_type (type)) { - mod_type_die = base_type_die (type, reverse); + /* If a target supports long double as different floating point + modes with the same 16-byte size, use normal DW_TAG_base_type + only for the composite (ibm_extended_real_format) type and + for the other for the time being emit instead a "_Float128" + or "complex _Float128" DW_TAG_base_type and a "long double" + or "complex long double" typedef to it. */ + if (tree other_type = long_double_as_float128 (type)) + { + dw_die_ref other_die; + if (TYPE_NAME (other_type)) + other_die + = modified_type_die (other_type, TYPE_UNQUALIFIED, reverse, + context_die); + else + { + other_die = base_type_die (type, reverse); + add_child_die (comp_unit_die (), other_die); + add_name_attribute (other_die, + TREE_CODE (type) == COMPLEX_TYPE + ? "complex _Float128" : "_Float128"); + } + mod_type_die = new_die_raw (DW_TAG_typedef); + add_AT_die_ref (mod_type_die, DW_AT_type, other_die); + } + else + mod_type_die = base_type_die (type, reverse); /* The DIE with DW_AT_endianity is placed right after the naked DIE. */ if (reverse_base_type) -- 2.7.4