Enhance debug info for fixed-point types

The Ada language supports fixed-point types as first-class citizens so
they need to be described as-is in the debug info.  We devised the
langhook get_fixed_point_type_info for this purpose a few years ago,
but it comes with a limitation for the representation of the scale
factor that we would need to lift in order to be able to represent
more fixed-point types.

gcc/ChangeLog:
	* dwarf2out.h (struct fixed_point_type_info) <scale_factor>: Turn
	numerator and denominator into a tree.
	* dwarf2out.c (base_type_die): In the case of a fixed-point type
	with arbitrary scale factor, call add_scalar_info on numerator and
	denominator to emit the appropriate attributes.

gcc/ada/ChangeLog:
	* exp_dbug.adb (Is_Handled_Scale_Factor): Delete.
	(Get_Encoded_Name): Do not call it.
	* gcc-interface/decl.c (gnat_to_gnu_entity) <Fixed_Point_Type>:
	Tidy up and always use a meaningful description for arbitrary
	scale factors.
	* gcc-interface/misc.c (gnat_get_fixed_point_type_info): Remove
	obsolete block and adjust the description of the scale factor.
This commit is contained in:
Eric Botcazou 2020-11-19 11:04:52 +01:00
parent 0d8290959e
commit 43a0debd52
5 changed files with 27 additions and 92 deletions

View File

@ -133,11 +133,6 @@ package body Exp_Dbug is
-- Determine whether the bounds of E match the size of the type. This is
-- used to determine whether encoding is required for a discrete type.
function Is_Handled_Scale_Factor (U : Ureal) return Boolean;
-- The argument U is the Small_Value of a fixed-point type. This function
-- determines whether the back-end can handle this scale factor. When it
-- cannot, we have to output a GNAT encoding for the corresponding type.
procedure Output_Homonym_Numbers_Suffix;
-- If homonym numbers are stored, then output them into Name_Buffer
@ -594,27 +589,6 @@ package body Exp_Dbug is
return Make_Null_Statement (Loc);
end Debug_Renaming_Declaration;
-----------------------------
-- Is_Handled_Scale_Factor --
-----------------------------
function Is_Handled_Scale_Factor (U : Ureal) return Boolean is
begin
-- Keep in sync with gigi (see E_*_Fixed_Point_Type handling in
-- decl.c:gnat_to_gnu_entity).
if UI_Eq (Numerator (U), Uint_1) then
if Rbase (U) = 2 or else Rbase (U) = 10 then
return True;
end if;
end if;
return
(UI_Is_In_Int_Range (Norm_Num (U))
and then
UI_Is_In_Int_Range (Norm_Den (U)));
end Is_Handled_Scale_Factor;
----------------------
-- Get_Encoded_Name --
----------------------
@ -671,12 +645,10 @@ package body Exp_Dbug is
Has_Suffix := True;
-- Fixed-point case: generate GNAT encodings when asked to or when we
-- know the back-end will not be able to handle the scale factor.
-- Fixed-point case: generate GNAT encodings when asked to
if Is_Fixed_Point_Type (E)
and then (GNAT_Encodings /= DWARF_GNAT_Encodings_Minimal
or else not Is_Handled_Scale_Factor (Small_Value (E)))
and then GNAT_Encodings /= DWARF_GNAT_Encodings_Minimal
then
Get_External_Name (E, True, "XF_");
Add_Real_To_Buffer (Delta_Value (E));

View File

@ -1743,24 +1743,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_type = make_signed_type (esize);
/* Try to decode the scale factor and to save it for the fixed-point
types debug hook. */
/* There are various ways to describe the scale factor, however there
are cases where back-end internals cannot hold it. In such cases,
we output invalid scale factor for such cases (i.e. the 0/0
rational constant) but we expect GNAT to output GNAT encodings,
then. Thus, keep this in sync with
Exp_Dbug.Is_Handled_Scale_Factor. */
/* When encoded as 1/2**N or 1/10**N, describe the scale factor as a
binary or decimal scale: it is easier to read for humans. */
if (UI_Eq (Numerator (gnat_small_value), Uint_1)
&& (Rbase (gnat_small_value) == 2
|| Rbase (gnat_small_value) == 10))
{
/* Given RM restrictions on 'Small values, we assume here that
the denominator fits in an int. */
tree base
= build_int_cst (integer_type_node, Rbase (gnat_small_value));
tree exponent
@ -1773,29 +1761,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
base, exponent));
}
/* Default to arbitrary scale factors descriptions. */
else
/* Use the arbitrary scale factor description. Note that we support
a Small_Value whose magnitude is larger than 64-bit even on 32-bit
platforms, so we unconditionally use a (dummy) 128-bit type. */
{
const Uint num = Norm_Num (gnat_small_value);
const Uint den = Norm_Den (gnat_small_value);
const Uint gnat_num = Norm_Num (gnat_small_value);
const Uint gnat_den = Norm_Den (gnat_small_value);
tree gnu_small_type = make_unsigned_type (128);
tree gnu_num = UI_To_gnu (gnat_num, gnu_small_type);
tree gnu_den = UI_To_gnu (gnat_den, gnu_small_type);
if (UI_Is_In_Int_Range (num) && UI_Is_In_Int_Range (den))
{
tree gnu_num
= build_int_cst (integer_type_node,
UI_To_Int (Norm_Num (gnat_small_value)));
tree gnu_den
= build_int_cst (integer_type_node,
UI_To_Int (Norm_Den (gnat_small_value)));
scale_factor = build2 (RDIV_EXPR, integer_type_node,
gnu_num, gnu_den);
}
else
/* If compiler internals cannot represent arbitrary scale
factors, output an invalid scale factor so that debugger
don't try to handle them but so that we still have a type
in the output. Note that GNAT */
scale_factor = integer_zero_node;
scale_factor
= build2 (RDIV_EXPR, gnu_small_type, gnu_num, gnu_den);
}
TYPE_FIXED_POINT_P (gnu_type) = 1;

