]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Make Long_Long_Float'Write deterministic
authorRonan Desplanques <desplanques@adacore.com>
Tue, 7 Oct 2025 13:04:46 +0000 (15:04 +0200)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Mon, 3 Nov 2025 14:15:15 +0000 (15:15 +0100)
On some platforms, Long_Long_Float'Size (and Long_Long_Float'Stream_Size)
is 128 but only 80 bits are effectively used. This pack makes it so
'Write in this case write zeros for the padding bits instead of
unspecified values.

gcc/ada/ChangeLog:

* gen_il-fields.ads (Is_IEEE_Extended_Precision): New flag.
* gen_il-gen-gen_entities.adb: Likewise.
* gen_il-internals.adb (Image): Likewise.
* treepr.adb (Image): Likewise.
* einfo.ads: Document new flag.
* cstand.adb (Copy_Float_Type, Register_Float_Type): Use new flag.
* libgnat/s-stratt.ads (W_80IEEE): New procedure.
* libgnat/s-stratt.adb (W_80IEEE): Likewise.
* exp_strm.adb (Get_Primitives): Select new procedure when
appropriate.
* rtsfind.ads: Register new runtime procedure.
* sem_ch3.adb (Build_Derived_Numeric_Type,
Analyze_Subtype_Declaration): Propagate new flag.

gcc/ada/cstand.adb
gcc/ada/einfo.ads
gcc/ada/exp_strm.adb
gcc/ada/gen_il-fields.ads
gcc/ada/gen_il-gen-gen_entities.adb
gcc/ada/gen_il-internals.adb
gcc/ada/libgnat/s-stratt.adb
gcc/ada/libgnat/s-stratt.ads
gcc/ada/rtsfind.ads
gcc/ada/sem_ch3.adb
gcc/ada/treepr.adb

index cdf2b5d6c30656298c9235442d40c1cf31db5bfd..8dd169a0dba86ac85d6e0a2f3f55908c5f3a1ef2 100644 (file)
@@ -298,6 +298,7 @@ package body CStand is
       Build_Float_Type
         (To, UI_To_Int (Digits_Value (From)), Float_Rep (From),
          UI_To_Int (Esize (From)), UI_To_Int (Alignment (From)));
+      Set_Is_IEEE_Extended_Precision (To, Is_IEEE_Extended_Precision (From));
    end Copy_Float_Type;
 
    ----------------------
@@ -2100,17 +2101,22 @@ package body CStand is
       Size      : Positive;
       Alignment : Natural)
    is
-      pragma Unreferenced (Precision);
-      --  See Build_Float_Type for the rationale
-
       Ent : constant Entity_Id := New_Standard_Entity (Name);
 
+      IEEE_Extended_Precision_Size : constant := 80;
    begin
       Set_Defining_Identifier (New_Node (N_Full_Type_Declaration, Stloc), Ent);
       Set_Scope (Ent, Standard_Standard);
       Build_Float_Type
         (Ent, Pos (Digs), Float_Rep, Int (Size), Nat (Alignment / 8));
 
+      --  We mostly disregard Precision, see Build_Float_Type for the
+      --  rationale. The only thing we use it for is to detect 80-bit IEEE
+      --  extended precision, in order to adjust the behavior of 'Write.
+      if Precision = IEEE_Extended_Precision_Size then
+         Set_Is_IEEE_Extended_Precision (Ent);
+      end if;
+
       Append_New_Elmt (Ent, Back_End_Float_Types);
    end Register_Float_Type;
 
index b9548a78f8455942baa0f90ef4d89cef587de068..cd00fe265e154845333ec7e6a818246c81b0e367 100644 (file)
@@ -3552,6 +3552,15 @@ package Einfo is
 --       a wrapper to handle inherited class-wide pre/post conditions that call
 --       overridden primitives or as a wrapper of a controlling function.
 
