public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-5911] ada: Further cleanup in finalization machinery
@ 2023-11-28  9:38 Marc Poulhi?s
  0 siblings, 0 replies; only message in thread
From: Marc Poulhi?s @ 2023-11-28  9:38 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:39cb85867dee738bd3773b63c2b48d5d0731dea5

commit r14-5911-g39cb85867dee738bd3773b63c2b48d5d0731dea5
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Thu Nov 9 15:00:56 2023 +0100

    ada: Further cleanup in finalization machinery
    
    When transient scopes are being materialized, they can give rise to a block
    created around the construct being wrapped or not, depending on the kind of
    construct.  In both cases finalization actions for the transient objects of
    the scope are generated the same way, with normal finalization done manually
    immediately after the construct and exceptional finalization deferred to the
    enclosing scope by means of a hooking mechanism.
    
    Now when the block is generated, it becomes this enclosing scope, so the
    normal finalization that comes with it would also be done immediately after
    the construct, even without normal finalization generated manually.
    
    Therefore this change gets rid of the manual finalization as well as of the
    hooking in the cases where the block is generated, leading to a significant
    streamlining of the expanded code in these cases.  This requires fixing a
    small inaccuracy of the Within_Case_Or_If_Expression predicate, which must
    only be concerned with the dependent expressions, since those are the only
    ones to be treated specially by the finalization machinery.
    
    It also contains a small cleanup for the description of the transient scope
    management present at the beginning of the exp_ch7.adb file.
    
    gcc/ada/
    
            * exp_ch7.ads (Expand_Cleanup_Actions): Move declaration to the
            Finalization Management section.
            * exp_ch7.adb (Transient Scope Management): Move description down to
            after that of the general finalization and make a few changes.
            (Insert_Actions_In_Scope_Around): Call Process_Transients_In_Scope
            only if cleanups are being handled.
            (Process_Transients_In_Scope): Remove redundant test on Clean.
            * exp_util.ads (Within_Case_Or_If_Expression): Adjust description.
            * exp_util.adb (Within_Case_Or_If_Expression): Only return true if
            within the dependent expressions of the conditional expressions.

Diff:
---
 gcc/ada/exp_ch7.adb  | 149 ++++++++++++++++++++++++++++++---------------------
 gcc/ada/exp_ch7.ads  |  12 ++---
 gcc/ada/exp_util.adb |  16 ++++--
 gcc/ada/exp_util.ads |   7 +--
 4 files changed, 110 insertions(+), 74 deletions(-)

diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f8c12b73e9b..f5d9b0fe802 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -70,59 +70,6 @@ with Uintp;          use Uintp;
 
 package body Exp_Ch7 is
 
-   --------------------------------
-   -- Transient Scope Management --
-   --------------------------------
-
-   --  A transient scope is needed when certain temporary objects are created
-   --  by the compiler. These temporary objects are allocated on the secondary
-   --  stack and/or need finalization, and the transient scope is responsible
-   --  for finalizing the objects and reclaiming the memory of the secondary
-   --  stack at the appropriate time. They are generally objects allocated to
-   --  store the result of a function returning an unconstrained or controlled
-   --  value. Expressions needing to be wrapped in a transient scope may appear
-   --  in three different contexts which lead to different kinds of transient
-   --  scope expansion:
-
-   --   1. In a simple statement (procedure call, assignment, ...). In this
-   --      case the instruction is wrapped into a transient block. See
-   --      Wrap_Transient_Statement for details.
-
-   --   2. In an expression of a control structure (test in a IF statement,
-   --      expression in a CASE statement, ...). See Wrap_Transient_Expression
-   --      for details.
-
-   --   3. In a expression of an object_declaration. No wrapping is possible
-   --      here, so the finalization actions, if any, are done right after the
-   --      declaration and the secondary stack deallocation is done in the
-   --      proper enclosing scope. See Wrap_Transient_Declaration for details.
-
-   --------------------------------------------------
-   -- Transient Blocks and Finalization Management --
-   --------------------------------------------------
-
-   procedure Insert_Actions_In_Scope_Around
-     (N         : Node_Id;
-      Clean     : Boolean;
-      Manage_SS : Boolean);
-   --  Insert the before-actions kept in the scope stack before N, and the
-   --  after-actions after N, which must be a member of a list. If flag Clean
-   --  is set, insert any cleanup actions. If flag Manage_SS is set, insert
-   --  calls to mark and release the secondary stack.
-
-   function Make_Transient_Block
-     (Loc    : Source_Ptr;
-      Action : Node_Id;
-      Par    : Node_Id) return Node_Id;
-   --  Action is a single statement or object declaration. Par is the proper
-   --  parent of the generated block. Create a transient block whose name is
-   --  the current scope and the only handled statement is Action. If Action
-   --  involves controlled objects or secondary stack usage, the corresponding
-   --  cleanup actions are performed at the end of the block.
-
-   procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
-   --  Shared processing for Store_xxx_Actions_In_Scope
-
    -----------------------------
    -- Finalization Management --
    -----------------------------
@@ -292,6 +239,84 @@ package body Exp_Ch7 is
    --  Build the deep Initialize/Adjust/Finalize for a record Typ with
    --  Has_Component_Component set and store them using the TSS mechanism.
 
+   --------------------------------
+   -- Transient Scope Management --
+   --------------------------------
+
+   --  A transient scope is needed when certain temporary objects are created
+   --  by the compiler. These temporary objects are allocated on the secondary
+   --  stack and/or need finalization, and the transient scope is responsible
+   --  for finalizing the objects and reclaiming the memory of the secondary
+   --  stack at the appropriate time. They are generally objects allocated to
+   --  store the result of a function returning an unconstrained or controlled
+   --  value. Expressions needing to be wrapped in a transient scope may appear
+   --  in three different contexts, which lead to different kinds of transient
+   --  scope expansion:
+
+   --   1. In a simple statement (procedure call, assignment, ...). In this
+   --      case the statement is wrapped into a transient block, which takes
+   --      care of the finalization actions as well as the secondary stack
+   --      deallocation, See Wrap_Transient_Statement for details.
+
+   --   2. In an expression of a control structure (test in a If statement,
+   --      expression in a Case statement, ...). In this case the expression
+   --      is replaced by a temporary and the enclosing statement is wrapped
+   --      into a transient block, which takes care of the finalization actions
+   --      and the secondary stack deallocation. See Wrap_Transient_Expression
+   --      for details.
+
+   --   3. In an expression of an object declaration. No wrapping is possible
+   --      here, so the finalization actions performed on the normal path, if
+   --      any, are done right after the declaration, and those performed on
+   --      the exceptional path, as well as the secondary stack deallocation,
+   --      are deferred to the enclosing scope. See Wrap_Transient_Declaration
+   --      for details.
+
+   --  A transient scope is created by calling Establish_Transient_Scope on the
+   --  node that needs to be serviced by it (the serviced node can subsequently
+   --  be retrieved by invoking Node_To_Be_Wrapped when the current scope is a
+   --  transient scope). Once this has been done, the normal processing of the
+   --  Insert_Actions procedures is blocked and the procedures are redirected
+   --  to the Store_xxx_Actions_In_Scope procedures and Store_Actions_In_Scope
+   --  is ultimately invoked to store the pending actions.
+
+   --  A transient scope is finalized by calling one of the Wrap_Transient_xxx
+   --  procedures depending on the context as explained above. They ultimately
+   --  invoke Insert_Actions_In_Scope_Around as per the following picture:
+
+   --            Wrap_Transient_Expression          Wrap_Transient_Statement
+   --                                  |              |
+   --                                  V              V
+   --                                Make_Transient_Block
+   --                                        |
+   --   Wrap_Transient_Declaration           |
+   --                          |             |
+   --                          V             V
+   --                       Insert_Actions_In_Scope_Around
+
+   procedure Insert_Actions_In_Scope_Around
+     (N         : Node_Id;
+      Clean     : Boolean;
+      Manage_SS : Boolean);
+   --  Insert the before-actions kept in the scope stack before N, and the
+   --  after-actions after N, which must be a member of a list. If Clean is
+   --  true, insert any cleanup actions kept in the scope stack and generate
+   --  required finalization actions for the before-actions and after-actions.
+   --  If Manage_SS is true, insert calls to mark/release the secondary stack.
+
+   function Make_Transient_Block
+     (Loc    : Source_Ptr;
+      Action : Node_Id;
+      Par    : Node_Id) return Node_Id;
+   --  Action is a single statement or object declaration. Par is the proper
+   --  parent of the generated block. Create a transient block whose name is
+   --  the current scope and the only handled statement is Action. If Action
+   --  involves controlled objects or secondary stack usage, the corresponding
+   --  cleanup actions are performed at the end of the block.
+
+   procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
+   --  Shared processing for Store_xxx_Actions_In_Scope
+
    -------------------------------------------
    -- Unnesting procedures for CCG and LLVM --
    -------------------------------------------
@@ -5641,9 +5666,7 @@ package body Exp_Ch7 is
             Blk_Ins   := Last_Object;
          end if;
 
-         if Clean then
-            Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
-         end if;
+         Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
 
          --  Examine all objects in the list First_Object .. Last_Object
 
@@ -5824,13 +5847,15 @@ package body Exp_Ch7 is
            (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
       end if;
 
-      --  Check for transient objects associated with Target and generate the
-      --  appropriate finalization actions for them.
+      --  If we are handling cleanups, check for transient objects associated
+      --  with Target and generate the required finalization actions for them.
 
-      Process_Transients_In_Scope
-        (First_Object => First_Obj,
-         Last_Object  => Last_Obj,
-         Related_Node => Target);
+      if Clean then
+         Process_Transients_In_Scope
+           (First_Object => First_Obj,
+            Last_Object  => Last_Obj,
+            Related_Node => Target);
+      end if;
 
       --  Reset the action lists
 
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index a131e55f5c3..105aa7e3d2f 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -176,6 +176,12 @@ package Exp_Ch7 is
    --  triggered by an abort, E_Id denotes the defining identifier of a local
    --  exception occurrence, Raised_Id is the entity of a local boolean flag.
 
+   procedure Expand_Cleanup_Actions (N : Node_Id);
+   --  Expand the necessary stuff into a scope to enable finalization of local
+   --  objects and deallocation of transient data when exiting the scope. N is
+   --  one of N_Block_Statement, N_Subprogram_Body, N_Task_Body, N_Entry_Body,
+   --  or N_Extended_Return_Statement.
+
    function Make_Adjust_Call
      (Obj_Ref   : Node_Id;
       Typ       : Entity_Id;
@@ -275,12 +281,6 @@ package Exp_Ch7 is
    -- Transient Scope Management --
    --------------------------------
 
-   procedure Expand_Cleanup_Actions (N : Node_Id);
-   --  Expand the necessary stuff into a scope to enable finalization of local
-   --  objects and deallocation of transient data when exiting the scope. N is
-   --  one of N_Block_Statement, N_Subprogram_Body, N_Task_Body, N_Entry_Body,
-   --  or N_Extended_Return_Statement.
-
    procedure Establish_Transient_Scope
      (N                : Node_Id;
       Manage_Sec_Stack : Boolean);
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 3952a161bd7..3dc34fcb493 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -14401,6 +14401,7 @@ package body Exp_Util is
    ----------------------------------
 
    function Within_Case_Or_If_Expression (N : Node_Id) return Boolean is
+      Nod : Node_Id;
       Par : Node_Id;
 
    begin
@@ -14408,9 +14409,17 @@ package body Exp_Util is
       --  can be expanded into Expression_With_Actions, hence the test of the
       --  original node.
 
-      Par := Parent (N);
+      Nod := N;
+      Par := Parent (Nod);
+
       while Present (Par) loop
-         if Nkind (Original_Node (Par)) in N_Case_Expression | N_If_Expression
+         if Nkind (Original_Node (Par)) = N_Case_Expression
+           and then Nod /= Expression (Original_Node (Par))
+         then
+            return True;
+
+         elsif Nkind (Original_Node (Par)) = N_If_Expression
+           and then Nod /= First (Expressions (Original_Node (Par)))
          then
             return True;
 
@@ -14430,7 +14439,8 @@ package body Exp_Util is
             return False;
          end if;
 
-         Par := Parent (Par);
+         Nod := Par;
+         Par := Parent (Nod);
       end loop;
 
       return False;
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 932bf3fdcbc..eb737d67769 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -1255,9 +1255,10 @@ package Exp_Util is
    --  extension to verify legality rules on inherited conditions.
 
    function Within_Case_Or_If_Expression (N : Node_Id) return Boolean;
-   --  Determine whether arbitrary node N is immediately within a case or an if
-   --  expression. The criterion is whether temporaries created by the actions
-   --  attached to N need to outlive an enclosing case or if expression.
+   --  Determine whether arbitrary node N is immediately within a dependent
+   --  expression of a case or an if expression. The criterion is whether
+   --  temporaries created by the actions attached to N need to outlive an
+   --  enclosing case or if expression.
 
 private
    pragma Inline (Duplicate_Subexpr);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-28  9:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-28  9:38 [gcc r14-5911] ada: Further cleanup in finalization machinery Marc Poulhi?s

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).