Commit b0d71355 by Hristian Kirtchev Committed by Arnaud Charlet

exp_ch4.adb (Insert_Dereference_Action): Reimplemented.

2012-05-15  Hristian Kirtchev  <kirtchev@adacore.com>

	* exp_ch4.adb (Insert_Dereference_Action): Reimplemented. The
	routine performs address and size adjustments for dereferences
	of heap-allocated controlled objects. This manipulation is needed
	in order to restore the original state of the memory at the time
	it was allocated by the finalization machinery.
	* rtsfind.ads: Add RE_Adjust_Controlled_Dereference to tables
	RE_Id and RE_Unit_Table.
	* sinfo.adb (Has_Dereference_Action): New routine.
	(Set_Has_Dereference_Action): New routine.
	* sinfo.ads: Add new semantic flag Has_Dereference_Action along
	its association in nodes.
	(Has_Dereference_Action): New routine and pragma Inline.
	(Set_Has_Dereference_Action): New routine and pragma Inline.
	* s-stposu.ads, s-stposu.adb (Adjust_Controlled_Dereference): New
	routine.

From-SVN: r187530
parent 5b5b27ad
2012-05-15 Hristian Kirtchev <kirtchev@adacore.com>
* exp_ch4.adb (Insert_Dereference_Action): Reimplemented. The
routine performs address and size adjustments for dereferences
of heap-allocated controlled objects. This manipulation is needed
in order to restore the original state of the memory at the time
it was allocated by the finalization machinery.
* rtsfind.ads: Add RE_Adjust_Controlled_Dereference to tables
RE_Id and RE_Unit_Table.
* sinfo.adb (Has_Dereference_Action): New routine.
(Set_Has_Dereference_Action): New routine.
* sinfo.ads: Add new semantic flag Has_Dereference_Action along
its association in nodes.
(Has_Dereference_Action): New routine and pragma Inline.
(Set_Has_Dereference_Action): New routine and pragma Inline.
* s-stposu.ads, s-stposu.adb (Adjust_Controlled_Dereference): New
routine.
2012-05-15 Thomas Quinot <quinot@adacore.com>
* uintp.adb (Image_Uint): Use UI_Div_Rem to get quotient and
......
......@@ -10117,11 +10117,6 @@ package body Exp_Ch4 is
-------------------------------
procedure Insert_Dereference_Action (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
Pnod : constant Node_Id := Parent (N);
function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
-- Return true if type of P is derived from Checked_Pool;
......@@ -10149,57 +10144,172 @@ package body Exp_Ch4 is
return False;
end Is_Checked_Storage_Pool;
-- Local variables
Typ : constant Entity_Id := Etype (N);
Desig : constant Entity_Id := Available_View (Designated_Type (Typ));
Loc : constant Source_Ptr := Sloc (N);
Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
Pnod : constant Node_Id := Parent (N);
Addr : Entity_Id;
Alig : Entity_Id;
Deref : Node_Id;
Size : Entity_Id;
Stmt : Node_Id;
-- Start of processing for Insert_Dereference_Action
begin
pragma Assert (Nkind (Pnod) = N_Explicit_Dereference);
if not (Is_Checked_Storage_Pool (Pool)
and then Comes_From_Source (Original_Node (Pnod)))
then
-- Do not re-expand a dereference which has already been processed by
-- this routine.
if Has_Dereference_Action (Pnod) then
return;
end if;
Insert_Action (N,
Make_Procedure_Call_Statement (Loc,
Name => New_Reference_To (
Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
-- Do not perform this type of expansion for internally-generated
-- dereferences.
Parameter_Associations => New_List (
elsif not Comes_From_Source (Original_Node (Pnod)) then
return;
-- Pool
-- A dereference action is only applicable to objects which have been
-- allocated on a checked pool.
New_Reference_To (Pool, Loc),
elsif not Is_Checked_Storage_Pool (Pool) then
return;
end if;
-- Storage_Address. We use the attribute Pool_Address, which uses
-- the pointer itself to find the address of the object, and which
-- handles unconstrained arrays properly by computing the address
-- of the template. i.e. the correct address of the corresponding
-- allocation.
-- Extract the address of the dereferenced object. Generate:
-- Addr : System.Address := <N>'Pool_Address;
Make_Attribute_Reference (Loc,
Prefix => Duplicate_Subexpr_Move_Checks (N),
Attribute_Name => Name_Pool_Address),
Addr := Make_Temporary (Loc, 'P');
-- Size_In_Storage_Elements
Insert_Action (N,
Make_Object_Declaration (Loc,
Defining_Identifier => Addr,
Object_Definition =>
New_Reference_To (RTE (RE_Address), Loc),
Expression =>
Make_Attribute_Reference (Loc,
Prefix => Duplicate_Subexpr_Move_Checks (N),
Attribute_Name => Name_Pool_Address)));
-- Calculate the size of the dereferenced object. Generate:
-- Size : Storage_Count := <N>.all'Size / Storage_Unit;
Deref :=
Make_Explicit_Dereference (Loc,
Prefix => Duplicate_Subexpr_Move_Checks (N));
Set_Has_Dereference_Action (Deref);
Make_Op_Divide (Loc,
Left_Opnd =>
Size := Make_Temporary (Loc, 'S');
Insert_Action (N,
Make_Object_Declaration (Loc,
Defining_Identifier => Size,
Object_Definition =>
New_Reference_To (RTE (RE_Storage_Count), Loc),
Expression =>
Make_Op_Divide (Loc,
Left_Opnd =>
Make_Attribute_Reference (Loc,
Prefix =>
Make_Explicit_Dereference (Loc,
Duplicate_Subexpr_Move_Checks (N)),
Prefix => Deref,
Attribute_Name => Name_Size),
Right_Opnd =>
Make_Integer_Literal (Loc, System_Storage_Unit)),
Make_Integer_Literal (Loc, System_Storage_Unit))));
-- Alignment
-- Calculate the alignment of the dereferenced object. Generate:
-- Alig : constant Storage_Count := <N>.all'Alignment;
Make_Attribute_Reference (Loc,
Prefix =>
Make_Explicit_Dereference (Loc,
Duplicate_Subexpr_Move_Checks (N)),
Attribute_Name => Name_Alignment))));
Deref :=
Make_Explicit_Dereference (Loc,
Prefix => Duplicate_Subexpr_Move_Checks (N));
Set_Has_Dereference_Action (Deref);
Alig := Make_Temporary (Loc, 'A');
Insert_Action (N,
Make_Object_Declaration (Loc,
Defining_Identifier => Alig,
Object_Definition =>
New_Reference_To (RTE (RE_Storage_Count), Loc),
Expression =>
Make_Attribute_Reference (Loc,
Prefix => Deref,
Attribute_Name => Name_Alignment)));
-- A dereference of a controlled object requires special processing. The
-- finalization machinery requests additional space from the underlying
-- pool to allocate and hide two pointers. As a result, a checked pool
-- may mark the wrong memory as valid. Since checked pools do not have
-- knowledge of hidden pointers, we have to bring the two pointers back
-- in view in order to restore the original state of the object.
if Needs_Finalization (Desig) then
-- Adjust the address and size of the dereferenced object. Generate:
-- Adjust_Controlled_Dereference (Addr, Size, Alig);
Stmt :=
Make_Procedure_Call_Statement (Loc,
Name =>
New_Reference_To (RTE (RE_Adjust_Controlled_Dereference), Loc),
Parameter_Associations => New_List (
New_Reference_To (Addr, Loc),
New_Reference_To (Size, Loc),
New_Reference_To (Alig, Loc)));
-- Class-wide types complicate things because we cannot determine
-- statically whether the actual object is truly controlled. We must
-- generate a runtime check to detect this property. Generate:
--
-- if Needs_Finalization (<N>.all'Tag) then
-- <Stmt>;
-- end if;
if Is_Class_Wide_Type (Desig) then
Deref :=
Make_Explicit_Dereference (Loc,
Prefix => Duplicate_Subexpr_Move_Checks (N));
Set_Has_Dereference_Action (Deref);
Stmt :=
Make_If_Statement (Loc,
Condition =>
Make_Function_Call (Loc,
Name =>
New_Reference_To (RTE (RE_Needs_Finalization), Loc),
Parameter_Associations => New_List (
Make_Attribute_Reference (Loc,
Prefix => Deref,
Attribute_Name => Name_Tag))),
Then_Statements => New_List (Stmt));
end if;
Insert_Action (N, Stmt);
end if;
-- Generate:
-- Dereference (Pool, Addr, Size, Alig);
Insert_Action (N,
Make_Procedure_Call_Statement (Loc,
Name =>
New_Reference_To
(Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
Parameter_Associations => New_List (
New_Reference_To (Pool, Loc),
New_Reference_To (Addr, Loc),
New_Reference_To (Size, Loc),
New_Reference_To (Alig, Loc))));
-- Mark the explicit dereference as processed to avoid potential
-- infinite expansion.
Set_Has_Dereference_Action (Pnod);
exception
when RE_Not_Available =>
......
......@@ -1401,6 +1401,7 @@ package Rtsfind is
RE_Root_Storage_Pool, -- System.Storage_Pools
RE_Root_Storage_Pool_Ptr, -- System.Storage_Pools
RE_Adjust_Controlled_Dereference, -- System.Storage_Pools.Subpools
RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Header_Size_With_Padding, -- System.Storage_Pools.Subpools
......@@ -2624,6 +2625,7 @@ package Rtsfind is
RE_Root_Storage_Pool => System_Storage_Pools,
RE_Root_Storage_Pool_Ptr => System_Storage_Pools,
RE_Adjust_Controlled_Dereference => System_Storage_Pools_Subpools,
RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Header_Size_With_Padding => System_Storage_Pools_Subpools,
......
......@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
-- Copyright (C) 2011, Free Software Foundation, Inc. --
-- Copyright (C) 2011-2012, 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- --
......@@ -56,6 +56,24 @@ package body System.Storage_Pools.Subpools is
procedure Detach (N : not null SP_Node_Ptr);
-- Unhook a subpool node from an arbitrary subpool list
procedure Adjust_Controlled_Dereference
(Addr : in out System.Address;
Storage_Size : in out System.Storage_Elements.Storage_Count;
Alignment : System.Storage_Elements.Storage_Count)
is
Header_And_Padding : constant Storage_Offset :=
Header_Size_With_Padding (Alignment);
begin
-- Expose the two hidden pointers by shifting the address from the
-- start of the object to the FM_Node equivalent of the pointers.
Addr := Addr - Header_And_Padding;
-- Update the size of the object to include the two pointers
Storage_Size := Storage_Size + Header_And_Padding;
end Adjust_Controlled_Dereference;
--------------
-- Allocate --
--------------
......
......@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
-- Copyright (C) 2011, Free Software Foundation, Inc. --
-- Copyright (C) 2011-2012, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
......@@ -249,6 +249,14 @@ private
-- This back pointer is used in subpool deallocation.
end record;
procedure Adjust_Controlled_Dereference
(Addr : in out System.Address;
Storage_Size : in out System.Storage_Elements.Storage_Count;
Alignment : System.Storage_Elements.Storage_Count);
-- Given the memory attributes of a heap-allocated object that is known to
-- be controlled, adjust the address and size of the object to include the
-- two hidden pointers inserted by the finalization machinery.
-- ??? Once Storage_Pools.Allocate_Any is removed, this should be renamed
-- to Allocate_Any.
......
......@@ -1427,6 +1427,14 @@ package body Sinfo is
return Flag15 (N);
end Has_Created_Identifier;
function Has_Dereference_Action
(N : Node_Id) return Boolean is
begin
pragma Assert (False
or else NT (N).Nkind = N_Explicit_Dereference);
return Flag13 (N);
end Has_Dereference_Action;
function Has_Dynamic_Length_Check
(N : Node_Id) return Boolean is
begin
......@@ -4515,6 +4523,14 @@ package body Sinfo is
Set_Flag15 (N, Val);
end Set_Has_Created_Identifier;
procedure Set_Has_Dereference_Action
(N : Node_Id; Val : Boolean := True) is
begin
pragma Assert (False
or else NT (N).Nkind = N_Explicit_Dereference);
Set_Flag13 (N, Val);
end Set_Has_Dereference_Action;
procedure Set_Has_Dynamic_Length_Check
(N : Node_Id; Val : Boolean := True) is
begin
......
......@@ -1111,6 +1111,12 @@ package Sinfo is
-- handler is deleted during optimization. For further details on why
-- this is required, see Exp_Ch11.Remove_Handler_Entries.
-- Has_Dereference_Action (Flag13-Sem)
-- This flag is present in N_Explicit_Dereference nodes. It is set to
-- indicate that the expansion has aready produced a call to primitive
-- Dereference of a System.Checked_Pools.Checked_Pool implementation.
-- Such dereference actions are produced for debugging purposes.
-- Has_Dynamic_Length_Check (Flag10-Sem)
-- This flag is present in all expression nodes. It is set to indicate
-- that one of the routines in unit Checks has generated a length check
......@@ -3192,6 +3198,7 @@ package Sinfo is
-- Prefix (Node3)
-- Actual_Designated_Subtype (Node4-Sem)
-- Atomic_Sync_Required (Flag14-Sem)
-- Has_Dereference_Action (Flag13-Sem)
-- plus fields for expression
-------------------------------
......@@ -8524,6 +8531,9 @@ package Sinfo is
function Has_Created_Identifier
(N : Node_Id) return Boolean; -- Flag15
function Has_Dereference_Action
(N : Node_Id) return Boolean; -- Flag13
function Has_Dynamic_Length_Check
(N : Node_Id) return Boolean; -- Flag10
......@@ -9508,6 +9518,9 @@ package Sinfo is
procedure Set_Has_Created_Identifier
(N : Node_Id; Val : Boolean := True); -- Flag15
procedure Set_Has_Dereference_Action
(N : Node_Id; Val : Boolean := True); -- Flag13
procedure Set_Has_Dynamic_Length_Check
(N : Node_Id; Val : Boolean := True); -- Flag10
......@@ -11947,6 +11960,7 @@ package Sinfo is
pragma Inline (Handled_Statement_Sequence);
pragma Inline (Handler_List_Entry);
pragma Inline (Has_Created_Identifier);
pragma Inline (Has_Dereference_Action);
pragma Inline (Has_Dynamic_Length_Check);
pragma Inline (Has_Dynamic_Range_Check);
pragma Inline (Has_Init_Expression);
......@@ -12272,6 +12286,7 @@ package Sinfo is
pragma Inline (Set_Handled_Statement_Sequence);
pragma Inline (Set_Handler_List_Entry);
pragma Inline (Set_Has_Created_Identifier);
pragma Inline (Set_Has_Dereference_Action);
pragma Inline (Set_Has_Dynamic_Length_Check);
pragma Inline (Set_Has_Init_Expression);
pragma Inline (Set_Has_Local_Raise);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment