Enhance debug info for fixed-point types
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 19 Nov 2020 10:04:52 +0000 (11:04 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Thu, 19 Nov 2020 10:04:52 +0000 (11:04 +0100)
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.

gcc/ada/exp_dbug.adb
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/misc.c
gcc/dwarf2out.c
gcc/dwarf2out.h

index c2e774140ff5878cf164f112522a01ee1498b89c..dc6cd265af438320bb57ec5edaf0a077a6fde0e5 100644 (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));
index fa17ad9453f3524142028fa90f3d93f3618d1aeb..a0f17b1aafcb08c8dc9f739fbec0d8b96094f2e1 100644 (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;
index 87724af814e1926913b37801d3a3637f5ba78d11..d0867e00c852da0112e3bc4bf2ba19292278d80f 100644 (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;
     }
 
index 54eb445665ca326703c431dbc707cd9d16230241..ea2a22a304200e5d87b3d76385192d1d6f9ecb25 100644 (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);
            }
index 9571f8b4b10d13cfdf589b136adf2445288bb9de..0b06cff477b9d5bc1e7f7f35a840f754707bce7c 100644 (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;
 };