diff options
Diffstat (limited to 'gcc/ada/exp_fixd.adb')
-rw-r--r-- | gcc/ada/exp_fixd.adb | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb index 79f43b102a6..41158104beb 100644 --- a/gcc/ada/exp_fixd.adb +++ b/gcc/ada/exp_fixd.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2001 Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2002 Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -30,7 +30,6 @@ with Einfo; use Einfo; with Exp_Util; use Exp_Util; with Nlists; use Nlists; with Nmake; use Nmake; -with Restrict; use Restrict; with Rtsfind; use Rtsfind; with Sem; use Sem; with Sem_Eval; use Sem_Eval; @@ -39,7 +38,6 @@ with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Stand; use Stand; with Tbuild; use Tbuild; -with Ttypes; use Ttypes; with Uintp; use Uintp; with Urealp; use Urealp; @@ -403,13 +401,6 @@ package body Exp_Fixd is Expr : Node_Id; begin - if Y_Size > System_Word_Size - or else - Z_Size > System_Word_Size - then - Disallow_In_No_Run_Time_Mode (N); - end if; - -- If denominator fits in 64 bits, we can build the operations directly -- without causing any intermediate overflow, so that's what we do! @@ -606,6 +597,8 @@ package body Exp_Fixd is Loc : constant Source_Ptr := Sloc (N); Left_Type : constant Entity_Id := Etype (L); Right_Type : constant Entity_Id := Etype (R); + Left_Size : Int; + Right_Size : Int; Rsize : Int; Result_Type : Entity_Id; Rnode : Node_Id; @@ -634,11 +627,54 @@ package body Exp_Fixd is return R; end if; - -- Otherwise we use a type that is at least twice the longer - -- of the two sizes. + -- Otherwise we need to figure out the correct result type size + -- First figure out the effective sizes of the operands. Normally + -- 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 8 or 16 bits. + + -- Note: if both operands are known at compile time (can that + -- happen?) and both were equal to the power of 2, then we would + -- be one bit off in this test, so for the left operand, we only + -- go up to the power of 2 - 1. This ensures that we do not get + -- this anomolous case, and in practice the right operand is by + -- far the more likely one to be the constant. + + Left_Size := UI_To_Int (RM_Size (Left_Type)); + + if Compile_Time_Known_Value (L) then + declare + Val : constant Uint := Expr_Value (L); + + begin + if Val < Int'(2 ** 8) then + Left_Size := 8; + elsif Val < Int'(2 ** 16) then + Left_Size := 16; + end if; + end; + end if; + + Right_Size := UI_To_Int (RM_Size (Right_Type)); + + if Compile_Time_Known_Value (R) then + declare + Val : constant Uint := Expr_Value (R); + + begin + if Val <= Int'(2 ** 8) then + Right_Size := 8; + elsif Val <= Int'(2 ** 16) then + Right_Size := 16; + end if; + end; + end if; + + -- Now the result size must be at least twice the longer of + -- the two sizes, to accomodate all possible results. - Rsize := 2 * Int'Max (UI_To_Int (Esize (Left_Type)), - UI_To_Int (Esize (Right_Type))); + Rsize := 2 * Int'Max (Left_Size, Right_Size); if Rsize <= 8 then Result_Type := Standard_Integer_8; @@ -650,10 +686,6 @@ package body Exp_Fixd is Result_Type := Standard_Integer_32; else - if Rsize > System_Word_Size then - Disallow_In_No_Run_Time_Mode (N); - end if; - Result_Type := Standard_Integer_64; end if; @@ -2309,7 +2341,6 @@ package body Exp_Fixd is Set_Analyzed (L); return L; - end Integer_Literal; ------------------ |