[Ada] Fix internal error on fixed-point divide, multiply and scaling
gcc/ada/ * exp_fixd.adb (Get_Size_For_Value): New function returning a size suitable for a non-negative integer value. (Get_Type_For_Size): New function returning a standard type suitable for a size. (Build_Divide): Call both functions to compute the result type, but make sure to pass a non-negative value to the first. (Build_Multiply): Likewise. (Do_Multiply_Fixed_Universal): Minor consistency tweak. (Integer_Literal): Call both functions to compute the type.
This commit is contained in:
parent
939b3a2ac6
commit
cea83351a2
@ -190,6 +190,15 @@ package body Exp_Fixd is
|
||||
-- The expression returned is neither analyzed nor resolved. The Etype
|
||||
-- of the result is properly set (to Universal_Real).
|
||||
|
||||
function Get_Size_For_Value (V : Uint) return Pos;
|
||||
-- Given a non-negative universal integer value, return the size of a small
|
||||
-- signed integer type covering -V .. V, or Pos'Max if no such type exists.
|
||||
|
||||
function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id;
|
||||
-- Return the smallest signed integer type containing at least Siz bits.
|
||||
-- If no such type exists, return Empty if Force is False or the largest
|
||||
-- signed integer type if Force is True.
|
||||
|
||||
function Integer_Literal
|
||||
(N : Node_Id;
|
||||
V : Uint;
|
||||
@ -324,7 +333,6 @@ package body Exp_Fixd is
|
||||
Right_Type : constant Entity_Id := Base_Type (Etype (R));
|
||||
Left_Size : Int;
|
||||
Right_Size : Int;
|
||||
Rsize : Int;
|
||||
Result_Type : Entity_Id;
|
||||
Rnode : Node_Id;
|
||||
|
||||
@ -354,20 +362,17 @@ package body Exp_Fixd is
|
||||
-- the effective size of an operand is the RM_Size of the operand.
|
||||
-- But a special case arises with operands whose size is known at
|
||||
-- compile time. In this case, we can use the actual value of the
|
||||
-- operand to get its size if it would fit in signed 8/16/32 bits.
|
||||
-- operand to get a size if it would fit in a small signed integer.
|
||||
|
||||
Left_Size := UI_To_Int (RM_Size (Left_Type));
|
||||
|
||||
if Compile_Time_Known_Value (L) then
|
||||
declare
|
||||
Val : constant Uint := Expr_Value (L);
|
||||
Siz : constant Int :=
|
||||
Get_Size_For_Value (UI_Abs (Expr_Value (L)));
|
||||
begin
|
||||
if Val < Uint_2 ** 7 then
|
||||
Left_Size := 8;
|
||||
elsif Val < Uint_2 ** 15 then
|
||||
Left_Size := 16;
|
||||
elsif Val < Uint_2 ** 31 then
|
||||
Left_Size := 32;
|
||||
if Siz < Left_Size then
|
||||
Left_Size := Siz;
|
||||
end if;
|
||||
end;
|
||||
end if;
|
||||
@ -376,35 +381,19 @@ package body Exp_Fixd is
|
||||
|
||||
if Compile_Time_Known_Value (R) then
|
||||
declare
|
||||
Val : constant Uint := Expr_Value (R);
|
||||
Siz : constant Int :=
|
||||
Get_Size_For_Value (UI_Abs (Expr_Value (R)));
|
||||
begin
|
||||
if Val <= Int'(2 ** 7) then
|
||||
Right_Size := 8;
|
||||
elsif Val <= Int'(2 ** 15) then
|
||||
Right_Size := 16;
|
||||
if Siz < Right_Size then
|
||||
Right_Size := Siz;
|
||||
end if;
|
||||
end;
|
||||
end if;
|
||||
|
||||
-- Do the operation using the longer of the two sizes
|
||||
|
||||
Rsize := Int'Max (Left_Size, Right_Size);
|
||||
|
||||
if Rsize <= 8 then
|
||||
Result_Type := Standard_Integer_8;
|
||||
|
||||
elsif Rsize <= 16 then
|
||||
Result_Type := Standard_Integer_16;
|
||||
|
||||
elsif Rsize <= 32 then
|
||||
Result_Type := Standard_Integer_32;
|
||||
|
||||
elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
|
||||
Result_Type := Standard_Integer_64;
|
||||
|
||||
else
|
||||
Result_Type := Standard_Integer_128;
|
||||
end if;
|
||||
Result_Type :=
|
||||
Get_Type_For_Size (Int'Max (Left_Size, Right_Size), Force => True);
|
||||
|
||||
Rnode :=
|
||||
Make_Op_Divide (Loc,
|
||||
@ -664,7 +653,6 @@ package body Exp_Fixd is
|
||||
Right_Type : constant Entity_Id := Etype (R);
|
||||
Left_Size : Int;
|
||||
Right_Size : Int;
|
||||
Rsize : Int;
|
||||
Result_Type : Entity_Id;
|
||||
Rnode : Node_Id;
|
||||
|
||||
@ -697,20 +685,17 @@ package body Exp_Fixd is
|
||||
-- the effective size of an operand is the RM_Size of the operand.
|
||||
-- But a special case arises with operands whose size is known at
|
||||
-- compile time. In this case, we can use the actual value of the
|
||||
-- operand to get its size if it would fit in signed 8/16/32 bits.
|
||||
-- operand to get a size if it would fit in a small signed integer.
|
||||
|
||||
Left_Size := UI_To_Int (RM_Size (Left_Type));
|
||||
|
||||
if Compile_Time_Known_Value (L) then
|
||||
declare
|
||||
Val : constant Uint := Expr_Value (L);
|
||||
Siz : constant Int :=
|
||||
Get_Size_For_Value (UI_Abs (Expr_Value (L)));
|
||||
begin
|
||||
if Val < Uint_2 ** 7 then
|
||||
Left_Size := 8;
|
||||
elsif Val < Uint_2 ** 15 then
|
||||
Left_Size := 16;
|
||||
elsif Val < Uint_2 ** 31 then
|
||||
Left_Size := 32;
|
||||
if Siz < Left_Size then
|
||||
Left_Size := Siz;
|
||||
end if;
|
||||
end;
|
||||
end if;
|
||||
@ -719,12 +704,11 @@ package body Exp_Fixd is
|
||||
|
||||
if Compile_Time_Known_Value (R) then
|
||||
declare
|
||||
Val : constant Uint := Expr_Value (R);
|
||||
Siz : constant Int :=
|
||||
Get_Size_For_Value (UI_Abs (Expr_Value (R)));
|
||||
begin
|
||||
if Val <= Int'(2 ** 7) then
|
||||
Right_Size := 8;
|
||||
elsif Val <= Int'(2 ** 15) then
|
||||
Right_Size := 16;
|
||||
if Siz < Right_Size then
|
||||
Right_Size := Siz;
|
||||
end if;
|
||||
end;
|
||||
end if;
|
||||
@ -732,23 +716,8 @@ package body Exp_Fixd is
|
||||
-- Now the result size must be at least the sum of the two sizes,
|
||||
-- to accommodate all possible results.
|
||||
|
||||
Rsize := Left_Size + Right_Size;
|
||||
|
||||
if Rsize <= 8 then
|
||||
Result_Type := Standard_Integer_8;
|
||||
|
||||
elsif Rsize <= 16 then
|
||||
Result_Type := Standard_Integer_16;
|
||||
|
||||
elsif Rsize <= 32 then
|
||||
Result_Type := Standard_Integer_32;
|
||||
|
||||
elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
|
||||
Result_Type := Standard_Integer_64;
|
||||
|
||||
else
|
||||
Result_Type := Standard_Integer_128;
|
||||
end if;
|
||||
Result_Type :=
|
||||
Get_Type_For_Size (Left_Size + Right_Size, Force => True);
|
||||
|
||||
Rnode :=
|
||||
Make_Op_Multiply (Loc,
|
||||
@ -1542,7 +1511,7 @@ package body Exp_Fixd is
|
||||
|
||||
else
|
||||
Lit_Int := Integer_Literal (N, Frac_Den, UR_Is_Negative (Frac));
|
||||
Lit_K := Integer_Literal (N, Frac_Num);
|
||||
Lit_K := Integer_Literal (N, Frac_Num, False);
|
||||
|
||||
if Present (Lit_Int) and then Present (Lit_K) then
|
||||
Set_Result (N, Build_Scaled_Divide (N, Left, Lit_K, Lit_Int));
|
||||
@ -2422,6 +2391,64 @@ package body Exp_Fixd is
|
||||
return Build_Conversion (N, Universal_Real, N);
|
||||
end Fpt_Value;
|
||||
|
||||
------------------------
|
||||
-- Get_Size_For_Value --
|
||||
------------------------
|
||||
|
||||
function Get_Size_For_Value (V : Uint) return Pos is
|
||||
begin
|
||||
pragma Assert (V >= Uint_0);
|
||||
|
||||
if V < Uint_2 ** 7 then
|
||||
return 8;
|
||||
|
||||
elsif V < Uint_2 ** 15 then
|
||||
return 16;
|
||||
|
||||
elsif V < Uint_2 ** 31 then
|
||||
return 32;
|
||||
|
||||
elsif V < Uint_2 ** 63 then
|
||||
return 64;
|
||||
|
||||
elsif V < Uint_2 ** 127 then
|
||||
return 128;
|
||||
|
||||
else
|
||||
return Pos'Last;
|
||||
end if;
|
||||
end Get_Size_For_Value;
|
||||
|
||||
-----------------------
|
||||
-- Get_Type_For_Size --
|
||||
-----------------------
|
||||
|
||||
function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id is
|
||||
begin
|
||||
if Siz <= 8 then
|
||||
return Standard_Integer_8;
|
||||
|
||||
elsif Siz <= 16 then
|
||||
return Standard_Integer_16;
|
||||
|
||||
elsif Siz <= 32 then
|
||||
return Standard_Integer_32;
|
||||
|
||||
elsif Siz <= 64
|
||||
or else (Force and then System_Max_Integer_Size < 128)
|
||||
then
|
||||
return Standard_Integer_64;
|
||||
|
||||
elsif (Siz <= 128 and then System_Max_Integer_Size = 128)
|
||||
or else Force
|
||||
then
|
||||
return Standard_Integer_128;
|
||||
|
||||
else
|
||||
return Empty;
|
||||
end if;
|
||||
end Get_Type_For_Size;
|
||||
|
||||
---------------------
|
||||
-- Integer_Literal --
|
||||
---------------------
|
||||
@ -2435,22 +2462,8 @@ package body Exp_Fixd is
|
||||
L : Node_Id;
|
||||
|
||||
begin
|
||||
if V < Uint_2 ** 7 then
|
||||
T := Standard_Integer_8;
|
||||
|
||||
elsif V < Uint_2 ** 15 then
|
||||
T := Standard_Integer_16;
|
||||
|
||||
elsif V < Uint_2 ** 31 then
|
||||
T := Standard_Integer_32;
|
||||
|
||||
elsif V < Uint_2 ** 63 then
|
||||
T := Standard_Integer_64;
|
||||
|
||||
elsif V < Uint_2 ** 127 and then System_Max_Integer_Size = 128 then
|
||||
T := Standard_Integer_128;
|
||||
|
||||
else
|
||||
T := Get_Type_For_Size (Get_Size_For_Value (V), Force => False);
|
||||
if No (T) then
|
||||
return Empty;
|
||||
end if;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user