From: Ronan Desplanques <[email protected]>

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.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/cstand.adb                  | 12 +++++++++---
 gcc/ada/einfo.ads                   | 10 ++++++++++
 gcc/ada/exp_strm.adb                |  8 ++++++++
 gcc/ada/gen_il-fields.ads           |  1 +
 gcc/ada/gen_il-gen-gen_entities.adb |  3 ++-
 gcc/ada/gen_il-internals.adb        |  2 ++
 gcc/ada/libgnat/s-stratt.adb        | 17 +++++++++++++++++
 gcc/ada/libgnat/s-stratt.ads        |  2 ++
 gcc/ada/rtsfind.ads                 |  2 ++
 gcc/ada/sem_ch3.adb                 |  6 ++++++
 gcc/ada/treepr.adb                  |  2 ++
 11 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb
index cdf2b5d6c30..8dd169a0dba 100644
--- a/gcc/ada/cstand.adb
+++ b/gcc/ada/cstand.adb
@@ -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;
 
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index b9548a78f84..cd00fe265e1 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -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)
diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb
index 3bb6966dc1c..f933a2e425f 100644
--- a/gcc/ada/exp_strm.adb
+++ b/gcc/ada/exp_strm.adb
@@ -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
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 6cd1355d119..5e954186e05 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -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,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb 
b/gcc/ada/gen_il-gen-gen_entities.adb
index bd091cbe823..95b172ad5f1 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -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
diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb
index 77685f25c6a..bd2d4804c52 100644
--- a/gcc/ada/gen_il-internals.adb
+++ b/gcc/ada/gen_il-internals.adb
@@ -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 =>
diff --git a/gcc/ada/libgnat/s-stratt.adb b/gcc/ada/libgnat/s-stratt.adb
index 844c530af3d..61bfa38f638 100644
--- a/gcc/ada/libgnat/s-stratt.adb
+++ b/gcc/ada/libgnat/s-stratt.adb
@@ -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;
diff --git a/gcc/ada/libgnat/s-stratt.ads b/gcc/ada/libgnat/s-stratt.ads
index 87f1357caaa..9f27f5a8198 100644
--- a/gcc/ada/libgnat/s-stratt.ads
+++ b/gcc/ada/libgnat/s-stratt.ads
@@ -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.
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index c82af1154fe..ee529e122ab 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -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,
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 79986bb48c5..2a42d89d971 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -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
 
diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb
index fbad71a3765..9d789879f11 100644
--- a/gcc/ada/treepr.adb
+++ b/gcc/ada/treepr.adb
@@ -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 =>
-- 
2.51.0

Reply via email to