diff options
Diffstat (limited to 'gcc/ada/exp_ch9.adb')
-rw-r--r-- | gcc/ada/exp_ch9.adb | 890 |
1 files changed, 344 insertions, 546 deletions
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 9d21af2..1f9f458 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -25,7 +25,6 @@ with Atree; use Atree; with Checks; use Checks; -with Debug; use Debug; with Einfo; use Einfo; with Elists; use Elists; with Errout; use Errout; @@ -52,6 +51,7 @@ with Sem; use Sem; with Sem_Aux; use Sem_Aux; with Sem_Ch6; use Sem_Ch6; with Sem_Ch8; use Sem_Ch8; +with Sem_Ch9; use Sem_Ch9; with Sem_Ch11; use Sem_Ch11; with Sem_Elab; use Sem_Elab; with Sem_Eval; use Sem_Eval; @@ -61,7 +61,6 @@ with Sinfo; use Sinfo; with Snames; use Snames; with Stand; use Stand; with Stringt; use Stringt; -with Table; with Targparm; use Targparm; with Tbuild; use Tbuild; with Uintp; use Uintp; @@ -77,37 +76,6 @@ package body Exp_Ch9 is Entry_Family_Bound : constant Int := 2**16; - ------------------------------ - -- Lock Free Data Structure -- - ------------------------------ - - -- A lock-free subprogram is a protected routine which references a unique - -- protected scalar component and does not contain statements that cause - -- side effects. Due to this restricted behavior, all references to shared - -- data from within the subprogram can be synchronized through the use of - -- atomic operations rather than relying on locks. - - type Lock_Free_Subprogram is record - Sub_Body : Node_Id; - -- Reference to the body of a protected subprogram which meets the lock- - -- free requirements. - - Comp_Id : Entity_Id; - -- Reference to the scalar component referenced from within Sub_Body - end record; - - -- This table establishes a relation between a protected subprogram body - -- and a unique component it references. The table is used when building - -- the lock-free versions of a protected subprogram body. - - package Lock_Free_Subprogram_Table is new Table.Table ( - Table_Component_Type => Lock_Free_Subprogram, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 5, - Table_Increment => 5, - Table_Name => "Lock_Free_Subprogram_Table"); - ----------------------- -- Local Subprograms -- ----------------------- @@ -142,20 +110,6 @@ package body Exp_Ch9 is -- Decls is the list of declarations to be enhanced. -- Ent is the entity for the original entry body. - function Allows_Lock_Free_Implementation (N : Node_Id) return Boolean; - -- Given a protected body N, return True if N satisfies the following list - -- of lock-free restrictions: - -- - -- 1) Protected type - -- May not contain entries - -- May contain only scalar components - -- Component types must support atomic compare and exchange - -- - -- 2) Protected subprograms - -- May not have side effects - -- May not contain loop statements or procedure calls - -- Function calls and attribute references must be static - function Build_Accept_Body (Astat : Node_Id) return Node_Id; -- Transform accept statement into a block with added exception handler. -- Used both for simple accept statements and for accept alternatives in @@ -828,220 +782,6 @@ package body Exp_Ch9 is Prepend_To (Decls, Decl); end Add_Object_Pointer; - ------------------------------------- - -- Allows_Lock_Free_Implementation -- - ------------------------------------- - - function Allows_Lock_Free_Implementation (N : Node_Id) return Boolean is - Spec : constant Entity_Id := Corresponding_Spec (N); - Prot_Def : constant Node_Id := Protected_Definition (Parent (Spec)); - Priv_Decls : constant List_Id := Private_Declarations (Prot_Def); - - function Satisfies_Lock_Free_Requirements - (Sub_Body : Node_Id) return Boolean; - -- Return True if protected subprogram body Sub_Body satisfies all - -- requirements of a lock-free implementation. - - -------------------------------------- - -- Satisfies_Lock_Free_Requirements -- - -------------------------------------- - - function Satisfies_Lock_Free_Requirements - (Sub_Body : Node_Id) return Boolean - is - Comp : Entity_Id := Empty; - -- Track the current component which the body references - - function Check_Node (N : Node_Id) return Traverse_Result; - -- Check that node N meets the lock free restrictions - - ---------------- - -- Check_Node -- - ---------------- - - function Check_Node (N : Node_Id) return Traverse_Result is - begin - -- Function calls and attribute references must be static - -- ??? what about side-effects - - if Nkind_In (N, N_Attribute_Reference, N_Function_Call) - and then not Is_Static_Expression (N) - then - return Abandon; - - -- Loop statements and procedure calls are prohibited - - elsif Nkind_In (N, N_Loop_Statement, - N_Procedure_Call_Statement) - then - return Abandon; - - -- References - - elsif Nkind (N) = N_Identifier - and then Present (Entity (N)) - then - declare - Id : constant Entity_Id := Entity (N); - Sub_Id : constant Entity_Id := Corresponding_Spec (Sub_Body); - - begin - -- Prohibit references to non-constant entities outside the - -- protected subprogram scope. - - if Ekind (Id) in Assignable_Kind - and then not Scope_Within_Or_Same (Scope (Id), Sub_Id) - and then not Scope_Within_Or_Same (Scope (Id), - Protected_Body_Subprogram (Sub_Id)) - then - return Abandon; - - -- A protected subprogram may reference only one component - -- of the protected type. - - elsif Ekind_In (Id, E_Constant, E_Variable) - and then Present (Prival_Link (Id)) - then - declare - Comp_Decl : constant Node_Id := - Parent (Prival_Link (Id)); - begin - if Nkind (Comp_Decl) = N_Component_Declaration - and then Is_List_Member (Comp_Decl) - and then List_Containing (Comp_Decl) = Priv_Decls - then - if No (Comp) then - Comp := Prival_Link (Id); - - -- Check if another protected component has already - -- been accessed by the subprogram body. - - elsif Comp /= Prival_Link (Id) then - return Abandon; - end if; - end if; - end; - end if; - end; - end if; - - return OK; - end Check_Node; - - function Check_All_Nodes is new Traverse_Func (Check_Node); - - -- Start of processing for Satisfies_Lock_Free_Requirements - - begin - if Check_All_Nodes (Sub_Body) = OK then - - -- Establish a relation between the subprogram body and the unique - -- protected component it references. - - if Present (Comp) then - Lock_Free_Subprogram_Table.Append - (Lock_Free_Subprogram'(Sub_Body, Comp)); - end if; - - return True; - else - return False; - end if; - end Satisfies_Lock_Free_Requirements; - - -- Local variables - - Decls : constant List_Id := Declarations (N); - Vis_Decls : constant List_Id := Visible_Declarations (Prot_Def); - - Comp_Id : Entity_Id; - Comp_Size : Int; - Comp_Type : Entity_Id; - Decl : Node_Id; - Has_Component : Boolean := False; - - -- Start of processing for Allows_Lock_Free_Implementation - - begin - -- The lock-free implementation is currently enabled through a debug - -- flag. - - if not Debug_Flag_9 then - return False; - end if; - - -- Examine the visible declarations. Entries and entry families are not - -- allowed by the lock-free restrictions. - - Decl := First (Vis_Decls); - while Present (Decl) loop - if Nkind (Decl) = N_Entry_Declaration then - return False; - end if; - - Next (Decl); - end loop; - - -- Examine the private declarations - - Decl := First (Priv_Decls); - while Present (Decl) loop - - -- The protected type must define at least one scalar component - - if Nkind (Decl) = N_Component_Declaration then - Has_Component := True; - - Comp_Id := Defining_Identifier (Decl); - Comp_Type := Etype (Comp_Id); - - if not Is_Scalar_Type (Comp_Type) then - return False; - end if; - - Comp_Size := UI_To_Int (Esize (Base_Type (Comp_Type))); - - -- Check that the size of the component is 8, 16, 32 or 64 bits - - case Comp_Size is - when 8 | 16 | 32 | 64 => - null; - when others => - return False; - end case; - - -- Entries and entry families are not allowed - - elsif Nkind (Decl) = N_Entry_Declaration then - return False; - end if; - - Next (Decl); - end loop; - - -- At least one scalar component must be present - - if not Has_Component then - return False; - end if; - - -- Ensure that all protected subprograms meet the restrictions of the - -- lock-free implementation. - - Decl := First (Decls); - while Present (Decl) loop - if Nkind (Decl) = N_Subprogram_Body - and then not Satisfies_Lock_Free_Requirements (Decl) - then - return False; - end if; - - Next (Decl); - end loop; - - return True; - end Allows_Lock_Free_Implementation; - ----------------------- -- Build_Accept_Body -- ----------------------- @@ -3228,7 +2968,8 @@ package body Exp_Ch9 is -- begin -- loop -- declare - -- Saved_Comp : constant ... := Atomic_Load (Comp'Address); + -- Saved_Comp : constant ... := + -- Atomic_Load (Comp'Address, Relaxed); -- Current_Comp : ... := Saved_Comp; -- begin -- <original statements> @@ -3496,19 +3237,33 @@ package body Exp_Ch9 is if Present (Comp) then declare - Comp_Typ : constant Entity_Id := Etype (Comp); - Typ_Size : constant Int := UI_To_Int (Esize (Comp_Typ)); + Comp_Type : constant Entity_Id := Etype (Comp); Block_Decls : List_Id; Compare : Entity_Id; Current_Comp : Entity_Id; Decl : Node_Id; Label : Node_Id; Load : Entity_Id; + Load_Params : List_Id; Saved_Comp : Entity_Id; Stmt : Node_Id; + Typ_Size : Int; Unsigned : Entity_Id; begin + -- Get the type size + + if Known_Esize (Comp_Type) then + Typ_Size := UI_To_Int (Esize (Comp_Type)); + + -- If the Esize (Object_Size) is unknown at compile-time, look at + -- the RM_Size (Value_Size) since it may have been set by an + -- explicit representation clause. + + else + Typ_Size := UI_To_Int (RM_Size (Comp_Type)); + end if; + -- Retrieve all relevant atomic routines and types case Typ_Size is @@ -3537,26 +3292,43 @@ package body Exp_Ch9 is end case; -- Generate: - -- Saved_Comp : constant Comp_Typ := - -- Comp_Typ (Atomic_Load (Comp'Address)); + -- For functions: + + -- Saved_Comp : constant Comp_Type := + -- Comp_Type (Atomic_Load (Comp'Address)); + + -- For procedures: + + -- Saved_Comp : constant Comp_Type := + -- Comp_Type (Atomic_Load (Comp'Address), + -- Relaxed); Saved_Comp := Make_Defining_Identifier (Loc, New_External_Name (Chars (Comp), Suffix => "_saved")); + Load_Params := New_List ( + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Comp, Loc), + Attribute_Name => Name_Address)); + + -- For protected procedures, set the memory model to be relaxed + + if Is_Procedure then + Append_To (Load_Params, + New_Reference_To (RTE (RE_Relaxed), Loc)); + end if; + Decl := Make_Object_Declaration (Loc, Defining_Identifier => Saved_Comp, Constant_Present => True, - Object_Definition => New_Reference_To (Comp_Typ, Loc), + Object_Definition => New_Reference_To (Comp_Type, Loc), Expression => - Unchecked_Convert_To (Comp_Typ, + Unchecked_Convert_To (Comp_Type, Make_Function_Call (Loc, Name => New_Reference_To (Load, Loc), - Parameter_Associations => New_List ( - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Comp, Loc), - Attribute_Name => Name_Address))))); + Parameter_Associations => Load_Params))); -- Protected procedures @@ -3564,7 +3336,7 @@ package body Exp_Ch9 is Block_Decls := New_List (Decl); -- Generate: - -- Current_Comp : Comp_Typ := Saved_Comp; + -- Current_Comp : Comp_Type := Saved_Comp; Current_Comp := Make_Defining_Identifier (Loc, @@ -3573,7 +3345,7 @@ package body Exp_Ch9 is Append_To (Block_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Current_Comp, - Object_Definition => New_Reference_To (Comp_Typ, Loc), + Object_Definition => New_Reference_To (Comp_Type, Loc), Expression => New_Reference_To (Saved_Comp, Loc))); -- Protected function @@ -3645,6 +3417,9 @@ package body Exp_Ch9 is if Is_Procedure then Stmts := New_List ( + Make_Procedure_Call_Statement (Loc, + Name => + New_Reference_To (RTE (RE_Atomic_Synchronize), Loc)), Make_Loop_Statement (Loc, Statements => New_List ( Make_Block_Statement (Loc, @@ -8423,7 +8198,7 @@ package body Exp_Ch9 is Loc : constant Source_Ptr := Sloc (N); Pid : constant Entity_Id := Corresponding_Spec (N); - Lock_Free_On : constant Boolean := Allows_Lock_Free_Implementation (N); + Lock_Free_Active : constant Boolean := Uses_Lock_Free (Pid); -- This flag indicates whether the lock free implementation is active Current_Node : Node_Id; @@ -8554,7 +8329,7 @@ package body Exp_Ch9 is if not Is_Eliminated (Defining_Entity (Op_Body)) and then not Is_Eliminated (Corresponding_Spec (Op_Body)) then - if Lock_Free_On then + if Lock_Free_Active then New_Op_Body := Build_Lock_Free_Unprotected_Subprogram_Body (Op_Body, Pid); @@ -8581,7 +8356,7 @@ package body Exp_Ch9 is -- declaration in the protected body itself. if Present (Corresponding_Spec (Op_Body)) then - if Lock_Free_On then + if Lock_Free_Active then New_Op_Body := Build_Lock_Free_Protected_Subprogram_Body (Op_Body, Pid, Specification (New_Op_Body)); @@ -8765,10 +8540,13 @@ package body Exp_Ch9 is -- the specs refer to this type. procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Prot_Typ : constant Entity_Id := Defining_Identifier (N); + Loc : constant Source_Ptr := Sloc (N); + Prot_Typ : constant Entity_Id := Defining_Identifier (N); + + Lock_Free_Active : constant Boolean := Uses_Lock_Free (Prot_Typ); + -- This flag indicates whether the lock free implementation is active - Pdef : constant Node_Id := Protected_Definition (N); + Pdef : constant Node_Id := Protected_Definition (N); -- This contains two lists; one for visible and one for private decls Rec_Decl : Node_Id; @@ -8926,108 +8704,6 @@ package body Exp_Ch9 is Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ); - -- Prepend the _Object field with the right type to the component list. - -- We need to compute the number of entries, and in some cases the - -- number of Attach_Handler pragmas. - - declare - Ritem : Node_Id; - Num_Attach_Handler : Int := 0; - Protection_Subtype : Node_Id; - Entry_Count_Expr : constant Node_Id := - Build_Entry_Count_Expression - (Prot_Typ, Cdecls, Loc); - - begin - -- Could this be simplified using Corresponding_Runtime_Package??? - - if Has_Attach_Handler (Prot_Typ) then - Ritem := First_Rep_Item (Prot_Typ); - while Present (Ritem) loop - if Nkind (Ritem) = N_Pragma - and then Pragma_Name (Ritem) = Name_Attach_Handler - then - Num_Attach_Handler := Num_Attach_Handler + 1; - end if; - - Next_Rep_Item (Ritem); - end loop; - - if Restricted_Profile then - if Has_Entries (Prot_Typ) then - Protection_Subtype := - New_Reference_To (RTE (RE_Protection_Entry), Loc); - else - Protection_Subtype := - New_Reference_To (RTE (RE_Protection), Loc); - end if; - else - Protection_Subtype := - Make_Subtype_Indication - (Sloc => Loc, - Subtype_Mark => - New_Reference_To - (RTE (RE_Static_Interrupt_Protection), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint ( - Sloc => Loc, - Constraints => New_List ( - Entry_Count_Expr, - Make_Integer_Literal (Loc, Num_Attach_Handler)))); - end if; - - elsif Has_Interrupt_Handler (Prot_Typ) - and then not Restriction_Active (No_Dynamic_Attachment) - then - Protection_Subtype := - Make_Subtype_Indication ( - Sloc => Loc, - Subtype_Mark => New_Reference_To - (RTE (RE_Dynamic_Interrupt_Protection), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint ( - Sloc => Loc, - Constraints => New_List (Entry_Count_Expr))); - - -- Type has explicit entries or generated primitive entry wrappers - - elsif Has_Entries (Prot_Typ) - or else (Ada_Version >= Ada_2005 - and then Present (Interface_List (N))) - then - case Corresponding_Runtime_Package (Prot_Typ) is - when System_Tasking_Protected_Objects_Entries => - Protection_Subtype := - Make_Subtype_Indication (Loc, - Subtype_Mark => - New_Reference_To (RTE (RE_Protection_Entries), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint ( - Sloc => Loc, - Constraints => New_List (Entry_Count_Expr))); - - when System_Tasking_Protected_Objects_Single_Entry => - Protection_Subtype := - New_Reference_To (RTE (RE_Protection_Entry), Loc); - - when others => - raise Program_Error; - end case; - - else - Protection_Subtype := New_Reference_To (RTE (RE_Protection), Loc); - end if; - - Object_Comp := - Make_Component_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uObject), - Component_Definition => - Make_Component_Definition (Loc, - Aliased_Present => True, - Subtype_Indication => Protection_Subtype)); - end; - pragma Assert (Present (Pdef)); -- Add private field components @@ -9144,10 +8820,117 @@ package body Exp_Ch9 is end loop; end if; - -- Put the _Object component after the private component so that it - -- be finalized early as required by 9.4 (20) + -- Except for the lock-free implementation, prepend the _Object field + -- with the right type to the component list. We need to compute the + -- number of entries, and in some cases the number of Attach_Handler + -- pragmas. + + if not Lock_Free_Active then + declare + Ritem : Node_Id; + Num_Attach_Handler : Int := 0; + Protection_Subtype : Node_Id; + Entry_Count_Expr : constant Node_Id := + Build_Entry_Count_Expression + (Prot_Typ, Cdecls, Loc); + + begin + -- Could this be simplified using Corresponding_Runtime_Package??? + + if Has_Attach_Handler (Prot_Typ) then + Ritem := First_Rep_Item (Prot_Typ); + while Present (Ritem) loop + if Nkind (Ritem) = N_Pragma + and then Pragma_Name (Ritem) = Name_Attach_Handler + then + Num_Attach_Handler := Num_Attach_Handler + 1; + end if; + + Next_Rep_Item (Ritem); + end loop; + + if Restricted_Profile then + if Has_Entries (Prot_Typ) then + Protection_Subtype := + New_Reference_To (RTE (RE_Protection_Entry), Loc); + else + Protection_Subtype := + New_Reference_To (RTE (RE_Protection), Loc); + end if; + else + Protection_Subtype := + Make_Subtype_Indication + (Sloc => Loc, + Subtype_Mark => + New_Reference_To + (RTE (RE_Static_Interrupt_Protection), Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint ( + Sloc => Loc, + Constraints => New_List ( + Entry_Count_Expr, + Make_Integer_Literal (Loc, Num_Attach_Handler)))); + end if; + + elsif Has_Interrupt_Handler (Prot_Typ) + and then not Restriction_Active (No_Dynamic_Attachment) + then + Protection_Subtype := + Make_Subtype_Indication ( + Sloc => Loc, + Subtype_Mark => New_Reference_To + (RTE (RE_Dynamic_Interrupt_Protection), Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint ( + Sloc => Loc, + Constraints => New_List (Entry_Count_Expr))); + + -- Type has explicit entries or generated primitive entry wrappers - Append_To (Cdecls, Object_Comp); + elsif Has_Entries (Prot_Typ) + or else (Ada_Version >= Ada_2005 + and then Present (Interface_List (N))) + then + case Corresponding_Runtime_Package (Prot_Typ) is + when System_Tasking_Protected_Objects_Entries => + Protection_Subtype := + Make_Subtype_Indication (Loc, + Subtype_Mark => + New_Reference_To (RTE (RE_Protection_Entries), + Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint ( + Sloc => Loc, + Constraints => New_List (Entry_Count_Expr))); + + when System_Tasking_Protected_Objects_Single_Entry => + Protection_Subtype := + New_Reference_To (RTE (RE_Protection_Entry), Loc); + + when others => + raise Program_Error; + end case; + + else + Protection_Subtype := + New_Reference_To (RTE (RE_Protection), Loc); + end if; + + Object_Comp := + Make_Component_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uObject), + Component_Definition => + Make_Component_Definition (Loc, + Aliased_Present => True, + Subtype_Indication => Protection_Subtype)); + end; + + -- Put the _Object component after the private component so that it + -- be finalized early as required by 9.4 (20) + + Append_To (Cdecls, Object_Comp); + end if; Insert_After (Current_Node, Rec_Decl); Current_Node := Rec_Decl; @@ -13149,9 +12932,12 @@ package body Exp_Ch9 is end if; -- Step 2: Create the Protection object and build its declaration for - -- any protected entry (family) of subprogram. + -- any protected entry (family) of subprogram. Note for the lock-free + -- implementation, the Protection object is not needed anymore. - if Is_Protected then + if Is_Protected + and then not Uses_Lock_Free (Conc_Typ) + then declare Prot_Ent : constant Entity_Id := Make_Temporary (Loc, 'R'); Prot_Typ : RE_Id; @@ -13612,191 +13398,200 @@ package body Exp_Ch9 is Args := New_List; - -- Object parameter. This is a pointer to the object of type - -- Protection used by the GNARL to control the protected object. - - Append_To (Args, - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Make_Identifier (Loc, Name_uInit), - Selector_Name => Make_Identifier (Loc, Name_uObject)), - Attribute_Name => Name_Unchecked_Access)); - - -- Priority parameter. Set to Unspecified_Priority unless there is a - -- priority pragma, in which case we take the value from the pragma, - -- or there is an interrupt pragma and no priority pragma, and we - -- set the ceiling to Interrupt_Priority'Last, an implementation- - -- defined value, see D.3(10). - - if Present (Pdef) - and then Has_Pragma_Priority (Pdef) - then - declare - Prio : constant Node_Id := - Expression - (First - (Pragma_Argument_Associations - (Find_Task_Or_Protected_Pragma - (Pdef, Name_Priority)))); - Temp : Entity_Id; - - begin - -- If priority is a static expression, then we can duplicate it - -- with no problem and simply append it to the argument list. - - if Is_Static_Expression (Prio) then - Append_To (Args, - Duplicate_Subexpr_No_Checks (Prio)); - - -- Otherwise, the priority may be a per-object expression, if it - -- depends on a discriminant of the type. In this case, create - -- local variable to capture the expression. Note that it is - -- really necessary to create this variable explicitly. It might - -- be thought that removing side effects would the appropriate - -- approach, but that could generate declarations improperly - -- placed in the enclosing scope. - - -- Note: Use System.Any_Priority as the expected type for the - -- non-static priority expression, in case the expression has not - -- been analyzed yet (as occurs for example with pragma - -- Interrupt_Priority). - - else - Temp := Make_Temporary (Loc, 'R', Prio); - Append_To (L, - Make_Object_Declaration (Loc, - Defining_Identifier => Temp, - Object_Definition => - New_Occurrence_Of (RTE (RE_Any_Priority), Loc), - Expression => Relocate_Node (Prio))); - - Append_To (Args, New_Occurrence_Of (Temp, Loc)); - end if; - end; + -- For lock-free implementation, skip initializations of the Protection + -- object. - -- When no priority is specified but an xx_Handler pragma is, we default - -- to System.Interrupts.Default_Interrupt_Priority, see D.3(10). + if not Uses_Lock_Free (Defining_Identifier (Pdec)) then + -- Object parameter. This is a pointer to the object of type + -- Protection used by the GNARL to control the protected object. - elsif Has_Attach_Handler (Ptyp) - or else Has_Interrupt_Handler (Ptyp) - then Append_To (Args, - New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc)); + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => Make_Identifier (Loc, Name_uInit), + Selector_Name => Make_Identifier (Loc, Name_uObject)), + Attribute_Name => Name_Unchecked_Access)); + + -- Priority parameter. Set to Unspecified_Priority unless there is a + -- priority pragma, in which case we take the value from the pragma, + -- or there is an interrupt pragma and no priority pragma, and we + -- set the ceiling to Interrupt_Priority'Last, an implementation- + -- defined value, see D.3(10). + + if Present (Pdef) + and then Has_Pragma_Priority (Pdef) + then + declare + Prio : constant Node_Id := + Expression + (First + (Pragma_Argument_Associations + (Find_Task_Or_Protected_Pragma + (Pdef, Name_Priority)))); + Temp : Entity_Id; - -- Normal case, no priority or xx_Handler specified, default priority + begin + -- If priority is a static expression, then we can duplicate it + -- with no problem and simply append it to the argument list. - else - Append_To (Args, - New_Reference_To (RTE (RE_Unspecified_Priority), Loc)); - end if; + if Is_Static_Expression (Prio) then + Append_To (Args, + Duplicate_Subexpr_No_Checks (Prio)); - -- Test for Compiler_Info parameter. This parameter allows entry body - -- procedures and barrier functions to be called from the runtime. It - -- is a pointer to the record generated by the compiler to represent - -- the protected object. + -- Otherwise, the priority may be a per-object expression, if + -- it depends on a discriminant of the type. In this case, + -- create local variable to capture the expression. Note that + -- it is really necessary to create this variable explicitly. + -- It might be thought that removing side effects would the + -- appropriate approach, but that could generate declarations + -- improperly placed in the enclosing scope. - -- A protected type without entries that covers an interface and - -- overrides the abstract routines with protected procedures is - -- considered equivalent to a protected type with entries in the - -- context of dispatching select statements. + -- Note: Use System.Any_Priority as the expected type for the + -- non-static priority expression, in case the expression has + -- not been analyzed yet (as occurs for example with pragma + -- Interrupt_Priority). - if Has_Entry - or else Has_Interfaces (Protect_Rec) - or else - ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp)) - and then not Restriction_Active (No_Dynamic_Attachment)) - then - declare - Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp); + else + Temp := Make_Temporary (Loc, 'R', Prio); + Append_To (L, + Make_Object_Declaration (Loc, + Defining_Identifier => Temp, + Object_Definition => + New_Occurrence_Of (RTE (RE_Any_Priority), Loc), + Expression => Relocate_Node (Prio))); + + Append_To (Args, New_Occurrence_Of (Temp, Loc)); + end if; + end; - Called_Subp : RE_Id; + -- When no priority is specified but an xx_Handler pragma is, we + -- default to System.Interrupts.Default_Interrupt_Priority, see + -- D.3(10). - begin - case Pkg_Id is - when System_Tasking_Protected_Objects_Entries => - Called_Subp := RE_Initialize_Protection_Entries; + elsif Has_Attach_Handler (Ptyp) + or else Has_Interrupt_Handler (Ptyp) + then + Append_To (Args, + New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc)); - when System_Tasking_Protected_Objects => - Called_Subp := RE_Initialize_Protection; + -- Normal case, no priority or xx_Handler specified, default priority - when System_Tasking_Protected_Objects_Single_Entry => - Called_Subp := RE_Initialize_Protection_Entry; + else + Append_To (Args, + New_Reference_To (RTE (RE_Unspecified_Priority), Loc)); + end if; - when others => - raise Program_Error; - end case; + -- Test for Compiler_Info parameter. This parameter allows entry body + -- procedures and barrier functions to be called from the runtime. It + -- is a pointer to the record generated by the compiler to represent + -- the protected object. + + -- A protected type without entries that covers an interface and + -- overrides the abstract routines with protected procedures is + -- considered equivalent to a protected type with entries in the + -- context of dispatching select statements. + + if Has_Entry + or else Has_Interfaces (Protect_Rec) + or else + ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp)) + and then not Restriction_Active (No_Dynamic_Attachment)) + then + declare + Pkg_Id : constant RTU_Id := + Corresponding_Runtime_Package (Ptyp); - if Has_Entry - or else not Restricted - or else Has_Interfaces (Protect_Rec) - then - Append_To (Args, - Make_Attribute_Reference (Loc, - Prefix => Make_Identifier (Loc, Name_uInit), - Attribute_Name => Name_Address)); - end if; + Called_Subp : RE_Id; - -- Entry_Bodies parameter. This is a pointer to an array of - -- pointers to the entry body procedures and barrier functions of - -- the object. If the protected type has no entries this object - -- will not exist, in this case, pass a null. + begin + case Pkg_Id is + when System_Tasking_Protected_Objects_Entries => + Called_Subp := RE_Initialize_Protection_Entries; - if Has_Entry then - P_Arr := Entry_Bodies_Array (Ptyp); + when System_Tasking_Protected_Objects => + Called_Subp := RE_Initialize_Protection; - Append_To (Args, - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (P_Arr, Loc), - Attribute_Name => Name_Unrestricted_Access)); + when System_Tasking_Protected_Objects_Single_Entry => + Called_Subp := RE_Initialize_Protection_Entry; + + when others => + raise Program_Error; + end case; - if Pkg_Id = System_Tasking_Protected_Objects_Entries then + if Has_Entry + or else not Restricted + or else Has_Interfaces (Protect_Rec) + then + Append_To (Args, + Make_Attribute_Reference (Loc, + Prefix => Make_Identifier (Loc, Name_uInit), + Attribute_Name => Name_Address)); + end if; - -- Find index mapping function (clumsy but ok for now) + -- Entry_Bodies parameter. This is a pointer to an array of + -- pointers to the entry body procedures and barrier functions + -- of the object. If the protected type has no entries this + -- object will not exist, in this case, pass a null. - while Ekind (P_Arr) /= E_Function loop - Next_Entity (P_Arr); - end loop; + if Has_Entry then + P_Arr := Entry_Bodies_Array (Ptyp); Append_To (Args, Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (P_Arr, Loc), + Prefix => New_Reference_To (P_Arr, Loc), Attribute_Name => Name_Unrestricted_Access)); - -- Build_Entry_Names generation flag. When set to true, the - -- runtime will allocate an array to hold the string names - -- of protected entries. + if Pkg_Id = System_Tasking_Protected_Objects_Entries then - if not Restricted_Profile then - if Entry_Names_OK then - Append_To (Args, - New_Reference_To (Standard_True, Loc)); - else - Append_To (Args, - New_Reference_To (Standard_False, Loc)); + -- Find index mapping function (clumsy but ok for now) + + while Ekind (P_Arr) /= E_Function loop + Next_Entity (P_Arr); + end loop; + + Append_To (Args, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (P_Arr, Loc), + Attribute_Name => Name_Unrestricted_Access)); + + -- Build_Entry_Names generation flag. When set to true, + -- the runtime will allocate an array to hold the string + -- names of protected entries. + + if not Restricted_Profile then + if Entry_Names_OK then + Append_To (Args, + New_Reference_To (Standard_True, Loc)); + else + Append_To (Args, + New_Reference_To (Standard_False, Loc)); + end if; end if; end if; - end if; - elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then - Append_To (Args, Make_Null (Loc)); + elsif Pkg_Id = + System_Tasking_Protected_Objects_Single_Entry + then + Append_To (Args, Make_Null (Loc)); - elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then - Append_To (Args, Make_Null (Loc)); - Append_To (Args, Make_Null (Loc)); - Append_To (Args, New_Reference_To (Standard_False, Loc)); - end if; + elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then + Append_To (Args, Make_Null (Loc)); + Append_To (Args, Make_Null (Loc)); + Append_To (Args, New_Reference_To (Standard_False, Loc)); + end if; + Append_To (L, + Make_Procedure_Call_Statement (Loc, + Name => New_Reference_To (RTE (Called_Subp), Loc), + Parameter_Associations => Args)); + end; + else Append_To (L, Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (Called_Subp), Loc), + Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc), Parameter_Associations => Args)); - end; - else - Append_To (L, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc), - Parameter_Associations => Args)); + end if; end if; if Has_Attach_Handler (Ptyp) then @@ -13868,15 +13663,18 @@ package body Exp_Ch9 is Parameter_Associations => Args)); else - -- First, prepends the _object argument + if not Uses_Lock_Free (Defining_Identifier (Pdec)) then + -- First, prepends the _object argument - Prepend_To (Args, - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Make_Identifier (Loc, Name_uInit), - Selector_Name => Make_Identifier (Loc, Name_uObject)), - Attribute_Name => Name_Unchecked_Access)); + Prepend_To (Args, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => Make_Identifier (Loc, Name_uInit), + Selector_Name => + Make_Identifier (Loc, Name_uObject)), + Attribute_Name => Name_Unchecked_Access)); + end if; -- Then, insert call to Install_Handlers |