View File

@ -628,16 +628,6 @@ gnat_get_fixed_point_type_info (const_tree type,
/* We expect here only a finite set of pattern. See fixed-point types
handling in gnat_to_gnu_entity. */
/* Put invalid values when compiler internals cannot represent the scale
factor. */
if (scale_factor == integer_zero_node)
{
info->scale_factor_kind = fixed_point_scale_factor_arbitrary;
info->scale_factor.arbitrary.numerator = 0;
info->scale_factor.arbitrary.denominator = 0;
return true;
}
if (TREE_CODE (scale_factor) == RDIV_EXPR)
{
tree num = TREE_OPERAND (scale_factor, 0);
@ -677,8 +667,8 @@ gnat_get_fixed_point_type_info (const_tree type,
&& TREE_CODE (den) == INTEGER_CST);
info->scale_factor_kind = fixed_point_scale_factor_arbitrary;
info->scale_factor.arbitrary.numerator = tree_to_uhwi (num);
info->scale_factor.arbitrary.denominator = tree_to_shwi (den);
info->scale_factor.arbitrary.numerator = num;
info->scale_factor.arbitrary.denominator = den;
return true;
}

View File

@ -12973,18 +12973,19 @@ base_type_die (tree type, bool reverse)
break;
case fixed_point_scale_factor_arbitrary:
/* Arbitrary scale factors cannot be described in standard DWARF,
yet. */
/* Arbitrary scale factors cannot be described in standard DWARF. */
if (!dwarf_strict)
{
/* Describe the scale factor as a rational constant. */
const dw_die_ref scale_factor
= new_die (DW_TAG_constant, comp_unit_die (), type);
add_AT_unsigned (scale_factor, DW_AT_GNU_numerator,
fpt_info.scale_factor.arbitrary.numerator);
add_AT_int (scale_factor, DW_AT_GNU_denominator,
fpt_info.scale_factor.arbitrary.denominator);
add_scalar_info (scale_factor, DW_AT_GNU_numerator,
fpt_info.scale_factor.arbitrary.numerator,
dw_scalar_form_constant, NULL);
add_scalar_info (scale_factor, DW_AT_GNU_denominator,
fpt_info.scale_factor.arbitrary.denominator,
dw_scalar_form_constant, NULL);
add_AT_die_ref (base_type_result, DW_AT_small, scale_factor);
}

View File

@ -362,23 +362,18 @@ enum fixed_point_scale_factor
struct fixed_point_type_info
{
/* A scale factor is the value one has to multiply with physical data in
order to get the fixed point logical data. The DWARF standard enables one
to encode it in three ways. */
/* The scale factor is the value one has to multiply the actual data with
to get the fixed point value. We support three ways to encode it. */
enum fixed_point_scale_factor scale_factor_kind;
union
{
/* For binary scale factor, the scale factor is: 2 ** binary. */
/* For a binary scale factor, the scale factor is 2 ** binary. */
int binary;
/* For decimal scale factor, the scale factor is: 10 ** binary. */
/* For a decimal scale factor, the scale factor is 10 ** decimal. */
int decimal;
/* For arbitrary scale factor, the scale factor is:
/* For an arbitrary scale factor, the scale factor is the ratio
numerator / denominator. */
struct
{
unsigned HOST_WIDE_INT numerator;
HOST_WIDE_INT denominator;
} arbitrary;
struct { tree numerator; tree denominator; } arbitrary;
} scale_factor;
};