Typ : constant Entity_Id := Etype (N);
DDC : constant Boolean := Do_Division_Check (N);
+ Is_Stoele_Mod : constant Boolean :=
+ Is_RTE (First_Subtype (Typ), RE_Storage_Offset)
+ and then Nkind (Left_Opnd (N)) = N_Unchecked_Type_Conversion
+ and then Is_RTE (Etype (Expression (Left_Opnd (N))), RE_Address);
+ -- True if this is the special mod operator of System.Storage_Elements
+
Left : Node_Id;
Right : Node_Id;
end if;
end if;
- if Is_Integer_Type (Typ) then
+ -- For the special mod operator of System.Storage_Elements, the checks
+ -- are subsumed into the handling of the negative case below.
+
+ if Is_Integer_Type (Typ) and then not Is_Stoele_Mod then
Apply_Divide_Checks (N);
-- All done if we don't have a MOD any more, which can happen as a
return;
end if;
+ -- The negative case makes no sense since it is a case of a mod where
+ -- the left argument is unsigned and the right argument is signed. In
+ -- accordance with the (spirit of the) permission of RM 13.7.1(16),
+ -- we raise CE, and also include the zero case here. Yes, the RM says
+ -- PE, but this really is so obviously more like a constraint error.
+
+ if Is_Stoele_Mod and then (not ROK or else Rlo <= 0) then
+ Insert_Action (N,
+ Make_Raise_Constraint_Error (Loc,
+ Condition =>
+ Make_Op_Le (Loc,
+ Left_Opnd => Duplicate_Subexpr_No_Checks (Right),
+ Right_Opnd => Make_Integer_Literal (Loc, 0)),
+ Reason => CE_Overflow_Check_Failed));
+ return;
+ end if;
+
-- If we still have a mod operator and we are in Modify_Tree_For_C
-- mode, and we have a signed integer type, then here is where we do
-- the rewrite in terms of Rem. Note this rewrite bypasses the need
-- N_Free_Statement and appropriate context.
procedure Expand_To_Address (N : Node_Id);
+ -- Expand a call to corresponding function from System.Storage_Elements or
+ -- declared in an instance of System.Address_To_Access_Conversions.
+
+ procedure Expand_To_Integer (N : Node_Id);
+ -- Expand a call to corresponding function from System.Storage_Elements
+
procedure Expand_To_Pointer (N : Node_Id);
-- Expand a call to corresponding function, declared in an instance of
-- System.Address_To_Access_Conversions.
elsif Nam = Name_To_Address then
Expand_To_Address (N);
+ elsif Nam = Name_To_Integer then
+ Expand_To_Integer (N);
+
elsif Nam = Name_To_Pointer then
Expand_To_Pointer (N);
Obj : Node_Id;
begin
+ if Is_Modular_Integer_Type (Etype (Arg)) then
+ Rewrite (N, Unchecked_Convert_To (Etype (N), Arg));
+ Analyze (N);
+ return;
+ end if;
+
Remove_Side_Effects (Arg);
Obj := Make_Explicit_Dereference (Loc, Relocate_Node (Arg));
Analyze_And_Resolve (N, RTE (RE_Address));
end Expand_To_Address;
+ -----------------------
+ -- Expand_To_Integer --
+ -----------------------
+
+ procedure Expand_To_Integer (N : Node_Id) is
+ Arg : constant Node_Id := First_Actual (N);
+
+ begin
+ Rewrite (N, Unchecked_Convert_To (Etype (N), Arg));
+ Analyze (N);
+ end Expand_To_Integer;
+
-----------------------
-- Expand_To_Pointer --
-----------------------
-- --
------------------------------------------------------------------------------
--- This package does not require a body, since it is a package renaming. We
--- provide a dummy file containing a No_Body pragma so that previous versions
--- of the body (which did exist) will not interfere.
+-- This package does not require a body. We provide a dummy file containing a
+-- No_Body pragma so that previous versions of the body (which did exist) will
+-- not interfere.
pragma No_Body;
-- --
------------------------------------------------------------------------------
-with Ada.Unchecked_Conversion;
+-- This package does not require a body. We provide a dummy file containing a
+-- No_Body pragma so that previous versions of the body (which did exist) will
+-- not interfere.
-package body System.Storage_Elements is
-
- pragma Suppress (All_Checks);
-
- -- Conversion to/from address
-
- -- Note qualification below of To_Address to avoid ambiguities systems
- -- where Address is a visible integer type.
-
- function To_Address is
- new Ada.Unchecked_Conversion (Storage_Offset, Address);
- function To_Offset is
- new Ada.Unchecked_Conversion (Address, Storage_Offset);
-
- -- Conversion to/from integers
-
- -- These functions must be place first because they are inlined_always
- -- and are used and inlined in other subprograms defined in this unit.
-
- ----------------
- -- To_Address --
- ----------------
-
- function To_Address (Value : Integer_Address) return Address is
- begin
- return Address (Value);
- end To_Address;
-
- ----------------
- -- To_Integer --
- ----------------
-
- function To_Integer (Value : Address) return Integer_Address is
- begin
- return Integer_Address (Value);
- end To_Integer;
-
- -- Address arithmetic
-
- ---------
- -- "+" --
- ---------
-
- function "+" (Left : Address; Right : Storage_Offset) return Address is
- begin
- return Storage_Elements.To_Address
- (To_Integer (Left) + To_Integer (To_Address (Right)));
- end "+";
-
- function "+" (Left : Storage_Offset; Right : Address) return Address is
- begin
- return Storage_Elements.To_Address
- (To_Integer (To_Address (Left)) + To_Integer (Right));
- end "+";
-
- ---------
- -- "-" --
- ---------
-
- function "-" (Left : Address; Right : Storage_Offset) return Address is
- begin
- return Storage_Elements.To_Address
- (To_Integer (Left) - To_Integer (To_Address (Right)));
- end "-";
-
- function "-" (Left, Right : Address) return Storage_Offset is
- begin
- return To_Offset (Storage_Elements.To_Address
- (To_Integer (Left) - To_Integer (Right)));
- end "-";
-
- -----------
- -- "mod" --
- -----------
-
- function "mod"
- (Left : Address;
- Right : Storage_Offset) return Storage_Offset
- is
- begin
- if Right > 0 then
- return Storage_Offset
- (To_Integer (Left) mod Integer_Address (Right));
-
- -- The negative case makes no sense since it is a case of a mod where
- -- the left argument is unsigned and the right argument is signed. In
- -- accordance with the (spirit of the) permission of RM 13.7.1(16),
- -- we raise CE, and also include the zero case here. Yes, the RM says
- -- PE, but this really is so obviously more like a constraint error.
-
- else
- raise Constraint_Error;
- end if;
- end "mod";
-
-end System.Storage_Elements;
+pragma No_Body;
pragma Annotate (GNATprove, Always_Return, Storage_Elements);
- -- We also add the pragma Pure_Function to the operations in this package,
- -- because otherwise functions with parameters derived from Address are
- -- treated as non-pure by the back-end (see exp_ch6.adb). This is because
- -- in many cases such a parameter is used to hide read/out access to
- -- objects, and it would be unsafe to treat such functions as pure.
-
type Storage_Offset is range
-(2 ** (Integer'(Standard'Address_Size) - 1)) ..
+(2 ** (Integer'(Standard'Address_Size) - 1)) - Long_Long_Integer'(1);
-- Address arithmetic
function "+" (Left : Address; Right : Storage_Offset) return Address;
- pragma Convention (Intrinsic, "+");
- pragma Inline_Always ("+");
- pragma Pure_Function ("+");
-
function "+" (Left : Storage_Offset; Right : Address) return Address;
- pragma Convention (Intrinsic, "+");
- pragma Inline_Always ("+");
- pragma Pure_Function ("+");
+ pragma Import (Intrinsic, "+");
function "-" (Left : Address; Right : Storage_Offset) return Address;
- pragma Convention (Intrinsic, "-");
- pragma Inline_Always ("-");
- pragma Pure_Function ("-");
-
function "-" (Left, Right : Address) return Storage_Offset;
- pragma Convention (Intrinsic, "-");
- pragma Inline_Always ("-");
- pragma Pure_Function ("-");
+ pragma Import (Intrinsic, "-");
function "mod"
(Left : Address;
- Right : Storage_Offset) return Storage_Offset;
- pragma Convention (Intrinsic, "mod");
- pragma Inline_Always ("mod");
- pragma Pure_Function ("mod");
+ Right : Storage_Offset) return Storage_Offset;
+ pragma Import (Intrinsic, "mod");
-- Conversion to/from integers
type Integer_Address is mod Memory_Size;
function To_Address (Value : Integer_Address) return Address;
- pragma Convention (Intrinsic, To_Address);
- pragma Inline_Always (To_Address);
- pragma Pure_Function (To_Address);
+ pragma Import (Intrinsic, To_Address);
function To_Integer (Value : Address) return Integer_Address;
- pragma Convention (Intrinsic, To_Integer);
- pragma Inline_Always (To_Integer);
- pragma Pure_Function (To_Integer);
+ pragma Import (Intrinsic, To_Integer);
end System.Storage_Elements;
if No (Actual_Subp) then
if Is_Intrinsic_Subprogram (Parent_Subp) then
+ Set_Convention (New_Subp, Convention_Intrinsic);
Set_Is_Intrinsic_Subprogram (New_Subp);
if Present (Alias (Parent_Subp))
-- Start of processing for Resolve_Arithmetic_Op
begin
- if Comes_From_Source (N)
- and then Ekind (Entity (N)) = E_Function
+ if Ekind (Entity (N)) = E_Function
and then Is_Imported (Entity (N))
and then Is_Intrinsic_Subprogram (Entity (N))
then
+ Generate_Reference (Entity (N), N);
Resolve_Intrinsic_Operator (N, Typ);
return;
--------------------------------
procedure Resolve_Intrinsic_Operator (N : Node_Id; Typ : Entity_Id) is
- Btyp : constant Entity_Id := Base_Type (Underlying_Type (Typ));
+ Btyp : constant Entity_Id := Implementation_Base_Type (Typ);
Op : Entity_Id;
Arg1 : Node_Id;
Arg2 : Node_Id;
end if;
end if;
- if Comes_From_Source (N)
- and then Ekind (Entity (N)) = E_Function
+ if Ekind (Entity (N)) = E_Function
and then Is_Imported (Entity (N))
and then Is_Intrinsic_Subprogram (Entity (N))
then
+ Generate_Reference (Entity (N), N);
Resolve_Intrinsic_Operator (N, Typ);
return;
end if;
Name_Shift_Right : constant Name_Id := N + $;
Name_Shift_Right_Arithmetic : constant Name_Id := N + $;
Name_Source_Location : constant Name_Id := N + $;
+ Name_To_Integer : constant Name_Id := N + $;
+ Name_To_Pointer : constant Name_Id := N + $;
Name_Unchecked_Conversion : constant Name_Id := N + $;
Name_Unchecked_Deallocation : constant Name_Id := N + $;
- Name_To_Pointer : constant Name_Id := N + $;
Last_Intrinsic_Name : constant Name_Id := N + $;
-- Names used in processing intrinsic calls