summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_fixd.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_fixd.adb')
-rw-r--r--gcc/ada/exp_fixd.adb69
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;
------------------