+--    Is_IEEE_Extended_Precision
+--       Defined in floating point types and subtypes. Indicates that the type
+--       corresponds to the 80-bit IEEE extended precision format. That format
+--       effectively uses 80 bits per value, but we set its Size to a larger
+--       value for the reasons explained in the documentation comment of
+--       Build_Float_Type. We also perform some extra work to consistently set
+--       the extra bits to zero in the 'Write implementation, which is why we
+--       need this flag.
+
 --    Itype_Printed
 --       Defined in all type and subtype entities. Set in Itypes if the Itype
 --       has been printed by Sprint. This is used to avoid printing an Itype
@@ -5529,6 +5538,7 @@ package Einfo is
    --    Digits_Value
    --    Float_Rep                            (Float_Rep_Kind)
    --    Default_Aspect_Value                 (base type only)
+   --    Is_IEEE_Extended_Precision
    --    Scalar_Range
    --    Static_Real_Or_String_Predicate
    --    Machine_Emax_Value                   (synth)
index 3bb6966dc1c237a502ae5993e6d541276f844f55..f933a2e425f735ec64263a3b8865c3a5df92fe8d 100644 (file)
@@ -501,6 +501,14 @@ package body Exp_Strm is
          then
             return Prims (RE_I_LF, RE_W_LF);
 
+         elsif Is_IEEE_Extended_Precision (U_Type) then
+            --  For 80-bit IEEE extended precision values, we use a special
+            --  write routine that sets the unused bytes to zero. The reason
+            --  why we don't set Stream_Size to 80 and stream only the
+            --  meaningful bits is that the user is allowed to select the XDR
+            --  implementation of streaming at bind time, and XDR does not
+            --  allow 80 bits floating point values.
+            return Prims (RE_I_LLF, RE_W_80IEEE);
          elsif P_Size = Standard_Long_Long_Float_Size then
             return Prims (RE_I_LLF, RE_W_LLF);
          else
index 6cd1355d11926899627db582eba4014030b80e71..5e954186e05c202dbbed154072690e9ed3cf3f57 100644 (file)
@@ -818,6 +818,7 @@ package Gen_IL.Fields is
       Is_Volatile_Object,
       Is_Volatile_Full_Access,
       Is_Wrapper,
+      Is_IEEE_Extended_Precision,
       Itype_Printed,
       Kill_Elaboration_Checks,
       Known_To_Have_Preelab_Init,
index bd091cbe823f54d9cbc5c85cf7e03c735fbc7532..95b172ad5f14e304b383655e9bb2566f683812f7 100644 (file)
@@ -630,7 +630,8 @@ begin -- Gen_IL.Gen.Gen_Entities
        --  first named subtype).
 
    Ab (Float_Kind, Real_Kind,
-       (Sm (Digits_Value, Upos)));
+       (Sm (Digits_Value, Upos),
+        Sm (Is_IEEE_Extended_Precision, Flag)));
 
    Cc (E_Floating_Point_Type, Float_Kind);
        --  Floating point type, used for the anonymous base type of the
index 77685f25c6a23352f47c2b2c436e3c08187fdc52..bd2d4804c52b30ecd1e5e9ebe5ebc840c266d237 100644 (file)
@@ -311,6 +311,8 @@ package body Gen_IL.Internals is
             return "Is_Elaboration_Warnings_OK_Id";
          when Is_Elaboration_Warnings_OK_Node =>
             return "Is_Elaboration_Warnings_OK_Node";
+         when Is_IEEE_Extended_Precision =>
+            return "Is_IEEE_Extended_Precision";
          when Is_Known_Guaranteed_ABE =>
             return "Is_Known_Guaranteed_ABE";
          when Is_RACW_Stub_Type =>
index 844c530af3d9c1473674555b069e7c75f9b91dae..61bfa38f638fe14abf03f73df85eefca828bf87b 100644 (file)
@@ -1036,4 +1036,21 @@ package body System.Stream_Attributes is
       Ada.Streams.Write (Stream.all, From_WWC (Item));
    end W_WWC;
 
+   N_IEEE_Extended_Precision_Bytes : constant := 10;
+
+   procedure W_80IEEE (Stream : not null access RST; Item : Long_Long_Float) is
+   begin
+      if XDR_Support then
+         XDR.W_LLF (Stream, Item);
+         return;
+      end if;
+
+      declare
+         X : S_LLF := From_LLF (Item);
+      begin
+         X (N_IEEE_Extended_Precision_Bytes + 1 .. X'Last) := (others => 0);
+         Ada.Streams.Write (Stream.all, X);
+      end;
+   end W_80IEEE;
+
 end System.Stream_Attributes;
index 87f1357caaac6f7f78baa03cbcc064bd044ef69b..9f27f5a819825cd746afe4b6c2849f03ccd18ae8 100644 (file)
@@ -171,6 +171,8 @@ package System.Stream_Attributes is
    procedure W_WC   (Stream : not null access RST; Item : Wide_Character);
    procedure W_WWC  (Stream : not null access RST; Item : Wide_Wide_Character);
 
+   procedure W_80IEEE (Stream : not null access RST; Item : Long_Long_Float);
+
    function Block_IO_OK return Boolean;
    --  Indicate whether the current setting supports block IO. See
    --  System.Strings.Stream_Ops (s-ststop) for details on block IO.
index c82af1154feac784edcafa4c3a6b6bf41527ef97..ee529e122ab44eb482a53283e67b841bc06721f1 100644 (file)
@@ -1900,6 +1900,7 @@ package Rtsfind is
      RE_W_U24,                           -- System.Stream_Attributes
      RE_W_WC,                            -- System.Stream_Attributes
      RE_W_WWC,                           -- System.Stream_Attributes
+     RE_W_80IEEE,                        -- System.Stream_Attributes
 
      RE_Storage_Array_Input,             -- System.Strings.Stream_Ops
      RE_Storage_Array_Input_Blk_IO,      -- System.Strings.Stream_Ops
@@ -3565,6 +3566,7 @@ package Rtsfind is
      RE_W_U24                            => System_Stream_Attributes,
      RE_W_WC                             => System_Stream_Attributes,
      RE_W_WWC                            => System_Stream_Attributes,
+     RE_W_80IEEE                         => System_Stream_Attributes,
 
      RE_Storage_Array_Input              => System_Strings_Stream_Ops,
      RE_Storage_Array_Input_Blk_IO       => System_Strings_Stream_Ops,
index 79986bb48c5ccb5715abf02f0e2fb817b5d1affe..2a42d89d9710dc696f0f14bcb3a52999716c354c 100644 (file)
@@ -5944,6 +5944,8 @@ package body Sem_Ch3 is
                Set_Scalar_Range         (Id, Scalar_Range       (T));
                Set_Digits_Value         (Id, Digits_Value       (T));
                Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_Is_IEEE_Extended_Precision
+                 (Id, Is_IEEE_Extended_Precision (T));
 
                --  If the floating point type has dimensions, these will be
                --  inherited subsequently when Analyze_Dimensions is called.
@@ -8206,10 +8208,14 @@ package body Sem_Ch3 is
 
          Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base));
          Set_Float_Rep    (Implicit_Base, Float_Rep    (Parent_Base));
+         Set_Is_IEEE_Extended_Precision
+           (Implicit_Base, Is_IEEE_Extended_Precision (Parent_Base));
 
          if No_Constraint then
             Set_Digits_Value (Derived_Type, Digits_Value (Parent_Type));
          end if;
+         Set_Is_IEEE_Extended_Precision
+           (Derived_Type, Is_IEEE_Extended_Precision (Parent_Base));
 
       elsif Is_Fixed_Point_Type (Parent_Type) then
 
index fbad71a3765a1b1a2a6880d51b3c543240e75530..9d789879f11d1a3bc203ee0d13e020c9d386ad02 100644 (file)
@@ -338,6 +338,8 @@ package body Treepr is
             return "Is_Elaboration_Checks_OK_Id";
          when F_Is_Elaboration_Warnings_OK_Id =>
             return "Is_Elaboration_Warnings_OK_Id";
+         when F_Is_IEEE_Extended_Precision =>
+            return "Is_IEEE_Extended_Precision";
          when F_Is_RACW_Stub_Type =>
             return "Is_RACW_Stub_Type";
          when F_LSP_Subprogram =>