Hi,
the Ada language supports fixed-point types as first-class citizens so they
need to be described as-is in the debug info. Pierre-Marie 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.
Since it's only used by the Ada compiler, this is probably non-controversial
but someone still needs to approve the change. Thanks in advance.
2020-11-11 Eric Botcazou <ebotca...@adacore.com>
* 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.
2020-11-11 Eric Botcazou <ebotca...@adacore.com>
* 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.
--
Eric Botcazou
diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb
index c2e774140ff..dc6cd265af4 100644
--- a/gcc/ada/exp_dbug.adb
+++ b/gcc/ada/exp_dbug.adb
@@ -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));
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index fa17ad9453f..a0f17b1aafc 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -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;
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 87724af814e..d0867e00c85 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -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;
}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index bc32a17efcd..413484436d6 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -12963,18 +12963,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);
}
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 9571f8b4b10..0b06cff477b 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -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;
};