aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_imgv.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_imgv.adb')
-rw-r--r--gcc/ada/exp_imgv.adb304
1 files changed, 203 insertions, 101 deletions
diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb
index 40cb514..d5db5b3 100644
--- a/gcc/ada/exp_imgv.adb
+++ b/gcc/ada/exp_imgv.adb
@@ -49,11 +49,6 @@ with Urealp; use Urealp;
package body Exp_Imgv is
- function Has_Decimal_Small (E : Entity_Id) return Boolean;
- -- Applies to all entities. True for a Decimal_Fixed_Point_Type, or an
- -- Ordinary_Fixed_Point_Type with a small that is a negative power of ten.
- -- Shouldn't this be in einfo.adb or sem_aux.adb???
-
procedure Rewrite_Object_Image
(N : Node_Id;
Pref : Entity_Id;
@@ -219,21 +214,13 @@ package body Exp_Imgv is
-- xx = Boolean
-- tv = Boolean (Expr)
- -- For signed integer types with size <= Integer'Size
- -- xx = Integer
- -- tv = Integer (Expr)
-
- -- For other signed integer types
- -- xx = Long_Long_Integer
- -- tv = Long_Long_Integer (Expr)
-
- -- For modular types with modulus <= System.Unsigned_Types.Unsigned
- -- xx = Unsigned
- -- tv = System.Unsigned_Types.Unsigned (Expr)
+ -- For signed integer types
+ -- xx = [Long_Long_[Long_]]Integer
+ -- tv = [Long_Long_[Long_]]Integer (Expr)
- -- For other modular integer types
- -- xx = Long_Long_Unsigned
- -- tv = System.Unsigned_Types.Long_Long_Unsigned (Expr)
+ -- For modular types
+ -- xx = [Long_Long_[Long_]]Unsigned
+ -- tv = System.Unsigned_Types.[Long_Long_[Long_]]Unsigned (Expr)
-- For types whose root type is Wide_Character
-- xx = Wide_Character
@@ -249,21 +236,24 @@ package body Exp_Imgv is
-- tv = Long_Long_Float (Expr)
-- pm = typ'Digits (typ = subtype of expression)
- -- For ordinary fixed-point types
+ -- For decimal fixed-point types
+ -- xx = Decimal{32,64,128}
+ -- tv = Integer_{32,64,128} (Expr)? [convert with no scaling]
+ -- pm = typ'Scale (typ = subtype of expression)
+
+ -- For the most common ordinary fixed-point types
+ -- xx = Fixed{32,64,128}
+ -- tv = Integer_{32,64,128} (Expr) [convert with no scaling]
+ -- pm = typ'Small (typ = subtype of expression)
+ -- 1.0 / typ'Small
+ -- (Integer_{32,64,128} x typ'Small)'Fore
+ -- typ'Aft
+
+ -- For other ordinary fixed-point types
-- xx = Ordinary_Fixed_Point
-- tv = Long_Long_Float (Expr)
-- pm = typ'Aft (typ = subtype of expression)
- -- For decimal fixed-point types with size = Integer'Size
- -- xx = Decimal
- -- tv = Integer (Expr)
- -- pm = typ'Scale (typ = subtype of expression)
-
- -- For decimal fixed-point types with size > Integer'Size
- -- xx = Long_Long_Decimal
- -- tv = Long_Long_Integer?(Expr) [convert with no scaling]
- -- pm = typ'Scale (typ = subtype of expression)
-
-- For enumeration types other than those declared in package Standard
-- or System, Snn, Pnn, are expanded as above, but the call looks like:
@@ -593,18 +583,50 @@ package body Exp_Imgv is
Tent := RTE (RE_Long_Long_Long_Unsigned);
end if;
- elsif Is_Fixed_Point_Type (Rtyp) and then Has_Decimal_Small (Rtyp) then
- if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
- Imid := RE_Image_Decimal;
- Tent := Standard_Integer;
+ elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
+ if Esize (Rtyp) <= 32 then
+ Imid := RE_Image_Decimal32;
+ Tent := RTE (RE_Integer_32);
+ elsif Esize (Rtyp) <= 64 then
+ Imid := RE_Image_Decimal64;
+ Tent := RTE (RE_Integer_64);
else
- Imid := RE_Image_Long_Long_Decimal;
- Tent := Standard_Long_Long_Integer;
+ Imid := RE_Image_Decimal128;
+ Tent := RTE (RE_Integer_128);
end if;
elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
- Imid := RE_Image_Ordinary_Fixed_Point;
- Tent := Standard_Long_Long_Float;
+ declare
+ Num : constant Uint := Norm_Num (Small_Value (Rtyp));
+ Den : constant Uint := Norm_Den (Small_Value (Rtyp));
+ Max : constant Uint := UI_Max (Num, Den);
+ Min : constant Uint := UI_Min (Num, Den);
+ Siz : constant Uint := Esize (Rtyp);
+
+ begin
+ if Siz <= 32
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 31
+ then
+ Imid := RE_Image_Fixed32;
+ Tent := RTE (RE_Integer_32);
+ elsif Siz <= 64
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 63
+ then
+ Imid := RE_Image_Fixed64;
+ Tent := RTE (RE_Integer_64);
+ elsif System_Max_Integer_Size = 128
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 127
+ then
+ Imid := RE_Image_Fixed128;
+ Tent := RTE (RE_Integer_128);
+ else
+ Imid := RE_Image_Ordinary_Fixed_Point;
+ Tent := Standard_Long_Long_Float;
+ end if;
+ end;
elsif Is_Floating_Point_Type (Rtyp) then
Imid := RE_Image_Floating_Point;
@@ -746,29 +768,45 @@ package body Exp_Imgv is
Prefix => New_Occurrence_Of (Ptyp, Loc),
Attribute_Name => Name_Digits));
- -- For ordinary fixed-point types, append Aft parameter
+ -- For decimal, append Scale and also set to do literal conversion
- elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
- Append_To (Arg_List,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_Aft));
+ elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
+ Set_Conversion_OK (First (Arg_List));
+
+ Append_To (Arg_List, Make_Integer_Literal (Loc, Scale_Value (Ptyp)));
- if Has_Decimal_Small (Rtyp) then
+ -- For ordinary fixed-point types, append Num, Den, Fore, Aft parameters
+ -- and also set to do literal conversion.
+
+ elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
+ if Imid /= RE_Image_Ordinary_Fixed_Point then
Set_Conversion_OK (First (Arg_List));
- Set_Etype (First (Arg_List), Tent);
- end if;
- -- For decimal, append Scale and also set to do literal conversion
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Num (Small_Value (Ptyp))));
- elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
- Append_To (Arg_List,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_Scale));
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Den (Small_Value (Ptyp))));
- Set_Conversion_OK (First (Arg_List));
- Set_Etype (First (Arg_List), Tent);
+ -- We want to compute the Fore value for the fixed point type
+ -- whose mantissa type is Tent and whose small is typ'Small.
+
+ declare
+ T : Ureal := Uint_2 ** (Esize (Tent) - 1) * Small_Value (Ptyp);
+ F : Nat := 2;
+
+ begin
+ while T >= Ureal_10 loop
+ F := F + 1;
+ T := T / Ureal_10;
+ end loop;
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, UI_From_Int (F)));
+ end;
+ end if;
+
+ Append_To (Arg_List, Make_Integer_Literal (Loc, Aft_Value (Ptyp)));
-- For Wide_Character, append Ada 2005 indication
@@ -827,35 +865,29 @@ package body Exp_Imgv is
-- For types whose root type is Boolean
-- xx = Boolean
- -- For signed integer types with size <= Integer'Size
- -- xx = Integer
-
- -- For other signed integer types
- -- xx = Long_Long_Integer
-
- -- For modular types with modulus <= System.Unsigned_Types.Unsigned
- -- xx = Unsigned
+ -- For signed integer types
+ -- xx = [Long_Long_[Long_]]Integer
- -- For other modular integer types
- -- xx = Long_Long_Unsigned
+ -- For modular types
+ -- xx = [Long_Long_[Long_]]Unsigned
- -- For floating-point types and ordinary fixed-point types
+ -- For floating-point types
-- xx = Real
- -- For Wide_[Wide_]Character types, typ'Value (X) expands into:
+ -- For decimal fixed-point types, typ'Value (X) expands into
- -- btyp (Value_xx (X, EM))
+ -- btyp?(Value_Decimal{32,64,128} (X, typ'Scale));
- -- where btyp is the base type of the prefix, and EM is the encoding method
+ -- For the most common ordinary fixed-point types
- -- For decimal types with size <= Integer'Size, typ'Value (X)
- -- expands into
+ -- btyp?(Value_Fixed{32,64,128} (X, S, 1.0 / S));
+ -- where S = typ'Small
- -- btyp?(Value_Decimal (X, typ'Scale));
+ -- For Wide_[Wide_]Character types, typ'Value (X) expands into:
- -- For all other decimal types, typ'Value (X) expands into
+ -- btyp (Value_xx (X, EM))
- -- btyp?(Value_Long_Long_Decimal (X, typ'Scale))
+ -- where btyp is the base type of the prefix, and EM is the encoding method
-- For enumeration types other than those derived from types Boolean,
-- Character, Wide_[Wide_]Character in Standard, typ'Value (X) expands to:
@@ -923,16 +955,15 @@ package body Exp_Imgv is
end if;
elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
- if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
- Vid := RE_Value_Decimal;
+ if Esize (Rtyp) <= 32 and then abs (Scale_Value (Rtyp)) <= 9 then
+ Vid := RE_Value_Decimal32;
+ elsif Esize (Rtyp) <= 64 and then abs (Scale_Value (Rtyp)) <= 18 then
+ Vid := RE_Value_Decimal64;
else
- Vid := RE_Value_Long_Long_Decimal;
+ Vid := RE_Value_Decimal128;
end if;
- Append_To (Args,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Typ, Loc),
- Attribute_Name => Name_Scale));
+ Append_To (Args, Make_Integer_Literal (Loc, Scale_Value (Rtyp)));
Rewrite (N,
OK_Convert_To (Btyp,
@@ -944,7 +975,54 @@ package body Exp_Imgv is
Analyze_And_Resolve (N, Btyp);
return;
- elsif Is_Real_Type (Rtyp) then
+ elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
+ declare
+ Num : constant Uint := Norm_Num (Small_Value (Rtyp));
+ Den : constant Uint := Norm_Den (Small_Value (Rtyp));
+ Max : constant Uint := UI_Max (Num, Den);
+ Min : constant Uint := UI_Min (Num, Den);
+ Siz : constant Uint := Esize (Rtyp);
+
+ begin
+ if Siz <= 32
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 31
+ then
+ Vid := RE_Value_Fixed32;
+ elsif Siz <= 64
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 63
+ then
+ Vid := RE_Value_Fixed64;
+ elsif System_Max_Integer_Size = 128
+ and then Min = Uint_1
+ and then Max <= Uint_2 ** 127
+ then
+ Vid := RE_Value_Fixed128;
+ else
+ Vid := RE_Value_Real;
+ end if;
+
+ if Vid /= RE_Value_Real then
+ Append_To (Args,
+ Make_Integer_Literal (Loc, -Norm_Num (Small_Value (Rtyp))));
+
+ Append_To (Args,
+ Make_Integer_Literal (Loc, -Norm_Den (Small_Value (Rtyp))));
+
+ Rewrite (N,
+ OK_Convert_To (Btyp,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (RTE (Vid), Loc),
+ Parameter_Associations => Args)));
+
+ Set_Etype (N, Btyp);
+ Analyze_And_Resolve (N, Btyp);
+ return;
+ end if;
+ end;
+
+ elsif Is_Floating_Point_Type (Rtyp) then
Vid := RE_Value_Real;
-- Only other possibility is user-defined enumeration type
@@ -1286,12 +1364,12 @@ package body Exp_Imgv is
-- yy = Boolean
-- For signed integer types
- -- xx = Width_Long_Long_Integer
- -- yy = Long_Long_Integer
+ -- xx = Width_[Long_Long_[Long_]]Integer
+ -- yy = [Long_Long_[Long_]]Integer
-- For modular integer types
- -- xx = Width_Long_Long_Unsigned
- -- yy = Long_Long_Unsigned
+ -- xx = Width_[Long_Long_[Long_]]Unsigned
+ -- yy = [Long_Long_[Long_]]Unsigned
-- For types derived from Wide_Character, typ'Width expands into
@@ -1329,7 +1407,11 @@ package body Exp_Imgv is
-- Wide_Wide_Character (typ'First),
-- Wide_Wide_Character (typ'Last));
- -- For real types, typ'Width and typ'Wide_[Wide_]Width expand into
+ -- For fixed point types, typ'Width and typ'Wide_[Wide_]Width expand into
+
+ -- if Ptyp'First > Ptyp'Last then 0 else Ptyp'Fore + 1 + Ptyp'Aft end if
+
+ -- and for floating point types, they expand into
-- if Ptyp'First > Ptyp'Last then 0 else btyp'Width end if
@@ -1451,9 +1533,41 @@ package body Exp_Imgv is
YY := RTE (RE_Long_Long_Long_Unsigned);
end if;
- -- Real types
+ -- Fixed point types
- elsif Is_Real_Type (Rtyp) then
+ elsif Is_Fixed_Point_Type (Rtyp) then
+ Rewrite (N,
+ Make_If_Expression (Loc,
+ Expressions => New_List (
+
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_First),
+
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Last)),
+
+ Make_Integer_Literal (Loc, 0),
+
+ Make_Op_Add (Loc,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Fore),
+
+ Make_Op_Add (Loc,
+ Make_Integer_Literal (Loc, 1),
+ Make_Integer_Literal (Loc, Aft_Value (Ptyp)))))));
+
+ Analyze_And_Resolve (N, Typ);
+ return;
+
+ -- Floating point types
+
+ elsif Is_Floating_Point_Type (Rtyp) then
Rewrite (N,
Make_If_Expression (Loc,
Expressions => New_List (
@@ -1680,18 +1794,6 @@ package body Exp_Imgv is
Analyze_And_Resolve (N, Typ);
end Expand_Width_Attribute;
- -----------------------
- -- Has_Decimal_Small --
- -----------------------
-
- function Has_Decimal_Small (E : Entity_Id) return Boolean is
- begin
- return Is_Decimal_Fixed_Point_Type (E)
- or else
- (Is_Ordinary_Fixed_Point_Type (E)
- and then Ureal_10**Aft_Value (E) * Small_Value (E) = Ureal_1);
- end Has_Decimal_Small;
-
--------------------------
-- Rewrite_Object_Image --
--------------------------