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;
 };
 

Reply via email to