* gimplify.c (find_single_pointer_decl_1): New static function.
[official-gcc.git] / gcc / ada / exp_ch9.adb
blob6911d862a594941acf8daec5204b19d79c9054cb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 9 --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Checks; use Checks;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Ch3; use Exp_Ch3;
33 with Exp_Ch11; use Exp_Ch11;
34 with Exp_Ch6; use Exp_Ch6;
35 with Exp_Dbug; use Exp_Dbug;
36 with Exp_Smem; use Exp_Smem;
37 with Exp_Tss; use Exp_Tss;
38 with Exp_Util; use Exp_Util;
39 with Freeze; use Freeze;
40 with Hostparm;
41 with Namet; use Namet;
42 with Nlists; use Nlists;
43 with Nmake; use Nmake;
44 with Opt; use Opt;
45 with Restrict; use Restrict;
46 with Rident; use Rident;
47 with Rtsfind; use Rtsfind;
48 with Sem; use Sem;
49 with Sem_Ch6; use Sem_Ch6;
50 with Sem_Ch8; use Sem_Ch8;
51 with Sem_Ch11; use Sem_Ch11;
52 with Sem_Elab; use Sem_Elab;
53 with Sem_Res; use Sem_Res;
54 with Sem_Util; use Sem_Util;
55 with Sinfo; use Sinfo;
56 with Snames; use Snames;
57 with Stand; use Stand;
58 with Targparm; use Targparm;
59 with Tbuild; use Tbuild;
60 with Uintp; use Uintp;
62 package body Exp_Ch9 is
64 --------------------------------
65 -- Select_Expansion_Utilities --
66 --------------------------------
68 -- The following package contains helper routines used in the expansion of
69 -- dispatching asynchronous, conditional and timed selects.
71 package Select_Expansion_Utilities is
72 function Build_Abort_Block
73 (Loc : Source_Ptr;
74 Blk_Ent : Entity_Id;
75 Blk : Node_Id) return Node_Id;
76 -- Generate:
77 -- begin
78 -- Blk
79 -- exception
80 -- when Abort_Signal => Abort_Undefer;
81 -- end;
82 -- Blk_Ent is the name of the encapsulated block, Blk is the actual
83 -- block node.
85 function Build_B
86 (Loc : Source_Ptr;
87 Decls : List_Id) return Entity_Id;
88 -- Generate:
89 -- B : Boolean := False;
90 -- Append the object declaration to the list and return the name of
91 -- the object.
93 function Build_C
94 (Loc : Source_Ptr;
95 Decls : List_Id) return Entity_Id;
96 -- Generate:
97 -- C : Ada.Tags.Prim_Op_Kind;
98 -- Append the object declaration to the list and return the name of
99 -- the object.
101 function Build_Cleanup_Block
102 (Loc : Source_Ptr;
103 Blk_Ent : Entity_Id;
104 Stmts : List_Id;
105 Clean_Ent : Entity_Id) return Node_Id;
106 -- Generate:
107 -- declare
108 -- procedure _clean is
109 -- begin
110 -- ...
111 -- end _clean;
112 -- begin
113 -- Stmts
114 -- at end
115 -- _clean;
116 -- end;
117 -- Blk_Ent is the name of the generated block, Stmts is the list
118 -- of encapsulated statements and Clean_Ent is the parameter to
119 -- the _clean procedure.
121 function Build_S
122 (Loc : Source_Ptr;
123 Decls : List_Id;
124 Call_Ent : Entity_Id) return Entity_Id;
125 -- Generate:
126 -- S : constant Integer := DT_Position (Call_Ent);
127 -- where Call_Ent is the entity of the dispatching call name. Append
128 -- the object declaration to the list and return the name of the
129 -- object.
131 function Build_Wrapping_Procedure
132 (Loc : Source_Ptr;
133 Nam : Character;
134 Decls : List_Id;
135 Stmts : List_Id) return Entity_Id;
136 -- Generate:
137 -- procedure <temp>Nam is
138 -- begin
139 -- Stmts
140 -- end <temp>Nam;
141 -- where Nam is the generated procedure name and Stmts are the
142 -- encapsulated statements. Append the procedure body to Decls.
143 -- Return the internally generated procedure name.
144 end Select_Expansion_Utilities;
146 package body Select_Expansion_Utilities is
148 -----------------------
149 -- Build_Abort_Block --
150 -----------------------
152 function Build_Abort_Block
153 (Loc : Source_Ptr;
154 Blk_Ent : Entity_Id;
155 Blk : Node_Id) return Node_Id
157 begin
158 return
159 Make_Block_Statement (Loc,
160 Declarations =>
161 No_List,
163 Handled_Statement_Sequence =>
164 Make_Handled_Sequence_Of_Statements (Loc,
165 Statements =>
166 New_List (
167 Make_Implicit_Label_Declaration (Loc,
168 Defining_Identifier =>
169 Blk_Ent,
170 Label_Construct =>
171 Blk),
172 Blk),
174 Exception_Handlers =>
175 New_List (
176 Make_Exception_Handler (Loc,
177 Exception_Choices =>
178 New_List (
179 New_Reference_To (Stand.Abort_Signal, Loc)),
180 Statements =>
181 New_List (
182 Make_Procedure_Call_Statement (Loc,
183 Name =>
184 New_Reference_To (RTE (
185 RE_Abort_Undefer), Loc),
186 Parameter_Associations => No_List))))));
187 end Build_Abort_Block;
189 -------------
190 -- Build_B --
191 -------------
193 function Build_B
194 (Loc : Source_Ptr;
195 Decls : List_Id) return Entity_Id
197 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
199 begin
200 Append_To (Decls,
201 Make_Object_Declaration (Loc,
202 Defining_Identifier =>
204 Object_Definition =>
205 New_Reference_To (Standard_Boolean, Loc),
206 Expression =>
207 New_Reference_To (Standard_False, Loc)));
209 return B;
210 end Build_B;
212 -------------
213 -- Build_C --
214 -------------
216 function Build_C
217 (Loc : Source_Ptr;
218 Decls : List_Id) return Entity_Id
220 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
222 begin
223 Append_To (Decls,
224 Make_Object_Declaration (Loc,
225 Defining_Identifier =>
227 Object_Definition =>
228 New_Reference_To (RTE (RE_Prim_Op_Kind), Loc)));
230 return C;
231 end Build_C;
233 -------------------------
234 -- Build_Cleanup_Block --
235 -------------------------
237 function Build_Cleanup_Block
238 (Loc : Source_Ptr;
239 Blk_Ent : Entity_Id;
240 Stmts : List_Id;
241 Clean_Ent : Entity_Id) return Node_Id
243 Cleanup_Block : constant Node_Id :=
244 Make_Block_Statement (Loc,
245 Identifier => New_Reference_To (Blk_Ent, Loc),
246 Declarations => No_List,
247 Handled_Statement_Sequence =>
248 Make_Handled_Sequence_Of_Statements (Loc,
249 Statements => Stmts),
250 Is_Asynchronous_Call_Block => True);
252 begin
253 Set_Entry_Cancel_Parameter (Blk_Ent, Clean_Ent);
255 return Cleanup_Block;
256 end Build_Cleanup_Block;
258 -------------
259 -- Build_S --
260 -------------
262 function Build_S
263 (Loc : Source_Ptr;
264 Decls : List_Id;
265 Call_Ent : Entity_Id) return Entity_Id
267 S : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uS);
269 begin
270 Append_To (Decls,
271 Make_Object_Declaration (Loc,
272 Defining_Identifier => S,
273 Constant_Present => True,
274 Object_Definition =>
275 New_Reference_To (Standard_Integer, Loc),
276 Expression =>
277 Make_Integer_Literal (Loc,
278 Intval => DT_Position (Call_Ent))));
280 return S;
281 end Build_S;
283 ------------------------------
284 -- Build_Wrapping_Procedure --
285 ------------------------------
287 function Build_Wrapping_Procedure
288 (Loc : Source_Ptr;
289 Nam : Character;
290 Decls : List_Id;
291 Stmts : List_Id) return Entity_Id
293 Proc_Nam : constant Entity_Id :=
294 Make_Defining_Identifier (Loc, New_Internal_Name (Nam));
295 begin
296 Append_To (Decls,
297 Make_Subprogram_Body (Loc,
298 Specification =>
299 Make_Procedure_Specification (Loc,
300 Defining_Unit_Name =>
301 Proc_Nam),
302 Declarations =>
303 No_List,
304 Handled_Statement_Sequence =>
305 Make_Handled_Sequence_Of_Statements (Loc,
306 Statements =>
307 New_Copy_List (Stmts))));
309 return Proc_Nam;
310 end Build_Wrapping_Procedure;
311 end Select_Expansion_Utilities;
313 package SEU renames Select_Expansion_Utilities;
315 -----------------------
316 -- Local Subprograms --
317 -----------------------
319 function Actual_Index_Expression
320 (Sloc : Source_Ptr;
321 Ent : Entity_Id;
322 Index : Node_Id;
323 Tsk : Entity_Id) return Node_Id;
324 -- Compute the index position for an entry call. Tsk is the target
325 -- task. If the bounds of some entry family depend on discriminants,
326 -- the expression computed by this function uses the discriminants
327 -- of the target task.
329 procedure Add_Object_Pointer
330 (Decls : List_Id;
331 Pid : Entity_Id;
332 Loc : Source_Ptr);
333 -- Prepend an object pointer declaration to the declaration list
334 -- Decls. This object pointer is initialized to a type conversion
335 -- of the System.Address pointer passed to entry barrier functions
336 -- and entry body procedures.
338 function Build_Accept_Body (Astat : Node_Id) return Node_Id;
339 -- Transform accept statement into a block with added exception handler.
340 -- Used both for simple accept statements and for accept alternatives in
341 -- select statements. Astat is the accept statement.
343 function Build_Barrier_Function
344 (N : Node_Id;
345 Ent : Entity_Id;
346 Pid : Node_Id) return Node_Id;
347 -- Build the function body returning the value of the barrier expression
348 -- for the specified entry body.
350 function Build_Barrier_Function_Specification
351 (Def_Id : Entity_Id;
352 Loc : Source_Ptr) return Node_Id;
353 -- Build a specification for a function implementing
354 -- the protected entry barrier of the specified entry body.
356 function Build_Corresponding_Record
357 (N : Node_Id;
358 Ctyp : Node_Id;
359 Loc : Source_Ptr) return Node_Id;
360 -- Common to tasks and protected types. Copy discriminant specifications,
361 -- build record declaration. N is the type declaration, Ctyp is the
362 -- concurrent entity (task type or protected type).
364 function Build_Entry_Count_Expression
365 (Concurrent_Type : Node_Id;
366 Component_List : List_Id;
367 Loc : Source_Ptr) return Node_Id;
368 -- Compute number of entries for concurrent object. This is a count of
369 -- simple entries, followed by an expression that computes the length
370 -- of the range of each entry family. A single array with that size is
371 -- allocated for each concurrent object of the type.
373 function Build_Parameter_Block
374 (Loc : Source_Ptr;
375 Actuals : List_Id;
376 Formals : List_Id;
377 Decls : List_Id) return Entity_Id;
378 -- Generate an access type for each actual parameter in the list Actuals.
379 -- Cleate an encapsulating record that contains all the actuals and return
380 -- its type. Generate:
381 -- type Ann1 is access all <actual1-type>
382 -- ...
383 -- type AnnN is access all <actualN-type>
384 -- type Pnn is record
385 -- <formal1> : Ann1;
386 -- ...
387 -- <formalN> : AnnN;
388 -- end record;
390 function Build_Wrapper_Body
391 (Loc : Source_Ptr;
392 Proc_Nam : Entity_Id;
393 Obj_Typ : Entity_Id;
394 Formals : List_Id) return Node_Id;
395 -- Ada 2005 (AI-345): Build the body that wraps a primitive operation
396 -- associated with a protected or task type. This is required to implement
397 -- dispatching calls through interfaces. Proc_Nam is the entry name to be
398 -- wrapped, Obj_Typ is the type of the newly added formal parameter to
399 -- handle object notation, Formals are the original entry formals that will
400 -- be explicitly replicated.
402 function Build_Wrapper_Spec
403 (Loc : Source_Ptr;
404 Proc_Nam : Entity_Id;
405 Obj_Typ : Entity_Id;
406 Formals : List_Id) return Node_Id;
407 -- Ada 2005 (AI-345): Build the specification of a primitive operation
408 -- associated with a protected or task type. This is required implement
409 -- dispatching calls through interfaces. Proc_Nam is the entry name to be
410 -- wrapped, Obj_Typ is the type of the newly added formal parameter to
411 -- handle object notation, Formals are the original entry formals that will
412 -- be explicitly replicated.
414 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
415 -- Build the function that translates the entry index in the call
416 -- (which depends on the size of entry families) into an index into the
417 -- Entry_Bodies_Array, to determine the body and barrier function used
418 -- in a protected entry call. A pointer to this function appears in every
419 -- protected object.
421 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
422 -- Build subprogram declaration for previous one
424 function Build_Protected_Entry
425 (N : Node_Id;
426 Ent : Entity_Id;
427 Pid : Node_Id) return Node_Id;
428 -- Build the procedure implementing the statement sequence of
429 -- the specified entry body.
431 function Build_Protected_Entry_Specification
432 (Def_Id : Entity_Id;
433 Ent_Id : Entity_Id;
434 Loc : Source_Ptr) return Node_Id;
435 -- Build a specification for a procedure implementing
436 -- the statement sequence of the specified entry body.
437 -- Add attributes associating it with the entry defining identifier
438 -- Ent_Id.
440 function Build_Protected_Subprogram_Body
441 (N : Node_Id;
442 Pid : Node_Id;
443 N_Op_Spec : Node_Id) return Node_Id;
444 -- This function is used to construct the protected version of a protected
445 -- subprogram. Its statement sequence first defers abort, then locks
446 -- the associated protected object, and then enters a block that contains
447 -- a call to the unprotected version of the subprogram (for details, see
448 -- Build_Unprotected_Subprogram_Body). This block statement requires
449 -- a cleanup handler that unlocks the object in all cases.
450 -- (see Exp_Ch7.Expand_Cleanup_Actions).
452 function Build_Protected_Spec
453 (N : Node_Id;
454 Obj_Type : Entity_Id;
455 Unprotected : Boolean := False;
456 Ident : Entity_Id) return List_Id;
457 -- Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
458 -- Subprogram_Type. Builds signature of protected subprogram, adding the
459 -- formal that corresponds to the object itself. For an access to protected
460 -- subprogram, there is no object type to specify, so the additional
461 -- parameter has type Address and mode In. An indirect call through such
462 -- a pointer converts the address to a reference to the actual object.
463 -- The object is a limited record and therefore a by_reference type.
465 function Build_Selected_Name
466 (Prefix, Selector : Name_Id;
467 Append_Char : Character := ' ') return Name_Id;
468 -- Build a name in the form of Prefix__Selector, with an optional
469 -- character appended. This is used for internal subprograms generated
470 -- for operations of protected types, including barrier functions.
471 -- For the subprograms generated for entry bodies and entry barriers,
472 -- the generated name includes a sequence number that makes names
473 -- unique in the presence of entry overloading. This is necessary
474 -- because entry body procedures and barrier functions all have the
475 -- same signature.
477 procedure Build_Simple_Entry_Call
478 (N : Node_Id;
479 Concval : Node_Id;
480 Ename : Node_Id;
481 Index : Node_Id);
482 -- Some comments here would be useful ???
484 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
485 -- This routine constructs a specification for the procedure that we will
486 -- build for the task body for task type T. The spec has the form:
488 -- procedure tnameB (_Task : access tnameV);
490 -- where name is the character name taken from the task type entity that
491 -- is passed as the argument to the procedure, and tnameV is the task
492 -- value type that is associated with the task type.
494 function Build_Unprotected_Subprogram_Body
495 (N : Node_Id;
496 Pid : Node_Id) return Node_Id;
497 -- This routine constructs the unprotected version of a protected
498 -- subprogram body, which is contains all of the code in the
499 -- original, unexpanded body. This is the version of the protected
500 -- subprogram that is called from all protected operations on the same
501 -- object, including the protected version of the same subprogram.
503 procedure Collect_Entry_Families
504 (Loc : Source_Ptr;
505 Cdecls : List_Id;
506 Current_Node : in out Node_Id;
507 Conctyp : Entity_Id);
508 -- For each entry family in a concurrent type, create an anonymous array
509 -- type of the right size, and add a component to the corresponding_record.
511 function Family_Offset
512 (Loc : Source_Ptr;
513 Hi : Node_Id;
514 Lo : Node_Id;
515 Ttyp : Entity_Id) return Node_Id;
516 -- Compute (Hi - Lo) for two entry family indices. Hi is the index in
517 -- an accept statement, or the upper bound in the discrete subtype of
518 -- an entry declaration. Lo is the corresponding lower bound. Ttyp is
519 -- the concurrent type of the entry.
521 function Family_Size
522 (Loc : Source_Ptr;
523 Hi : Node_Id;
524 Lo : Node_Id;
525 Ttyp : Entity_Id) return Node_Id;
526 -- Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in
527 -- a family, and handle properly the superflat case. This is equivalent
528 -- to the use of 'Length on the index type, but must use Family_Offset
529 -- to handle properly the case of bounds that depend on discriminants.
531 procedure Extract_Dispatching_Call
532 (N : Node_Id;
533 Call_Ent : out Entity_Id;
534 Object : out Entity_Id;
535 Actuals : out List_Id;
536 Formals : out List_Id);
537 -- Given a dispatching call, extract the entity of the name of the call,
538 -- its object parameter, its actual parameters and the formal parameters
539 -- of the overriden interface-level version.
541 procedure Extract_Entry
542 (N : Node_Id;
543 Concval : out Node_Id;
544 Ename : out Node_Id;
545 Index : out Node_Id);
546 -- Given an entry call, returns the associated concurrent object,
547 -- the entry name, and the entry family index.
549 function Find_Task_Or_Protected_Pragma
550 (T : Node_Id;
551 P : Name_Id) return Node_Id;
552 -- Searches the task or protected definition T for the first occurrence
553 -- of the pragma whose name is given by P. The caller has ensured that
554 -- the pragma is present in the task definition. A special case is that
555 -- when P is Name_uPriority, the call will also find Interrupt_Priority.
556 -- ??? Should be implemented with the rep item chain mechanism.
558 function Index_Constant_Declaration
559 (N : Node_Id;
560 Index_Id : Entity_Id;
561 Prot : Entity_Id) return List_Id;
562 -- For an entry family and its barrier function, we define a local entity
563 -- that maps the index in the call into the entry index into the object:
565 -- I : constant Index_Type := Index_Type'Val (
566 -- E - <<index of first family member>> +
567 -- Protected_Entry_Index (Index_Type'Pos (Index_Type'First)));
569 function Parameter_Block_Pack
570 (Loc : Source_Ptr;
571 Blk_Typ : Entity_Id;
572 Actuals : List_Id;
573 Formals : List_Id;
574 Decls : List_Id;
575 Stmts : List_Id) return Node_Id;
576 -- Set the components of the generated parameter block with the values of
577 -- the actual parameters. Generate aliased temporaries to capture the
578 -- values for types that are passed by copy. Otherwise generate a reference
579 -- to the actual's value. Return the address of the aggregate block.
580 -- Generate:
581 -- Jnn1 : alias <formal-type1>;
582 -- Jnn1 := <actual1>;
583 -- ...
584 -- P : Blk_Typ := (
585 -- Jnn1'unchecked_access;
586 -- <actual2>'reference;
587 -- ...);
589 function Parameter_Block_Unpack
590 (Loc : Source_Ptr;
591 Actuals : List_Id;
592 Formals : List_Id) return List_Id;
593 -- Retrieve the values of the components from the parameter block and
594 -- assign then to the original actual parameters. Generate:
595 -- <actual1> := P.<formal1>;
596 -- ...
597 -- <actualN> := P.<formalN>;
599 procedure Update_Prival_Subtypes (N : Node_Id);
600 -- The actual subtypes of the privals will differ from the type of the
601 -- private declaration in the original protected type, if the protected
602 -- type has discriminants or if the prival has constrained components.
603 -- This is because the privals are generated out of sequence w.r.t. the
604 -- analysis of a protected body. After generating the bodies for protected
605 -- operations, we set correctly the type of all references to privals, by
606 -- means of a recursive tree traversal, which is heavy-handed but
607 -- correct.
609 -----------------------------
610 -- Actual_Index_Expression --
611 -----------------------------
613 function Actual_Index_Expression
614 (Sloc : Source_Ptr;
615 Ent : Entity_Id;
616 Index : Node_Id;
617 Tsk : Entity_Id) return Node_Id
619 Ttyp : constant Entity_Id := Etype (Tsk);
620 Expr : Node_Id;
621 Num : Node_Id;
622 Lo : Node_Id;
623 Hi : Node_Id;
624 Prev : Entity_Id;
625 S : Node_Id;
627 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
628 -- Compute difference between bounds of entry family
630 --------------------------
631 -- Actual_Family_Offset --
632 --------------------------
634 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
636 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
637 -- Replace a reference to a discriminant with a selected component
638 -- denoting the discriminant of the target task.
640 -----------------------------
641 -- Actual_Discriminant_Ref --
642 -----------------------------
644 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
645 Typ : constant Entity_Id := Etype (Bound);
646 B : Node_Id;
648 begin
649 if not Is_Entity_Name (Bound)
650 or else Ekind (Entity (Bound)) /= E_Discriminant
651 then
652 if Nkind (Bound) = N_Attribute_Reference then
653 return Bound;
654 else
655 B := New_Copy_Tree (Bound);
656 end if;
658 else
659 B :=
660 Make_Selected_Component (Sloc,
661 Prefix => New_Copy_Tree (Tsk),
662 Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
664 Analyze_And_Resolve (B, Typ);
665 end if;
667 return
668 Make_Attribute_Reference (Sloc,
669 Attribute_Name => Name_Pos,
670 Prefix => New_Occurrence_Of (Etype (Bound), Sloc),
671 Expressions => New_List (B));
672 end Actual_Discriminant_Ref;
674 -- Start of processing for Actual_Family_Offset
676 begin
677 return
678 Make_Op_Subtract (Sloc,
679 Left_Opnd => Actual_Discriminant_Ref (Hi),
680 Right_Opnd => Actual_Discriminant_Ref (Lo));
681 end Actual_Family_Offset;
683 -- Start of processing for Actual_Index_Expression
685 begin
686 -- The queues of entries and entry families appear in textual
687 -- order in the associated record. The entry index is computed as
688 -- the sum of the number of queues for all entries that precede the
689 -- designated one, to which is added the index expression, if this
690 -- expression denotes a member of a family.
692 -- The following is a place holder for the count of simple entries
694 Num := Make_Integer_Literal (Sloc, 1);
696 -- We construct an expression which is a series of addition
697 -- operations. See comments in Entry_Index_Expression, which is
698 -- identical in structure.
700 if Present (Index) then
701 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
703 Expr :=
704 Make_Op_Add (Sloc,
705 Left_Opnd => Num,
707 Right_Opnd =>
708 Actual_Family_Offset (
709 Make_Attribute_Reference (Sloc,
710 Attribute_Name => Name_Pos,
711 Prefix => New_Reference_To (Base_Type (S), Sloc),
712 Expressions => New_List (Relocate_Node (Index))),
713 Type_Low_Bound (S)));
714 else
715 Expr := Num;
716 end if;
718 -- Now add lengths of preceding entries and entry families
720 Prev := First_Entity (Ttyp);
722 while Chars (Prev) /= Chars (Ent)
723 or else (Ekind (Prev) /= Ekind (Ent))
724 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
725 loop
726 if Ekind (Prev) = E_Entry then
727 Set_Intval (Num, Intval (Num) + 1);
729 elsif Ekind (Prev) = E_Entry_Family then
730 S :=
731 Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
732 Lo := Type_Low_Bound (S);
733 Hi := Type_High_Bound (S);
735 Expr :=
736 Make_Op_Add (Sloc,
737 Left_Opnd => Expr,
738 Right_Opnd =>
739 Make_Op_Add (Sloc,
740 Left_Opnd =>
741 Actual_Family_Offset (Hi, Lo),
742 Right_Opnd =>
743 Make_Integer_Literal (Sloc, 1)));
745 -- Other components are anonymous types to be ignored
747 else
748 null;
749 end if;
751 Next_Entity (Prev);
752 end loop;
754 return Expr;
755 end Actual_Index_Expression;
757 ----------------------------------
758 -- Add_Discriminal_Declarations --
759 ----------------------------------
761 procedure Add_Discriminal_Declarations
762 (Decls : List_Id;
763 Typ : Entity_Id;
764 Name : Name_Id;
765 Loc : Source_Ptr)
767 D : Entity_Id;
769 begin
770 if Has_Discriminants (Typ) then
771 D := First_Discriminant (Typ);
773 while Present (D) loop
775 Prepend_To (Decls,
776 Make_Object_Renaming_Declaration (Loc,
777 Defining_Identifier => Discriminal (D),
778 Subtype_Mark => New_Reference_To (Etype (D), Loc),
779 Name =>
780 Make_Selected_Component (Loc,
781 Prefix => Make_Identifier (Loc, Name),
782 Selector_Name => Make_Identifier (Loc, Chars (D)))));
784 Next_Discriminant (D);
785 end loop;
786 end if;
787 end Add_Discriminal_Declarations;
789 ------------------------
790 -- Add_Object_Pointer --
791 ------------------------
793 procedure Add_Object_Pointer
794 (Decls : List_Id;
795 Pid : Entity_Id;
796 Loc : Source_Ptr)
798 Obj_Ptr : Node_Id;
800 begin
801 -- Prepend the declaration of _object. This must be first in the
802 -- declaration list, since it is used by the discriminal and
803 -- prival declarations.
804 -- ??? An attempt to make this a renaming was unsuccessful.
806 -- type poVP is access poV;
807 -- _object : poVP := poVP!O;
809 Obj_Ptr :=
810 Make_Defining_Identifier (Loc,
811 Chars =>
812 New_External_Name
813 (Chars (Corresponding_Record_Type (Pid)), 'P'));
815 Prepend_To (Decls,
816 Make_Object_Declaration (Loc,
817 Defining_Identifier =>
818 Make_Defining_Identifier (Loc, Name_uObject),
819 Object_Definition => New_Reference_To (Obj_Ptr, Loc),
820 Expression =>
821 Unchecked_Convert_To (Obj_Ptr,
822 Make_Identifier (Loc, Name_uO))));
824 Prepend_To (Decls,
825 Make_Full_Type_Declaration (Loc,
826 Defining_Identifier => Obj_Ptr,
827 Type_Definition => Make_Access_To_Object_Definition (Loc,
828 Subtype_Indication =>
829 New_Reference_To (Corresponding_Record_Type (Pid), Loc))));
830 end Add_Object_Pointer;
832 ------------------------------
833 -- Add_Private_Declarations --
834 ------------------------------
836 procedure Add_Private_Declarations
837 (Decls : List_Id;
838 Typ : Entity_Id;
839 Name : Name_Id;
840 Loc : Source_Ptr)
842 Def : constant Node_Id := Protected_Definition (Parent (Typ));
843 Body_Ent : constant Entity_Id := Corresponding_Body (Parent (Typ));
844 P : Node_Id;
845 Pdef : Entity_Id;
847 begin
848 pragma Assert (Nkind (Def) = N_Protected_Definition);
850 if Present (Private_Declarations (Def)) then
851 P := First (Private_Declarations (Def));
853 while Present (P) loop
854 if Nkind (P) = N_Component_Declaration then
855 Pdef := Defining_Identifier (P);
856 Prepend_To (Decls,
857 Make_Object_Renaming_Declaration (Loc,
858 Defining_Identifier => Prival (Pdef),
859 Subtype_Mark => New_Reference_To (Etype (Pdef), Loc),
860 Name =>
861 Make_Selected_Component (Loc,
862 Prefix => Make_Identifier (Loc, Name),
863 Selector_Name => Make_Identifier (Loc, Chars (Pdef)))));
864 end if;
865 Next (P);
866 end loop;
867 end if;
869 -- One more "prival" for the object itself, with the right protection
870 -- type.
872 declare
873 Protection_Type : RE_Id;
874 begin
875 if Has_Attach_Handler (Typ) then
876 if Restricted_Profile then
877 if Has_Entries (Typ) then
878 Protection_Type := RE_Protection_Entry;
879 else
880 Protection_Type := RE_Protection;
881 end if;
882 else
883 Protection_Type := RE_Static_Interrupt_Protection;
884 end if;
886 elsif Has_Interrupt_Handler (Typ) then
887 Protection_Type := RE_Dynamic_Interrupt_Protection;
889 -- The type has explicit entries or generated primitive entry
890 -- wrappers.
892 elsif Has_Entries (Typ)
893 or else (Ada_Version >= Ada_05
894 and then Present (Interface_List (Parent (Typ))))
895 then
896 if Abort_Allowed
897 or else Restriction_Active (No_Entry_Queue) = False
898 or else Number_Entries (Typ) > 1
899 then
900 Protection_Type := RE_Protection_Entries;
901 else
902 Protection_Type := RE_Protection_Entry;
903 end if;
905 else
906 Protection_Type := RE_Protection;
907 end if;
909 Prepend_To (Decls,
910 Make_Object_Renaming_Declaration (Loc,
911 Defining_Identifier => Object_Ref (Body_Ent),
912 Subtype_Mark => New_Reference_To (RTE (Protection_Type), Loc),
913 Name =>
914 Make_Selected_Component (Loc,
915 Prefix => Make_Identifier (Loc, Name),
916 Selector_Name => Make_Identifier (Loc, Name_uObject))));
917 end;
918 end Add_Private_Declarations;
920 -----------------------
921 -- Build_Accept_Body --
922 -----------------------
924 function Build_Accept_Body (Astat : Node_Id) return Node_Id is
925 Loc : constant Source_Ptr := Sloc (Astat);
926 Stats : constant Node_Id := Handled_Statement_Sequence (Astat);
927 New_S : Node_Id;
928 Hand : Node_Id;
929 Call : Node_Id;
930 Ohandle : Node_Id;
932 begin
933 -- At the end of the statement sequence, Complete_Rendezvous is called.
934 -- A label skipping the Complete_Rendezvous, and all other
935 -- accept processing, has already been added for the expansion
936 -- of requeue statements.
938 Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
939 Insert_Before (Last (Statements (Stats)), Call);
940 Analyze (Call);
942 -- If exception handlers are present, then append Complete_Rendezvous
943 -- calls to the handlers, and construct the required outer block.
945 if Present (Exception_Handlers (Stats)) then
946 Hand := First (Exception_Handlers (Stats));
948 while Present (Hand) loop
949 Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
950 Append (Call, Statements (Hand));
951 Analyze (Call);
952 Next (Hand);
953 end loop;
955 New_S :=
956 Make_Handled_Sequence_Of_Statements (Loc,
957 Statements => New_List (
958 Make_Block_Statement (Loc,
959 Handled_Statement_Sequence => Stats)));
961 else
962 New_S := Stats;
963 end if;
965 -- At this stage we know that the new statement sequence does not
966 -- have an exception handler part, so we supply one to call
967 -- Exceptional_Complete_Rendezvous. This handler is
969 -- when all others =>
970 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
972 -- We handle Abort_Signal to make sure that we properly catch the abort
973 -- case and wake up the caller.
975 Ohandle := Make_Others_Choice (Loc);
976 Set_All_Others (Ohandle);
978 Set_Exception_Handlers (New_S,
979 New_List (
980 Make_Exception_Handler (Loc,
981 Exception_Choices => New_List (Ohandle),
983 Statements => New_List (
984 Make_Procedure_Call_Statement (Loc,
985 Name => New_Reference_To (
986 RTE (RE_Exceptional_Complete_Rendezvous), Loc),
987 Parameter_Associations => New_List (
988 Make_Function_Call (Loc,
989 Name => New_Reference_To (
990 RTE (RE_Get_GNAT_Exception), Loc))))))));
992 Set_Parent (New_S, Astat); -- temp parent for Analyze call
993 Analyze_Exception_Handlers (Exception_Handlers (New_S));
994 Expand_Exception_Handlers (New_S);
996 -- Exceptional_Complete_Rendezvous must be called with abort
997 -- still deferred, which is the case for a "when all others" handler.
999 return New_S;
1000 end Build_Accept_Body;
1002 -----------------------------------
1003 -- Build_Activation_Chain_Entity --
1004 -----------------------------------
1006 procedure Build_Activation_Chain_Entity (N : Node_Id) is
1007 P : Node_Id;
1008 B : Node_Id;
1009 Decls : List_Id;
1011 begin
1012 -- Loop to find enclosing construct containing activation chain variable
1014 P := Parent (N);
1016 while Nkind (P) /= N_Subprogram_Body
1017 and then Nkind (P) /= N_Package_Declaration
1018 and then Nkind (P) /= N_Package_Body
1019 and then Nkind (P) /= N_Block_Statement
1020 and then Nkind (P) /= N_Task_Body
1021 loop
1022 P := Parent (P);
1023 end loop;
1025 -- If we are in a package body, the activation chain variable is
1026 -- allocated in the corresponding spec. First, we save the package
1027 -- body node because we enter the new entity in its Declarations list.
1029 B := P;
1031 if Nkind (P) = N_Package_Body then
1032 P := Unit_Declaration_Node (Corresponding_Spec (P));
1033 Decls := Declarations (B);
1035 elsif Nkind (P) = N_Package_Declaration then
1036 Decls := Visible_Declarations (Specification (B));
1038 else
1039 Decls := Declarations (B);
1040 end if;
1042 -- If activation chain entity not already declared, declare it
1044 if No (Activation_Chain_Entity (P)) then
1045 Set_Activation_Chain_Entity
1046 (P, Make_Defining_Identifier (Sloc (N), Name_uChain));
1048 Prepend_To (Decls,
1049 Make_Object_Declaration (Sloc (P),
1050 Defining_Identifier => Activation_Chain_Entity (P),
1051 Aliased_Present => True,
1052 Object_Definition =>
1053 New_Reference_To (RTE (RE_Activation_Chain), Sloc (P))));
1055 Analyze (First (Decls));
1056 end if;
1057 end Build_Activation_Chain_Entity;
1059 ----------------------------
1060 -- Build_Barrier_Function --
1061 ----------------------------
1063 function Build_Barrier_Function
1064 (N : Node_Id;
1065 Ent : Entity_Id;
1066 Pid : Node_Id) return Node_Id
1068 Loc : constant Source_Ptr := Sloc (N);
1069 Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
1070 Index_Spec : constant Node_Id := Entry_Index_Specification
1071 (Ent_Formals);
1072 Op_Decls : constant List_Id := New_List;
1073 Bdef : Entity_Id;
1074 Bspec : Node_Id;
1076 begin
1077 Bdef :=
1078 Make_Defining_Identifier (Loc, Chars (Barrier_Function (Ent)));
1079 Bspec := Build_Barrier_Function_Specification (Bdef, Loc);
1081 -- <object pointer declaration>
1082 -- <discriminant renamings>
1083 -- <private object renamings>
1084 -- Add discriminal and private renamings. These names have
1085 -- already been used to expand references to discriminants
1086 -- and private data.
1088 Add_Discriminal_Declarations (Op_Decls, Pid, Name_uObject, Loc);
1089 Add_Private_Declarations (Op_Decls, Pid, Name_uObject, Loc);
1090 Add_Object_Pointer (Op_Decls, Pid, Loc);
1092 -- If this is the barrier for an entry family, the entry index is
1093 -- visible in the body of the barrier. Create a local variable that
1094 -- converts the entry index (which is the last formal of the barrier
1095 -- function) into the appropriate offset into the entry array. The
1096 -- entry index constant must be set, as for the entry body, so that
1097 -- local references to the entry index are correctly replaced with
1098 -- the local variable. This parallels what is done for entry bodies.
1100 if Present (Index_Spec) then
1101 declare
1102 Index_Id : constant Entity_Id := Defining_Identifier (Index_Spec);
1103 Index_Con : constant Entity_Id :=
1104 Make_Defining_Identifier (Loc,
1105 Chars => New_Internal_Name ('J'));
1107 begin
1108 Set_Entry_Index_Constant (Index_Id, Index_Con);
1109 Append_List_To (Op_Decls,
1110 Index_Constant_Declaration (N, Index_Id, Pid));
1111 end;
1112 end if;
1114 -- Note: the condition in the barrier function needs to be properly
1115 -- processed for the C/Fortran boolean possibility, but this happens
1116 -- automatically since the return statement does this normalization.
1118 return
1119 Make_Subprogram_Body (Loc,
1120 Specification => Bspec,
1121 Declarations => Op_Decls,
1122 Handled_Statement_Sequence =>
1123 Make_Handled_Sequence_Of_Statements (Loc,
1124 Statements => New_List (
1125 Make_Return_Statement (Loc,
1126 Expression => Condition (Ent_Formals)))));
1127 end Build_Barrier_Function;
1129 ------------------------------------------
1130 -- Build_Barrier_Function_Specification --
1131 ------------------------------------------
1133 function Build_Barrier_Function_Specification
1134 (Def_Id : Entity_Id;
1135 Loc : Source_Ptr) return Node_Id
1137 begin
1138 Set_Needs_Debug_Info (Def_Id);
1139 return Make_Function_Specification (Loc,
1140 Defining_Unit_Name => Def_Id,
1141 Parameter_Specifications => New_List (
1142 Make_Parameter_Specification (Loc,
1143 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
1144 Parameter_Type =>
1145 New_Reference_To (RTE (RE_Address), Loc)),
1147 Make_Parameter_Specification (Loc,
1148 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uE),
1149 Parameter_Type =>
1150 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
1152 Result_Definition => New_Reference_To (Standard_Boolean, Loc));
1153 end Build_Barrier_Function_Specification;
1155 --------------------------
1156 -- Build_Call_With_Task --
1157 --------------------------
1159 function Build_Call_With_Task
1160 (N : Node_Id;
1161 E : Entity_Id) return Node_Id
1163 Loc : constant Source_Ptr := Sloc (N);
1165 begin
1166 return
1167 Make_Function_Call (Loc,
1168 Name => New_Reference_To (E, Loc),
1169 Parameter_Associations => New_List (Concurrent_Ref (N)));
1170 end Build_Call_With_Task;
1172 --------------------------------
1173 -- Build_Corresponding_Record --
1174 --------------------------------
1176 function Build_Corresponding_Record
1177 (N : Node_Id;
1178 Ctyp : Entity_Id;
1179 Loc : Source_Ptr) return Node_Id
1181 Rec_Ent : constant Entity_Id :=
1182 Make_Defining_Identifier
1183 (Loc, New_External_Name (Chars (Ctyp), 'V'));
1184 Disc : Entity_Id;
1185 Dlist : List_Id;
1186 New_Disc : Entity_Id;
1187 Cdecls : List_Id;
1189 begin
1190 Set_Corresponding_Record_Type (Ctyp, Rec_Ent);
1191 Set_Ekind (Rec_Ent, E_Record_Type);
1192 Set_Has_Delayed_Freeze (Rec_Ent, Has_Delayed_Freeze (Ctyp));
1193 Set_Is_Concurrent_Record_Type (Rec_Ent, True);
1194 Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
1195 Set_Stored_Constraint (Rec_Ent, No_Elist);
1196 Cdecls := New_List;
1198 -- Use discriminals to create list of discriminants for record, and
1199 -- create new discriminals for use in default expressions, etc. It is
1200 -- worth noting that a task discriminant gives rise to 5 entities;
1202 -- a) The original discriminant.
1203 -- b) The discriminal for use in the task.
1204 -- c) The discriminant of the corresponding record.
1205 -- d) The discriminal for the init proc of the corresponding record.
1206 -- e) The local variable that renames the discriminant in the procedure
1207 -- for the task body.
1209 -- In fact the discriminals b) are used in the renaming declarations
1210 -- for e). See details in einfo (Handling of Discriminants).
1212 if Present (Discriminant_Specifications (N)) then
1213 Dlist := New_List;
1214 Disc := First_Discriminant (Ctyp);
1216 while Present (Disc) loop
1217 New_Disc := CR_Discriminant (Disc);
1219 Append_To (Dlist,
1220 Make_Discriminant_Specification (Loc,
1221 Defining_Identifier => New_Disc,
1222 Discriminant_Type =>
1223 New_Occurrence_Of (Etype (Disc), Loc),
1224 Expression =>
1225 New_Copy (Discriminant_Default_Value (Disc))));
1227 Next_Discriminant (Disc);
1228 end loop;
1230 else
1231 Dlist := No_List;
1232 end if;
1234 -- Now we can construct the record type declaration. Note that this
1235 -- record is "limited tagged". It is "limited" to reflect the underlying
1236 -- limitedness of the task or protected object that it represents, and
1237 -- ensuring for example that it is properly passed by reference. It is
1238 -- "tagged" to give support to dispatching calls through interfaces (Ada
1239 -- 2005: AI-345)
1241 return
1242 Make_Full_Type_Declaration (Loc,
1243 Defining_Identifier => Rec_Ent,
1244 Discriminant_Specifications => Dlist,
1245 Type_Definition =>
1246 Make_Record_Definition (Loc,
1247 Component_List =>
1248 Make_Component_List (Loc,
1249 Component_Items => Cdecls),
1250 Tagged_Present => Ada_Version >= Ada_05,
1251 Limited_Present => True));
1252 end Build_Corresponding_Record;
1254 ----------------------------------
1255 -- Build_Entry_Count_Expression --
1256 ----------------------------------
1258 function Build_Entry_Count_Expression
1259 (Concurrent_Type : Node_Id;
1260 Component_List : List_Id;
1261 Loc : Source_Ptr) return Node_Id
1263 Eindx : Nat;
1264 Ent : Entity_Id;
1265 Ecount : Node_Id;
1266 Comp : Node_Id;
1267 Lo : Node_Id;
1268 Hi : Node_Id;
1269 Typ : Entity_Id;
1271 begin
1272 Ent := First_Entity (Concurrent_Type);
1273 Eindx := 0;
1275 -- Count number of non-family entries
1277 while Present (Ent) loop
1278 if Ekind (Ent) = E_Entry then
1279 Eindx := Eindx + 1;
1280 end if;
1282 Next_Entity (Ent);
1283 end loop;
1285 Ecount := Make_Integer_Literal (Loc, Eindx);
1287 -- Loop through entry families building the addition nodes
1289 Ent := First_Entity (Concurrent_Type);
1290 Comp := First (Component_List);
1292 while Present (Ent) loop
1293 if Ekind (Ent) = E_Entry_Family then
1294 while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
1295 Next (Comp);
1296 end loop;
1298 Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1299 Hi := Type_High_Bound (Typ);
1300 Lo := Type_Low_Bound (Typ);
1302 Ecount :=
1303 Make_Op_Add (Loc,
1304 Left_Opnd => Ecount,
1305 Right_Opnd => Family_Size (Loc, Hi, Lo, Concurrent_Type));
1306 end if;
1308 Next_Entity (Ent);
1309 end loop;
1311 return Ecount;
1312 end Build_Entry_Count_Expression;
1314 ---------------------------
1315 -- Build_Parameter_Block --
1316 ---------------------------
1318 function Build_Parameter_Block
1319 (Loc : Source_Ptr;
1320 Actuals : List_Id;
1321 Formals : List_Id;
1322 Decls : List_Id) return Entity_Id
1324 Actual : Entity_Id;
1325 Comp_Nam : Node_Id;
1326 Comp_Rec : Node_Id;
1327 Comps : List_Id;
1328 Formal : Entity_Id;
1330 begin
1331 Actual := First (Actuals);
1332 Comps := New_List;
1333 Formal := Defining_Identifier (First (Formals));
1334 while Present (Actual) loop
1335 -- Generate:
1336 -- type Ann is access all <actual-type>
1338 Comp_Nam :=
1339 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
1341 Append_To (Decls,
1342 Make_Full_Type_Declaration (Loc,
1343 Defining_Identifier =>
1344 Comp_Nam,
1345 Type_Definition =>
1346 Make_Access_To_Object_Definition (Loc,
1347 All_Present =>
1348 True,
1349 Constant_Present =>
1350 Ekind (Formal) = E_In_Parameter,
1351 Subtype_Indication =>
1352 New_Reference_To (Etype (Actual), Loc))));
1354 -- Generate:
1355 -- Param : Ann;
1357 Append_To (Comps,
1358 Make_Component_Declaration (Loc,
1359 Defining_Identifier =>
1360 Make_Defining_Identifier (Loc, Chars (Formal)),
1361 Component_Definition =>
1362 Make_Component_Definition (Loc,
1363 Aliased_Present =>
1364 False,
1365 Subtype_Indication =>
1366 New_Reference_To (Comp_Nam, Loc))));
1368 Next_Actual (Actual);
1369 Next_Formal_With_Extras (Formal);
1370 end loop;
1372 -- Generate:
1373 -- type Pnn is record
1374 -- Param1 : Ann1;
1375 -- ...
1376 -- ParamN : AnnN;
1378 -- where Pnn is a parameter wrapping record, Param1 .. ParamN are the
1379 -- original parameter names and Ann1 .. AnnN are the access to actual
1380 -- types.
1382 Comp_Rec :=
1383 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1385 Append_To (Decls,
1386 Make_Full_Type_Declaration (Loc,
1387 Defining_Identifier =>
1388 Comp_Rec,
1389 Type_Definition =>
1390 Make_Record_Definition (Loc,
1391 Component_List =>
1392 Make_Component_List (Loc, Comps))));
1394 return Comp_Rec;
1395 end Build_Parameter_Block;
1397 ------------------------
1398 -- Build_Wrapper_Body --
1399 ------------------------
1401 function Build_Wrapper_Body
1402 (Loc : Source_Ptr;
1403 Proc_Nam : Entity_Id;
1404 Obj_Typ : Entity_Id;
1405 Formals : List_Id) return Node_Id
1407 Actuals : List_Id := No_List;
1408 Body_Spec : Node_Id;
1409 Conv_Id : Node_Id;
1410 First_Formal : Node_Id;
1411 Formal : Node_Id;
1413 begin
1414 Body_Spec := Build_Wrapper_Spec (Loc, Proc_Nam, Obj_Typ, Formals);
1416 -- If we did not generate the specification do have nothing else to do
1418 if Body_Spec = Empty then
1419 return Empty;
1420 end if;
1422 -- Map formals to actuals. Use the list built for the wrapper spec,
1423 -- skipping the object notation parameter.
1425 First_Formal := First (Parameter_Specifications (Body_Spec));
1427 Formal := First_Formal;
1428 Next (Formal);
1430 if Present (Formal) then
1431 Actuals := New_List;
1433 while Present (Formal) loop
1434 Append_To (Actuals,
1435 Make_Identifier (Loc, Chars =>
1436 Chars (Defining_Identifier (Formal))));
1438 Next (Formal);
1439 end loop;
1440 end if;
1442 -- An access-to-variable first parameter will require an explicit
1443 -- dereference in the unchecked conversion. This case occurs when
1444 -- a protected entry wrapper must override an interface-level
1445 -- procedure with interface access as first parameter.
1447 -- SubprgName (O.all).Proc_Nam (Formal_1 .. Formal_N)
1449 if Nkind (Parameter_Type (First_Formal)) = N_Access_Definition then
1450 Conv_Id :=
1451 Make_Explicit_Dereference (Loc,
1452 Prefix =>
1453 Make_Identifier (Loc, Chars => Name_uO));
1454 else
1455 Conv_Id :=
1456 Make_Identifier (Loc, Chars => Name_uO);
1457 end if;
1459 if Ekind (Proc_Nam) = E_Function then
1460 return
1461 Make_Subprogram_Body (Loc,
1462 Specification => Body_Spec,
1463 Declarations => Empty_List,
1464 Handled_Statement_Sequence =>
1465 Make_Handled_Sequence_Of_Statements (Loc,
1466 Statements =>
1467 New_List (
1468 Make_Return_Statement (Loc,
1469 Make_Function_Call (Loc,
1470 Name =>
1471 Make_Selected_Component (Loc,
1472 Prefix =>
1473 Unchecked_Convert_To (
1474 Corresponding_Concurrent_Type (Obj_Typ),
1475 Conv_Id),
1476 Selector_Name =>
1477 New_Reference_To (Proc_Nam, Loc)),
1478 Parameter_Associations => Actuals)))));
1479 else
1480 return
1481 Make_Subprogram_Body (Loc,
1482 Specification => Body_Spec,
1483 Declarations => Empty_List,
1484 Handled_Statement_Sequence =>
1485 Make_Handled_Sequence_Of_Statements (Loc,
1486 Statements =>
1487 New_List (
1488 Make_Procedure_Call_Statement (Loc,
1489 Name =>
1490 Make_Selected_Component (Loc,
1491 Prefix =>
1492 Unchecked_Convert_To (
1493 Corresponding_Concurrent_Type (Obj_Typ),
1494 Conv_Id),
1495 Selector_Name =>
1496 New_Reference_To (Proc_Nam, Loc)),
1497 Parameter_Associations => Actuals))));
1498 end if;
1499 end Build_Wrapper_Body;
1501 ------------------------
1502 -- Build_Wrapper_Spec --
1503 ------------------------
1505 function Build_Wrapper_Spec
1506 (Loc : Source_Ptr;
1507 Proc_Nam : Entity_Id;
1508 Obj_Typ : Entity_Id;
1509 Formals : List_Id) return Node_Id
1511 New_Name_Id : constant Entity_Id :=
1512 Make_Defining_Identifier (Loc, Chars (Proc_Nam));
1514 First_Param : Node_Id := Empty;
1515 Iface : Entity_Id;
1516 Iface_Elmt : Elmt_Id := No_Elmt;
1517 New_Formals : List_Id;
1518 Obj_Param : Node_Id;
1519 Obj_Param_Typ : Node_Id;
1520 Iface_Prim_Op : Entity_Id;
1521 Iface_Prim_Op_Elmt : Elmt_Id;
1523 function Overriding_Possible
1524 (Iface_Prim_Op : Entity_Id;
1525 Proc_Nam : Entity_Id) return Boolean;
1526 -- Determine whether a primitive operation can be overriden by the
1527 -- wrapper. Iface_Prim_Op is the candidate primitive operation of an
1528 -- abstract interface type, Proc_Nam is the generated entry wrapper.
1530 function Replicate_Entry_Formals
1531 (Loc : Source_Ptr;
1532 Formals : List_Id) return List_Id;
1533 -- An explicit parameter replication is required due to the
1534 -- Is_Entry_Formal flag being set for all the formals. The explicit
1535 -- replication removes the flag that would otherwise cause a different
1536 -- path of analysis.
1538 -------------------------
1539 -- Overriding_Possible --
1540 -------------------------
1542 function Overriding_Possible
1543 (Iface_Prim_Op : Entity_Id;
1544 Proc_Nam : Entity_Id) return Boolean
1546 Prim_Op_Spec : constant Node_Id := Parent (Iface_Prim_Op);
1547 Proc_Spec : constant Node_Id := Parent (Proc_Nam);
1549 Is_Access_To_Variable : Boolean;
1550 Is_Out_Present : Boolean;
1552 function Type_Conformant_Parameters
1553 (Prim_Op_Param_Specs : List_Id;
1554 Proc_Param_Specs : List_Id) return Boolean;
1555 -- Determine whether the parameters of the generated entry wrapper
1556 -- and those of a primitive operation are type conformant. During
1557 -- this check, the first parameter of the primitive operation is
1558 -- always skipped.
1560 --------------------------------
1561 -- Type_Conformant_Parameters --
1562 --------------------------------
1564 function Type_Conformant_Parameters
1565 (Prim_Op_Param_Specs : List_Id;
1566 Proc_Param_Specs : List_Id) return Boolean
1568 Prim_Op_Param : Node_Id;
1569 Proc_Param : Node_Id;
1571 begin
1572 -- Skip the first parameter of the primitive operation
1574 Prim_Op_Param := Next (First (Prim_Op_Param_Specs));
1575 Proc_Param := First (Proc_Param_Specs);
1576 while Present (Prim_Op_Param)
1577 and then Present (Proc_Param)
1578 loop
1579 -- The two parameters must be mode conformant and have
1580 -- the exact same types.
1582 if Out_Present (Prim_Op_Param) /= Out_Present (Proc_Param)
1583 or else In_Present (Prim_Op_Param) /= In_Present (Proc_Param)
1584 or else Etype (Parameter_Type (Prim_Op_Param)) /=
1585 Etype (Parameter_Type (Proc_Param))
1586 then
1587 return False;
1588 end if;
1590 Next (Prim_Op_Param);
1591 Next (Proc_Param);
1592 end loop;
1594 -- One of the lists is longer than the other
1596 if Present (Prim_Op_Param) or else Present (Proc_Param) then
1597 return False;
1598 end if;
1600 return True;
1601 end Type_Conformant_Parameters;
1603 -- Start of processing for Overriding_Possible
1605 begin
1606 if Chars (Iface_Prim_Op) /= Chars (Proc_Nam) then
1607 return False;
1608 end if;
1610 -- Special check for protected procedures: If an inherited subprogram
1611 -- is implemented by a protected procedure or an entry, then the
1612 -- first parameter of the inherited subprogram shall be of mode OUT
1613 -- or IN OUT, or an access-to-variable parameter.
1615 if Ekind (Iface_Prim_Op) = E_Procedure then
1617 Is_Out_Present :=
1618 Present (Parameter_Specifications (Prim_Op_Spec))
1619 and then
1620 Out_Present (First (Parameter_Specifications (Prim_Op_Spec)));
1622 Is_Access_To_Variable :=
1623 Present (Parameter_Specifications (Prim_Op_Spec))
1624 and then
1625 Nkind (Parameter_Type
1626 (First
1627 (Parameter_Specifications (Prim_Op_Spec))))
1628 = N_Access_Definition;
1630 if not Is_Out_Present
1631 and then not Is_Access_To_Variable
1632 then
1633 return False;
1634 end if;
1635 end if;
1637 return Type_Conformant_Parameters (
1638 Parameter_Specifications (Prim_Op_Spec),
1639 Parameter_Specifications (Proc_Spec));
1641 end Overriding_Possible;
1643 -----------------------------
1644 -- Replicate_Entry_Formals --
1645 -----------------------------
1647 function Replicate_Entry_Formals
1648 (Loc : Source_Ptr;
1649 Formals : List_Id) return List_Id
1651 New_Formals : constant List_Id := New_List;
1652 Formal : Node_Id;
1654 begin
1655 Formal := First (Formals);
1657 if Present (Formal) then
1658 while Present (Formal) loop
1660 -- Create an explicit copy of the entry parameter
1662 Append_To (New_Formals,
1663 Make_Parameter_Specification (Loc,
1664 Defining_Identifier =>
1665 Make_Defining_Identifier (Loc,
1666 Chars => Chars (Defining_Identifier (Formal))),
1667 In_Present => In_Present (Formal),
1668 Out_Present => Out_Present (Formal),
1669 Parameter_Type => New_Reference_To (Etype (
1670 Parameter_Type (Formal)), Loc)));
1672 Next (Formal);
1673 end loop;
1674 end if;
1676 return New_Formals;
1677 end Replicate_Entry_Formals;
1679 -- Start of processing for Build_Wrapper_Spec
1681 begin
1682 -- The mode is determined by the first parameter of the interface-level
1683 -- procedure that the current entry is trying to override.
1685 pragma Assert (Present (Abstract_Interfaces
1686 (Corresponding_Record_Type (Scope (Proc_Nam)))));
1688 Iface_Elmt :=
1689 First_Elmt (Abstract_Interfaces
1690 (Corresponding_Record_Type (Scope (Proc_Nam))));
1692 -- We must examine all the protected operations of the implemented
1693 -- interfaces in order to discover a possible overriding candidate.
1695 Examine_Interfaces : while Present (Iface_Elmt) loop
1696 Iface := Node (Iface_Elmt);
1698 if Present (Primitive_Operations (Iface)) then
1699 Iface_Prim_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
1701 while Present (Iface_Prim_Op_Elmt) loop
1702 Iface_Prim_Op := Node (Iface_Prim_Op_Elmt);
1704 -- The current primitive operation can be overriden by the
1705 -- generated entry wrapper.
1707 if Overriding_Possible (Iface_Prim_Op, Proc_Nam) then
1708 First_Param :=
1709 First (Parameter_Specifications (Parent (Iface_Prim_Op)));
1711 exit Examine_Interfaces;
1712 end if;
1714 Next_Elmt (Iface_Prim_Op_Elmt);
1715 end loop;
1716 end if;
1718 Next_Elmt (Iface_Elmt);
1719 end loop Examine_Interfaces;
1721 -- Return if no interface primitive can be overriden
1723 if not Present (First_Param) then
1724 return Empty;
1725 end if;
1727 New_Formals := Replicate_Entry_Formals (Loc, Formals);
1729 -- ??? Certain source packages contain protected or task types that do
1730 -- not implement any interfaces and are compiled with the -gnat05
1731 -- switch. In this case, a default first parameter is created.
1733 if Present (First_Param) then
1734 if Nkind (Parameter_Type (First_Param)) = N_Access_Definition then
1735 Obj_Param_Typ :=
1736 Make_Access_Definition (Loc,
1737 Subtype_Mark =>
1738 New_Reference_To (Obj_Typ, Loc));
1739 else
1740 Obj_Param_Typ := New_Reference_To (Obj_Typ, Loc);
1741 end if;
1743 Obj_Param :=
1744 Make_Parameter_Specification (Loc,
1745 Defining_Identifier =>
1746 Make_Defining_Identifier (Loc, Name_uO),
1747 In_Present => In_Present (First_Param),
1748 Out_Present => Out_Present (First_Param),
1749 Parameter_Type => Obj_Param_Typ);
1751 else
1752 Obj_Param :=
1753 Make_Parameter_Specification (Loc,
1754 Defining_Identifier =>
1755 Make_Defining_Identifier (Loc, Name_uO),
1756 In_Present => True,
1757 Out_Present => True,
1758 Parameter_Type => New_Reference_To (Obj_Typ, Loc));
1759 end if;
1761 Prepend_To (New_Formals, Obj_Param);
1763 -- Minimum decoration needed to catch the entity in
1764 -- Sem_Ch6.Override_Dispatching_Operation
1766 if Ekind (Proc_Nam) = E_Procedure
1767 or else Ekind (Proc_Nam) = E_Entry
1768 then
1769 Set_Ekind (New_Name_Id, E_Procedure);
1770 Set_Is_Primitive_Wrapper (New_Name_Id);
1771 Set_Wrapped_Entity (New_Name_Id, Proc_Nam);
1773 return
1774 Make_Procedure_Specification (Loc,
1775 Defining_Unit_Name => New_Name_Id,
1776 Parameter_Specifications => New_Formals);
1778 else pragma Assert (Ekind (Proc_Nam) = E_Function);
1779 Set_Ekind (New_Name_Id, E_Function);
1781 return
1782 Make_Function_Specification (Loc,
1783 Defining_Unit_Name => New_Name_Id,
1784 Parameter_Specifications => New_Formals,
1785 Result_Definition =>
1786 New_Copy (Result_Definition (Parent (Proc_Nam))));
1787 end if;
1788 end Build_Wrapper_Spec;
1790 ---------------------------
1791 -- Build_Find_Body_Index --
1792 ---------------------------
1794 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id is
1795 Loc : constant Source_Ptr := Sloc (Typ);
1796 Ent : Entity_Id;
1797 E_Typ : Entity_Id;
1798 Has_F : Boolean := False;
1799 Index : Nat;
1800 If_St : Node_Id := Empty;
1801 Lo : Node_Id;
1802 Hi : Node_Id;
1803 Decls : List_Id := New_List;
1804 Ret : Node_Id;
1805 Spec : Node_Id;
1806 Siz : Node_Id := Empty;
1808 procedure Add_If_Clause (Expr : Node_Id);
1809 -- Add test for range of current entry
1811 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
1812 -- If a bound of an entry is given by a discriminant, retrieve the
1813 -- actual value of the discriminant from the enclosing object.
1815 -------------------
1816 -- Add_If_Clause --
1817 -------------------
1819 procedure Add_If_Clause (Expr : Node_Id) is
1820 Cond : Node_Id;
1821 Stats : constant List_Id :=
1822 New_List (
1823 Make_Return_Statement (Loc,
1824 Expression => Make_Integer_Literal (Loc, Index + 1)));
1826 begin
1827 -- Index for current entry body
1829 Index := Index + 1;
1831 -- Compute total length of entry queues so far
1833 if No (Siz) then
1834 Siz := Expr;
1835 else
1836 Siz :=
1837 Make_Op_Add (Loc,
1838 Left_Opnd => Siz,
1839 Right_Opnd => Expr);
1840 end if;
1842 Cond :=
1843 Make_Op_Le (Loc,
1844 Left_Opnd => Make_Identifier (Loc, Name_uE),
1845 Right_Opnd => Siz);
1847 -- Map entry queue indices in the range of the current family
1848 -- into the current index, that designates the entry body.
1850 if No (If_St) then
1851 If_St :=
1852 Make_Implicit_If_Statement (Typ,
1853 Condition => Cond,
1854 Then_Statements => Stats,
1855 Elsif_Parts => New_List);
1857 Ret := If_St;
1859 else
1860 Append (
1861 Make_Elsif_Part (Loc,
1862 Condition => Cond,
1863 Then_Statements => Stats),
1864 Elsif_Parts (If_St));
1865 end if;
1866 end Add_If_Clause;
1868 ------------------------------
1869 -- Convert_Discriminant_Ref --
1870 ------------------------------
1872 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
1873 B : Node_Id;
1875 begin
1876 if Is_Entity_Name (Bound)
1877 and then Ekind (Entity (Bound)) = E_Discriminant
1878 then
1879 B :=
1880 Make_Selected_Component (Loc,
1881 Prefix =>
1882 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
1883 Make_Explicit_Dereference (Loc,
1884 Make_Identifier (Loc, Name_uObject))),
1885 Selector_Name => Make_Identifier (Loc, Chars (Bound)));
1886 Set_Etype (B, Etype (Entity (Bound)));
1887 else
1888 B := New_Copy_Tree (Bound);
1889 end if;
1891 return B;
1892 end Convert_Discriminant_Ref;
1894 -- Start of processing for Build_Find_Body_Index
1896 begin
1897 Spec := Build_Find_Body_Index_Spec (Typ);
1899 Ent := First_Entity (Typ);
1901 while Present (Ent) loop
1903 if Ekind (Ent) = E_Entry_Family then
1904 Has_F := True;
1905 exit;
1906 end if;
1908 Next_Entity (Ent);
1909 end loop;
1911 if not Has_F then
1913 -- If the protected type has no entry families, there is a one-one
1914 -- correspondence between entry queue and entry body.
1916 Ret :=
1917 Make_Return_Statement (Loc,
1918 Expression => Make_Identifier (Loc, Name_uE));
1920 else
1921 -- Suppose entries e1, e2, ... have size l1, l2, ... we generate
1922 -- the following:
1924 -- if E <= l1 then return 1;
1925 -- elsif E <= l1 + l2 then return 2;
1926 -- ...
1928 Index := 0;
1929 Siz := Empty;
1930 Ent := First_Entity (Typ);
1932 Add_Object_Pointer (Decls, Typ, Loc);
1934 while Present (Ent) loop
1936 if Ekind (Ent) = E_Entry then
1937 Add_If_Clause (Make_Integer_Literal (Loc, 1));
1939 elsif Ekind (Ent) = E_Entry_Family then
1941 E_Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1942 Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
1943 Lo := Convert_Discriminant_Ref (Type_Low_Bound (E_Typ));
1944 Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ));
1945 end if;
1947 Next_Entity (Ent);
1948 end loop;
1950 if Index = 1 then
1951 Decls := New_List;
1952 Ret :=
1953 Make_Return_Statement (Loc,
1954 Expression => Make_Integer_Literal (Loc, 1));
1956 elsif Nkind (Ret) = N_If_Statement then
1958 -- Ranges are in increasing order, so last one doesn't need a
1959 -- guard.
1961 declare
1962 Nod : constant Node_Id := Last (Elsif_Parts (Ret));
1964 begin
1965 Remove (Nod);
1966 Set_Else_Statements (Ret, Then_Statements (Nod));
1967 end;
1968 end if;
1969 end if;
1971 return
1972 Make_Subprogram_Body (Loc,
1973 Specification => Spec,
1974 Declarations => Decls,
1975 Handled_Statement_Sequence =>
1976 Make_Handled_Sequence_Of_Statements (Loc,
1977 Statements => New_List (Ret)));
1978 end Build_Find_Body_Index;
1980 --------------------------------
1981 -- Build_Find_Body_Index_Spec --
1982 --------------------------------
1984 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id is
1985 Loc : constant Source_Ptr := Sloc (Typ);
1986 Id : constant Entity_Id :=
1987 Make_Defining_Identifier (Loc,
1988 Chars => New_External_Name (Chars (Typ), 'F'));
1989 Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
1990 Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
1992 begin
1993 return
1994 Make_Function_Specification (Loc,
1995 Defining_Unit_Name => Id,
1996 Parameter_Specifications => New_List (
1997 Make_Parameter_Specification (Loc,
1998 Defining_Identifier => Parm1,
1999 Parameter_Type =>
2000 New_Reference_To (RTE (RE_Address), Loc)),
2002 Make_Parameter_Specification (Loc,
2003 Defining_Identifier => Parm2,
2004 Parameter_Type =>
2005 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
2006 Result_Definition => New_Occurrence_Of (
2007 RTE (RE_Protected_Entry_Index), Loc));
2008 end Build_Find_Body_Index_Spec;
2010 -------------------------
2011 -- Build_Master_Entity --
2012 -------------------------
2014 procedure Build_Master_Entity (E : Entity_Id) is
2015 Loc : constant Source_Ptr := Sloc (E);
2016 P : Node_Id;
2017 Decl : Node_Id;
2018 S : Entity_Id;
2020 begin
2021 S := Scope (E);
2023 -- Ada 2005 (AI-287): Do not set/get the has_master_entity reminder
2024 -- in internal scopes. Required for nested limited aggregates.
2026 if Ada_Version >= Ada_05 then
2027 while Is_Internal (S) loop
2028 S := Scope (S);
2029 end loop;
2030 end if;
2032 -- Nothing to do if we already built a master entity for this scope
2033 -- or if there is no task hierarchy.
2035 if Has_Master_Entity (S)
2036 or else Restriction_Active (No_Task_Hierarchy)
2037 then
2038 return;
2039 end if;
2041 -- Otherwise first build the master entity
2042 -- _Master : constant Master_Id := Current_Master.all;
2043 -- and insert it just before the current declaration
2045 Decl :=
2046 Make_Object_Declaration (Loc,
2047 Defining_Identifier =>
2048 Make_Defining_Identifier (Loc, Name_uMaster),
2049 Constant_Present => True,
2050 Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
2051 Expression =>
2052 Make_Explicit_Dereference (Loc,
2053 New_Reference_To (RTE (RE_Current_Master), Loc)));
2055 P := Parent (E);
2056 Insert_Before (P, Decl);
2057 Analyze (Decl);
2059 -- Ada 2005 (AI-287): Set the has_master_entity reminder in the
2060 -- non-internal scope selected above.
2062 if Ada_Version >= Ada_05 then
2063 Set_Has_Master_Entity (S);
2064 else
2065 Set_Has_Master_Entity (Scope (E));
2066 end if;
2068 -- Now mark the containing scope as a task master
2070 while Nkind (P) /= N_Compilation_Unit loop
2071 P := Parent (P);
2073 -- If we fall off the top, we are at the outer level, and the
2074 -- environment task is our effective master, so nothing to mark.
2076 if Nkind (P) = N_Task_Body
2077 or else Nkind (P) = N_Block_Statement
2078 or else Nkind (P) = N_Subprogram_Body
2079 then
2080 Set_Is_Task_Master (P, True);
2081 return;
2083 elsif Nkind (Parent (P)) = N_Subunit then
2084 P := Corresponding_Stub (Parent (P));
2085 end if;
2086 end loop;
2087 end Build_Master_Entity;
2089 ---------------------------
2090 -- Build_Protected_Entry --
2091 ---------------------------
2093 function Build_Protected_Entry
2094 (N : Node_Id;
2095 Ent : Entity_Id;
2096 Pid : Node_Id) return Node_Id
2098 Loc : constant Source_Ptr := Sloc (N);
2099 Op_Decls : constant List_Id := New_List;
2100 Edef : Entity_Id;
2101 Espec : Node_Id;
2102 Op_Stats : List_Id;
2103 Ohandle : Node_Id;
2104 Complete : Node_Id;
2106 begin
2107 Edef :=
2108 Make_Defining_Identifier (Loc,
2109 Chars => Chars (Protected_Body_Subprogram (Ent)));
2110 Espec := Build_Protected_Entry_Specification (Edef, Empty, Loc);
2112 -- <object pointer declaration>
2113 -- Add object pointer declaration. This is needed by the
2114 -- discriminal and prival renamings, which should already
2115 -- have been inserted into the declaration list.
2117 Add_Object_Pointer (Op_Decls, Pid, Loc);
2119 if Abort_Allowed
2120 or else Restriction_Active (No_Entry_Queue) = False
2121 or else Number_Entries (Pid) > 1
2122 then
2123 Complete := New_Reference_To (RTE (RE_Complete_Entry_Body), Loc);
2124 else
2125 Complete :=
2126 New_Reference_To (RTE (RE_Complete_Single_Entry_Body), Loc);
2127 end if;
2129 Op_Stats := New_List (
2130 Make_Block_Statement (Loc,
2131 Declarations => Declarations (N),
2132 Handled_Statement_Sequence =>
2133 Handled_Statement_Sequence (N)),
2135 Make_Procedure_Call_Statement (Loc,
2136 Name => Complete,
2137 Parameter_Associations => New_List (
2138 Make_Attribute_Reference (Loc,
2139 Prefix =>
2140 Make_Selected_Component (Loc,
2141 Prefix =>
2142 Make_Identifier (Loc, Name_uObject),
2144 Selector_Name =>
2145 Make_Identifier (Loc, Name_uObject)),
2146 Attribute_Name => Name_Unchecked_Access))));
2148 if Restriction_Active (No_Exception_Handlers) then
2149 return
2150 Make_Subprogram_Body (Loc,
2151 Specification => Espec,
2152 Declarations => Op_Decls,
2153 Handled_Statement_Sequence =>
2154 Make_Handled_Sequence_Of_Statements (Loc, Op_Stats));
2156 else
2157 Ohandle := Make_Others_Choice (Loc);
2158 Set_All_Others (Ohandle);
2160 if Abort_Allowed
2161 or else Restriction_Active (No_Entry_Queue) = False
2162 or else Number_Entries (Pid) > 1
2163 then
2164 Complete :=
2165 New_Reference_To (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
2167 else
2168 Complete := New_Reference_To (
2169 RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
2170 end if;
2172 return
2173 Make_Subprogram_Body (Loc,
2174 Specification => Espec,
2175 Declarations => Op_Decls,
2176 Handled_Statement_Sequence =>
2177 Make_Handled_Sequence_Of_Statements (Loc,
2178 Statements => Op_Stats,
2179 Exception_Handlers => New_List (
2180 Make_Exception_Handler (Loc,
2181 Exception_Choices => New_List (Ohandle),
2183 Statements => New_List (
2184 Make_Procedure_Call_Statement (Loc,
2185 Name => Complete,
2186 Parameter_Associations => New_List (
2187 Make_Attribute_Reference (Loc,
2188 Prefix =>
2189 Make_Selected_Component (Loc,
2190 Prefix =>
2191 Make_Identifier (Loc, Name_uObject),
2192 Selector_Name =>
2193 Make_Identifier (Loc, Name_uObject)),
2194 Attribute_Name => Name_Unchecked_Access),
2196 Make_Function_Call (Loc,
2197 Name => New_Reference_To (
2198 RTE (RE_Get_GNAT_Exception), Loc)))))))));
2199 end if;
2200 end Build_Protected_Entry;
2202 -----------------------------------------
2203 -- Build_Protected_Entry_Specification --
2204 -----------------------------------------
2206 function Build_Protected_Entry_Specification
2207 (Def_Id : Entity_Id;
2208 Ent_Id : Entity_Id;
2209 Loc : Source_Ptr) return Node_Id
2211 P : Entity_Id;
2213 begin
2214 Set_Needs_Debug_Info (Def_Id);
2215 P := Make_Defining_Identifier (Loc, Name_uP);
2217 if Present (Ent_Id) then
2218 Append_Elmt (P, Accept_Address (Ent_Id));
2219 end if;
2221 return Make_Procedure_Specification (Loc,
2222 Defining_Unit_Name => Def_Id,
2223 Parameter_Specifications => New_List (
2224 Make_Parameter_Specification (Loc,
2225 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
2226 Parameter_Type =>
2227 New_Reference_To (RTE (RE_Address), Loc)),
2229 Make_Parameter_Specification (Loc,
2230 Defining_Identifier => P,
2231 Parameter_Type =>
2232 New_Reference_To (RTE (RE_Address), Loc)),
2234 Make_Parameter_Specification (Loc,
2235 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uE),
2236 Parameter_Type =>
2237 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))));
2238 end Build_Protected_Entry_Specification;
2240 --------------------------
2241 -- Build_Protected_Spec --
2242 --------------------------
2244 function Build_Protected_Spec
2245 (N : Node_Id;
2246 Obj_Type : Entity_Id;
2247 Unprotected : Boolean := False;
2248 Ident : Entity_Id) return List_Id
2250 Loc : constant Source_Ptr := Sloc (N);
2251 Formal : Entity_Id;
2252 New_Plist : List_Id;
2253 New_Param : Node_Id;
2255 begin
2256 New_Plist := New_List;
2257 Formal := First_Formal (Ident);
2259 while Present (Formal) loop
2260 New_Param :=
2261 Make_Parameter_Specification (Loc,
2262 Defining_Identifier =>
2263 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
2264 In_Present => In_Present (Parent (Formal)),
2265 Out_Present => Out_Present (Parent (Formal)),
2266 Parameter_Type =>
2267 New_Reference_To (Etype (Formal), Loc));
2269 if Unprotected then
2270 Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
2271 end if;
2273 Append (New_Param, New_Plist);
2274 Next_Formal (Formal);
2275 end loop;
2277 -- If the subprogram is a procedure and the context is not an access
2278 -- to protected subprogram, the parameter is in-out. Otherwise it is
2279 -- an in parameter.
2281 Prepend_To (New_Plist,
2282 Make_Parameter_Specification (Loc,
2283 Defining_Identifier =>
2284 Make_Defining_Identifier (Loc, Name_uObject),
2285 In_Present => True,
2286 Out_Present =>
2287 (Etype (Ident) = Standard_Void_Type
2288 and then not Is_RTE (Obj_Type, RE_Address)),
2289 Parameter_Type => New_Reference_To (Obj_Type, Loc)));
2291 return New_Plist;
2292 end Build_Protected_Spec;
2294 ---------------------------------------
2295 -- Build_Protected_Sub_Specification --
2296 ---------------------------------------
2298 function Build_Protected_Sub_Specification
2299 (N : Node_Id;
2300 Prottyp : Entity_Id;
2301 Mode : Subprogram_Protection_Mode) return Node_Id
2303 Loc : constant Source_Ptr := Sloc (N);
2304 Decl : Node_Id;
2305 Protnm : constant Name_Id := Chars (Prottyp);
2306 Ident : Entity_Id;
2307 Nam : Name_Id;
2308 New_Id : Entity_Id;
2309 New_Plist : List_Id;
2310 New_Spec : Node_Id;
2312 Append_Chr : constant array (Subprogram_Protection_Mode) of Character :=
2313 (Dispatching_Mode => ' ',
2314 Protected_Mode => 'P',
2315 Unprotected_Mode => 'N');
2317 begin
2318 if Ekind
2319 (Defining_Unit_Name (Specification (N))) = E_Subprogram_Body
2320 then
2321 Decl := Unit_Declaration_Node (Corresponding_Spec (N));
2322 else
2323 Decl := N;
2324 end if;
2326 Ident := Defining_Unit_Name (Specification (Decl));
2327 Nam := Chars (Ident);
2329 New_Plist :=
2330 Build_Protected_Spec (Decl,
2331 Corresponding_Record_Type (Prottyp),
2332 Mode = Unprotected_Mode, Ident);
2334 New_Id :=
2335 Make_Defining_Identifier (Loc,
2336 Chars => Build_Selected_Name (Protnm, Nam, Append_Chr (Mode)));
2338 -- The unprotected operation carries the user code, and debugging
2339 -- information must be generated for it, even though this spec does
2340 -- not come from source. It is also convenient to allow gdb to step
2341 -- into the protected operation, even though it only contains lock/
2342 -- unlock calls.
2344 Set_Needs_Debug_Info (New_Id);
2346 if Nkind (Specification (Decl)) = N_Procedure_Specification then
2347 return
2348 Make_Procedure_Specification (Loc,
2349 Defining_Unit_Name => New_Id,
2350 Parameter_Specifications => New_Plist);
2352 else
2353 New_Spec :=
2354 Make_Function_Specification (Loc,
2355 Defining_Unit_Name => New_Id,
2356 Parameter_Specifications => New_Plist,
2357 Result_Definition =>
2358 New_Copy (Result_Definition (Specification (Decl))));
2359 Set_Return_Present (Defining_Unit_Name (New_Spec));
2360 return New_Spec;
2361 end if;
2362 end Build_Protected_Sub_Specification;
2364 -------------------------------------
2365 -- Build_Protected_Subprogram_Body --
2366 -------------------------------------
2368 function Build_Protected_Subprogram_Body
2369 (N : Node_Id;
2370 Pid : Node_Id;
2371 N_Op_Spec : Node_Id) return Node_Id
2373 Loc : constant Source_Ptr := Sloc (N);
2374 Op_Spec : Node_Id;
2375 P_Op_Spec : Node_Id;
2376 Uactuals : List_Id;
2377 Pformal : Node_Id;
2378 Unprot_Call : Node_Id;
2379 Sub_Body : Node_Id;
2380 Lock_Name : Node_Id;
2381 Lock_Stmt : Node_Id;
2382 Service_Name : Node_Id;
2383 R : Node_Id;
2384 Return_Stmt : Node_Id := Empty; -- init to avoid gcc 3 warning
2385 Pre_Stmts : List_Id := No_List; -- init to avoid gcc 3 warning
2386 Stmts : List_Id;
2387 Object_Parm : Node_Id;
2388 Exc_Safe : Boolean;
2390 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
2391 -- Tell whether a given subprogram cannot raise an exception
2393 -----------------------
2394 -- Is_Exception_Safe --
2395 -----------------------
2397 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
2399 function Has_Side_Effect (N : Node_Id) return Boolean;
2400 -- Return True whenever encountering a subprogram call or a
2401 -- raise statement of any kind in the sequence of statements N
2403 ---------------------
2404 -- Has_Side_Effect --
2405 ---------------------
2407 -- What is this doing buried two levels down in exp_ch9. It
2408 -- seems like a generally useful function, and indeed there
2409 -- may be code duplication going on here ???
2411 function Has_Side_Effect (N : Node_Id) return Boolean is
2412 Stmt : Node_Id := N;
2413 Expr : Node_Id;
2415 function Is_Call_Or_Raise (N : Node_Id) return Boolean;
2416 -- Indicate whether N is a subprogram call or a raise statement
2418 function Is_Call_Or_Raise (N : Node_Id) return Boolean is
2419 begin
2420 return Nkind (N) = N_Procedure_Call_Statement
2421 or else Nkind (N) = N_Function_Call
2422 or else Nkind (N) = N_Raise_Statement
2423 or else Nkind (N) = N_Raise_Constraint_Error
2424 or else Nkind (N) = N_Raise_Program_Error
2425 or else Nkind (N) = N_Raise_Storage_Error;
2426 end Is_Call_Or_Raise;
2428 -- Start of processing for Has_Side_Effect
2430 begin
2431 while Present (Stmt) loop
2432 if Is_Call_Or_Raise (Stmt) then
2433 return True;
2434 end if;
2436 -- An object declaration can also contain a function call
2437 -- or a raise statement
2439 if Nkind (Stmt) = N_Object_Declaration then
2440 Expr := Expression (Stmt);
2442 if Present (Expr) and then Is_Call_Or_Raise (Expr) then
2443 return True;
2444 end if;
2445 end if;
2447 Next (Stmt);
2448 end loop;
2450 return False;
2451 end Has_Side_Effect;
2453 -- Start of processing for Is_Exception_Safe
2455 begin
2456 -- If the checks handled by the back end are not disabled, we cannot
2457 -- ensure that no exception will be raised.
2459 if not Access_Checks_Suppressed (Empty)
2460 or else not Discriminant_Checks_Suppressed (Empty)
2461 or else not Range_Checks_Suppressed (Empty)
2462 or else not Index_Checks_Suppressed (Empty)
2463 or else Opt.Stack_Checking_Enabled
2464 then
2465 return False;
2466 end if;
2468 if Has_Side_Effect (First (Declarations (Subprogram)))
2469 or else
2470 Has_Side_Effect (
2471 First (Statements (Handled_Statement_Sequence (Subprogram))))
2472 then
2473 return False;
2474 else
2475 return True;
2476 end if;
2477 end Is_Exception_Safe;
2479 -- Start of processing for Build_Protected_Subprogram_Body
2481 begin
2482 Op_Spec := Specification (N);
2483 Exc_Safe := Is_Exception_Safe (N);
2485 P_Op_Spec :=
2486 Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
2488 -- Build a list of the formal parameters of the protected
2489 -- version of the subprogram to use as the actual parameters
2490 -- of the unprotected version.
2492 Uactuals := New_List;
2493 Pformal := First (Parameter_Specifications (P_Op_Spec));
2495 while Present (Pformal) loop
2496 Append (
2497 Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))),
2498 Uactuals);
2499 Next (Pformal);
2500 end loop;
2502 -- Make a call to the unprotected version of the subprogram
2503 -- built above for use by the protected version built below.
2505 if Nkind (Op_Spec) = N_Function_Specification then
2506 if Exc_Safe then
2507 R := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
2508 Unprot_Call :=
2509 Make_Object_Declaration (Loc,
2510 Defining_Identifier => R,
2511 Constant_Present => True,
2512 Object_Definition => New_Copy (Result_Definition (N_Op_Spec)),
2513 Expression =>
2514 Make_Function_Call (Loc,
2515 Name => Make_Identifier (Loc,
2516 Chars (Defining_Unit_Name (N_Op_Spec))),
2517 Parameter_Associations => Uactuals));
2518 Return_Stmt := Make_Return_Statement (Loc,
2519 Expression => New_Reference_To (R, Loc));
2521 else
2522 Unprot_Call := Make_Return_Statement (Loc,
2523 Expression => Make_Function_Call (Loc,
2524 Name =>
2525 Make_Identifier (Loc,
2526 Chars (Defining_Unit_Name (N_Op_Spec))),
2527 Parameter_Associations => Uactuals));
2528 end if;
2530 else
2531 Unprot_Call := Make_Procedure_Call_Statement (Loc,
2532 Name =>
2533 Make_Identifier (Loc,
2534 Chars (Defining_Unit_Name (N_Op_Spec))),
2535 Parameter_Associations => Uactuals);
2536 end if;
2538 -- Wrap call in block that will be covered by an at_end handler
2540 if not Exc_Safe then
2541 Unprot_Call := Make_Block_Statement (Loc,
2542 Handled_Statement_Sequence =>
2543 Make_Handled_Sequence_Of_Statements (Loc,
2544 Statements => New_List (Unprot_Call)));
2545 end if;
2547 -- Make the protected subprogram body. This locks the protected
2548 -- object and calls the unprotected version of the subprogram.
2550 -- If the protected object is controlled (i.e it has entries or
2551 -- needs finalization for interrupt handling), call Lock_Entries,
2552 -- except if the protected object follows the Ravenscar profile, in
2553 -- which case call Lock_Entry, otherwise call the simplified version,
2554 -- Lock.
2556 if Has_Entries (Pid)
2557 or else Has_Interrupt_Handler (Pid)
2558 or else (Has_Attach_Handler (Pid)
2559 and then not Restricted_Profile)
2560 or else (Ada_Version >= Ada_05
2561 and then Present (Interface_List (Parent (Pid))))
2562 then
2563 if Abort_Allowed
2564 or else Restriction_Active (No_Entry_Queue) = False
2565 or else Number_Entries (Pid) > 1
2566 then
2567 Lock_Name := New_Reference_To (RTE (RE_Lock_Entries), Loc);
2568 Service_Name := New_Reference_To (RTE (RE_Service_Entries), Loc);
2570 else
2571 Lock_Name := New_Reference_To (RTE (RE_Lock_Entry), Loc);
2572 Service_Name := New_Reference_To (RTE (RE_Service_Entry), Loc);
2573 end if;
2575 else
2576 Lock_Name := New_Reference_To (RTE (RE_Lock), Loc);
2577 Service_Name := New_Reference_To (RTE (RE_Unlock), Loc);
2578 end if;
2580 Object_Parm :=
2581 Make_Attribute_Reference (Loc,
2582 Prefix =>
2583 Make_Selected_Component (Loc,
2584 Prefix =>
2585 Make_Identifier (Loc, Name_uObject),
2586 Selector_Name =>
2587 Make_Identifier (Loc, Name_uObject)),
2588 Attribute_Name => Name_Unchecked_Access);
2590 Lock_Stmt := Make_Procedure_Call_Statement (Loc,
2591 Name => Lock_Name,
2592 Parameter_Associations => New_List (Object_Parm));
2594 if Abort_Allowed then
2595 Stmts := New_List (
2596 Make_Procedure_Call_Statement (Loc,
2597 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
2598 Parameter_Associations => Empty_List),
2599 Lock_Stmt);
2601 else
2602 Stmts := New_List (Lock_Stmt);
2603 end if;
2605 if not Exc_Safe then
2606 Append (Unprot_Call, Stmts);
2607 else
2608 if Nkind (Op_Spec) = N_Function_Specification then
2609 Pre_Stmts := Stmts;
2610 Stmts := Empty_List;
2611 else
2612 Append (Unprot_Call, Stmts);
2613 end if;
2615 Append (
2616 Make_Procedure_Call_Statement (Loc,
2617 Name => Service_Name,
2618 Parameter_Associations =>
2619 New_List (New_Copy_Tree (Object_Parm))),
2620 Stmts);
2622 if Abort_Allowed then
2623 Append (
2624 Make_Procedure_Call_Statement (Loc,
2625 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc),
2626 Parameter_Associations => Empty_List),
2627 Stmts);
2628 end if;
2630 if Nkind (Op_Spec) = N_Function_Specification then
2631 Append (Return_Stmt, Stmts);
2632 Append (Make_Block_Statement (Loc,
2633 Declarations => New_List (Unprot_Call),
2634 Handled_Statement_Sequence =>
2635 Make_Handled_Sequence_Of_Statements (Loc,
2636 Statements => Stmts)), Pre_Stmts);
2637 Stmts := Pre_Stmts;
2638 end if;
2639 end if;
2641 Sub_Body :=
2642 Make_Subprogram_Body (Loc,
2643 Declarations => Empty_List,
2644 Specification => P_Op_Spec,
2645 Handled_Statement_Sequence =>
2646 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
2648 if not Exc_Safe then
2649 Set_Is_Protected_Subprogram_Body (Sub_Body);
2650 end if;
2652 return Sub_Body;
2653 end Build_Protected_Subprogram_Body;
2655 -------------------------------------
2656 -- Build_Protected_Subprogram_Call --
2657 -------------------------------------
2659 procedure Build_Protected_Subprogram_Call
2660 (N : Node_Id;
2661 Name : Node_Id;
2662 Rec : Node_Id;
2663 External : Boolean := True)
2665 Loc : constant Source_Ptr := Sloc (N);
2666 Sub : constant Entity_Id := Entity (Name);
2667 New_Sub : Node_Id;
2668 Params : List_Id;
2670 begin
2671 if External then
2672 New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
2673 else
2674 New_Sub :=
2675 New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
2676 end if;
2678 if Present (Parameter_Associations (N)) then
2679 Params := New_Copy_List_Tree (Parameter_Associations (N));
2680 else
2681 Params := New_List;
2682 end if;
2684 Prepend (Rec, Params);
2686 if Ekind (Sub) = E_Procedure then
2687 Rewrite (N,
2688 Make_Procedure_Call_Statement (Loc,
2689 Name => New_Sub,
2690 Parameter_Associations => Params));
2692 else
2693 pragma Assert (Ekind (Sub) = E_Function);
2694 Rewrite (N,
2695 Make_Function_Call (Loc,
2696 Name => New_Sub,
2697 Parameter_Associations => Params));
2698 end if;
2700 if External
2701 and then Nkind (Rec) = N_Unchecked_Type_Conversion
2702 and then Is_Entity_Name (Expression (Rec))
2703 and then Is_Shared_Passive (Entity (Expression (Rec)))
2704 then
2705 Add_Shared_Var_Lock_Procs (N);
2706 end if;
2707 end Build_Protected_Subprogram_Call;
2709 -------------------------
2710 -- Build_Selected_Name --
2711 -------------------------
2713 function Build_Selected_Name
2714 (Prefix, Selector : Name_Id;
2715 Append_Char : Character := ' ') return Name_Id
2717 Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
2718 Select_Len : Natural;
2720 begin
2721 Get_Name_String (Selector);
2722 Select_Len := Name_Len;
2723 Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
2724 Get_Name_String (Prefix);
2726 -- If scope is anonymous type, discard suffix to recover name of
2727 -- single protected object. Otherwise use protected type name.
2729 if Name_Buffer (Name_Len) = 'T' then
2730 Name_Len := Name_Len - 1;
2731 end if;
2733 Name_Buffer (Name_Len + 1) := '_';
2734 Name_Buffer (Name_Len + 2) := '_';
2736 Name_Len := Name_Len + 2;
2737 for J in 1 .. Select_Len loop
2738 Name_Len := Name_Len + 1;
2739 Name_Buffer (Name_Len) := Select_Buffer (J);
2740 end loop;
2742 if Append_Char /= ' ' then
2743 Name_Len := Name_Len + 1;
2744 Name_Buffer (Name_Len) := Append_Char;
2745 end if;
2747 return Name_Find;
2748 end Build_Selected_Name;
2750 -----------------------------
2751 -- Build_Simple_Entry_Call --
2752 -----------------------------
2754 -- A task entry call is converted to a call to Call_Simple
2756 -- declare
2757 -- P : parms := (parm, parm, parm);
2758 -- begin
2759 -- Call_Simple (acceptor-task, entry-index, P'Address);
2760 -- parm := P.param;
2761 -- parm := P.param;
2762 -- ...
2763 -- end;
2765 -- Here Pnn is an aggregate of the type constructed for the entry to hold
2766 -- the parameters, and the constructed aggregate value contains either the
2767 -- parameters or, in the case of non-elementary types, references to these
2768 -- parameters. Then the address of this aggregate is passed to the runtime
2769 -- routine, along with the task id value and the task entry index value.
2770 -- Pnn is only required if parameters are present.
2772 -- The assignments after the call are present only in the case of in-out
2773 -- or out parameters for elementary types, and are used to assign back the
2774 -- resulting values of such parameters.
2776 -- Note: the reason that we insert a block here is that in the context
2777 -- of selects, conditional entry calls etc. the entry call statement
2778 -- appears on its own, not as an element of a list.
2780 -- A protected entry call is converted to a Protected_Entry_Call:
2782 -- declare
2783 -- P : E1_Params := (param, param, param);
2784 -- Pnn : Boolean;
2785 -- Bnn : Communications_Block;
2787 -- declare
2788 -- P : E1_Params := (param, param, param);
2789 -- Bnn : Communications_Block;
2791 -- begin
2792 -- Protected_Entry_Call (
2793 -- Object => po._object'Access,
2794 -- E => <entry index>;
2795 -- Uninterpreted_Data => P'Address;
2796 -- Mode => Simple_Call;
2797 -- Block => Bnn);
2798 -- parm := P.param;
2799 -- parm := P.param;
2800 -- ...
2801 -- end;
2803 procedure Build_Simple_Entry_Call
2804 (N : Node_Id;
2805 Concval : Node_Id;
2806 Ename : Node_Id;
2807 Index : Node_Id)
2809 begin
2810 Expand_Call (N);
2812 -- Convert entry call to Call_Simple call
2814 declare
2815 Loc : constant Source_Ptr := Sloc (N);
2816 Parms : constant List_Id := Parameter_Associations (N);
2817 Stats : constant List_Id := New_List;
2818 Pdecl : Node_Id;
2819 Xdecl : Node_Id;
2820 Decls : List_Id;
2821 Conctyp : Node_Id;
2822 Ent : Entity_Id;
2823 Ent_Acc : Entity_Id;
2824 P : Entity_Id;
2825 X : Entity_Id;
2826 Plist : List_Id;
2827 Parm1 : Node_Id;
2828 Parm2 : Node_Id;
2829 Parm3 : Node_Id;
2830 Call : Node_Id;
2831 Actual : Node_Id;
2832 Formal : Node_Id;
2833 N_Node : Node_Id;
2834 N_Var : Node_Id;
2835 Comm_Name : Entity_Id;
2837 begin
2838 -- Simple entry and entry family cases merge here
2840 Ent := Entity (Ename);
2841 Ent_Acc := Entry_Parameters_Type (Ent);
2842 Conctyp := Etype (Concval);
2844 -- If prefix is an access type, dereference to obtain the task type
2846 if Is_Access_Type (Conctyp) then
2847 Conctyp := Designated_Type (Conctyp);
2848 end if;
2850 -- Special case for protected subprogram calls
2852 if Is_Protected_Type (Conctyp)
2853 and then Is_Subprogram (Entity (Ename))
2854 then
2855 if not Is_Eliminated (Entity (Ename)) then
2856 Build_Protected_Subprogram_Call
2857 (N, Ename, Convert_Concurrent (Concval, Conctyp));
2858 Analyze (N);
2859 end if;
2861 return;
2862 end if;
2864 -- First parameter is the Task_Id value from the task value or the
2865 -- Object from the protected object value, obtained by selecting
2866 -- the _Task_Id or _Object from the result of doing an unchecked
2867 -- conversion to convert the value to the corresponding record type.
2869 Parm1 := Concurrent_Ref (Concval);
2871 -- Second parameter is the entry index, computed by the routine
2872 -- provided for this purpose. The value of this expression is
2873 -- assigned to an intermediate variable to assure that any entry
2874 -- family index expressions are evaluated before the entry
2875 -- parameters.
2877 if Abort_Allowed
2878 or else Restriction_Active (No_Entry_Queue) = False
2879 or else not Is_Protected_Type (Conctyp)
2880 or else Number_Entries (Conctyp) > 1
2881 then
2882 X := Make_Defining_Identifier (Loc, Name_uX);
2884 Xdecl :=
2885 Make_Object_Declaration (Loc,
2886 Defining_Identifier => X,
2887 Object_Definition =>
2888 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2889 Expression => Actual_Index_Expression (
2890 Loc, Entity (Ename), Index, Concval));
2892 Decls := New_List (Xdecl);
2893 Parm2 := New_Reference_To (X, Loc);
2895 else
2896 Xdecl := Empty;
2897 Decls := New_List;
2898 Parm2 := Empty;
2899 end if;
2901 -- The third parameter is the packaged parameters. If there are
2902 -- none, then it is just the null address, since nothing is passed
2904 if No (Parms) then
2905 Parm3 := New_Reference_To (RTE (RE_Null_Address), Loc);
2906 P := Empty;
2908 -- Case of parameters present, where third argument is the address
2909 -- of a packaged record containing the required parameter values.
2911 else
2912 -- First build a list of parameter values, which are
2913 -- references to objects of the parameter types.
2915 Plist := New_List;
2917 Actual := First_Actual (N);
2918 Formal := First_Formal (Ent);
2920 while Present (Actual) loop
2922 -- If it is a by_copy_type, copy it to a new variable. The
2923 -- packaged record has a field that points to this variable.
2925 if Is_By_Copy_Type (Etype (Actual)) then
2926 N_Node :=
2927 Make_Object_Declaration (Loc,
2928 Defining_Identifier =>
2929 Make_Defining_Identifier (Loc,
2930 Chars => New_Internal_Name ('J')),
2931 Aliased_Present => True,
2932 Object_Definition =>
2933 New_Reference_To (Etype (Formal), Loc));
2935 -- We have to make an assignment statement separate for
2936 -- the case of limited type. We can not assign it unless
2937 -- the Assignment_OK flag is set first.
2939 if Ekind (Formal) /= E_Out_Parameter then
2940 N_Var :=
2941 New_Reference_To (Defining_Identifier (N_Node), Loc);
2942 Set_Assignment_OK (N_Var);
2943 Append_To (Stats,
2944 Make_Assignment_Statement (Loc,
2945 Name => N_Var,
2946 Expression => Relocate_Node (Actual)));
2947 end if;
2949 Append (N_Node, Decls);
2951 Append_To (Plist,
2952 Make_Attribute_Reference (Loc,
2953 Attribute_Name => Name_Unchecked_Access,
2954 Prefix =>
2955 New_Reference_To (Defining_Identifier (N_Node), Loc)));
2956 else
2957 Append_To (Plist,
2958 Make_Reference (Loc, Prefix => Relocate_Node (Actual)));
2959 end if;
2961 Next_Actual (Actual);
2962 Next_Formal_With_Extras (Formal);
2963 end loop;
2965 -- Now build the declaration of parameters initialized with the
2966 -- aggregate containing this constructed parameter list.
2968 P := Make_Defining_Identifier (Loc, Name_uP);
2970 Pdecl :=
2971 Make_Object_Declaration (Loc,
2972 Defining_Identifier => P,
2973 Object_Definition =>
2974 New_Reference_To (Designated_Type (Ent_Acc), Loc),
2975 Expression =>
2976 Make_Aggregate (Loc, Expressions => Plist));
2978 Parm3 :=
2979 Make_Attribute_Reference (Loc,
2980 Attribute_Name => Name_Address,
2981 Prefix => New_Reference_To (P, Loc));
2983 Append (Pdecl, Decls);
2984 end if;
2986 -- Now we can create the call, case of protected type
2988 if Is_Protected_Type (Conctyp) then
2989 if Abort_Allowed
2990 or else Restriction_Active (No_Entry_Queue) = False
2991 or else Number_Entries (Conctyp) > 1
2992 then
2993 -- Change the type of the index declaration
2995 Set_Object_Definition (Xdecl,
2996 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc));
2998 -- Some additional declarations for protected entry calls
3000 if No (Decls) then
3001 Decls := New_List;
3002 end if;
3004 -- Bnn : Communications_Block;
3006 Comm_Name :=
3007 Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
3009 Append_To (Decls,
3010 Make_Object_Declaration (Loc,
3011 Defining_Identifier => Comm_Name,
3012 Object_Definition =>
3013 New_Reference_To (RTE (RE_Communication_Block), Loc)));
3015 -- Some additional statements for protected entry calls
3017 -- Protected_Entry_Call (
3018 -- Object => po._object'Access,
3019 -- E => <entry index>;
3020 -- Uninterpreted_Data => P'Address;
3021 -- Mode => Simple_Call;
3022 -- Block => Bnn);
3024 Call :=
3025 Make_Procedure_Call_Statement (Loc,
3026 Name =>
3027 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
3029 Parameter_Associations => New_List (
3030 Make_Attribute_Reference (Loc,
3031 Attribute_Name => Name_Unchecked_Access,
3032 Prefix => Parm1),
3033 Parm2,
3034 Parm3,
3035 New_Reference_To (RTE (RE_Simple_Call), Loc),
3036 New_Occurrence_Of (Comm_Name, Loc)));
3038 else
3039 -- Protected_Single_Entry_Call (
3040 -- Object => po._object'Access,
3041 -- Uninterpreted_Data => P'Address;
3042 -- Mode => Simple_Call);
3044 Call :=
3045 Make_Procedure_Call_Statement (Loc,
3046 Name => New_Reference_To (
3047 RTE (RE_Protected_Single_Entry_Call), Loc),
3049 Parameter_Associations => New_List (
3050 Make_Attribute_Reference (Loc,
3051 Attribute_Name => Name_Unchecked_Access,
3052 Prefix => Parm1),
3053 Parm3,
3054 New_Reference_To (RTE (RE_Simple_Call), Loc)));
3055 end if;
3057 -- Case of task type
3059 else
3060 Call :=
3061 Make_Procedure_Call_Statement (Loc,
3062 Name => New_Reference_To (RTE (RE_Call_Simple), Loc),
3063 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
3065 end if;
3067 Append_To (Stats, Call);
3069 -- If there are out or in/out parameters by copy
3070 -- add assignment statements for the result values.
3072 if Present (Parms) then
3073 Actual := First_Actual (N);
3074 Formal := First_Formal (Ent);
3076 Set_Assignment_OK (Actual);
3077 while Present (Actual) loop
3078 if Is_By_Copy_Type (Etype (Actual))
3079 and then Ekind (Formal) /= E_In_Parameter
3080 then
3081 N_Node :=
3082 Make_Assignment_Statement (Loc,
3083 Name => New_Copy (Actual),
3084 Expression =>
3085 Make_Explicit_Dereference (Loc,
3086 Make_Selected_Component (Loc,
3087 Prefix => New_Reference_To (P, Loc),
3088 Selector_Name =>
3089 Make_Identifier (Loc, Chars (Formal)))));
3091 -- In all cases (including limited private types) we
3092 -- want the assignment to be valid.
3094 Set_Assignment_OK (Name (N_Node));
3096 -- If the call is the triggering alternative in an
3097 -- asynchronous select, or the entry_call alternative
3098 -- of a conditional entry call, the assignments for in-out
3099 -- parameters are incorporated into the statement list
3100 -- that follows, so that there are executed only if the
3101 -- entry call succeeds.
3103 if (Nkind (Parent (N)) = N_Triggering_Alternative
3104 and then N = Triggering_Statement (Parent (N)))
3105 or else
3106 (Nkind (Parent (N)) = N_Entry_Call_Alternative
3107 and then N = Entry_Call_Statement (Parent (N)))
3108 then
3109 if No (Statements (Parent (N))) then
3110 Set_Statements (Parent (N), New_List);
3111 end if;
3113 Prepend (N_Node, Statements (Parent (N)));
3115 else
3116 Insert_After (Call, N_Node);
3117 end if;
3118 end if;
3120 Next_Actual (Actual);
3121 Next_Formal_With_Extras (Formal);
3122 end loop;
3123 end if;
3125 -- Finally, create block and analyze it
3127 Rewrite (N,
3128 Make_Block_Statement (Loc,
3129 Declarations => Decls,
3130 Handled_Statement_Sequence =>
3131 Make_Handled_Sequence_Of_Statements (Loc,
3132 Statements => Stats)));
3134 Analyze (N);
3135 end;
3136 end Build_Simple_Entry_Call;
3138 --------------------------------
3139 -- Build_Task_Activation_Call --
3140 --------------------------------
3142 procedure Build_Task_Activation_Call (N : Node_Id) is
3143 Loc : constant Source_Ptr := Sloc (N);
3144 Chain : Entity_Id;
3145 Call : Node_Id;
3146 Name : Node_Id;
3147 P : Node_Id;
3149 begin
3150 -- Get the activation chain entity. Except in the case of a package
3151 -- body, this is in the node that w as passed. For a package body, we
3152 -- have to find the corresponding package declaration node.
3154 if Nkind (N) = N_Package_Body then
3155 P := Corresponding_Spec (N);
3157 loop
3158 P := Parent (P);
3159 exit when Nkind (P) = N_Package_Declaration;
3160 end loop;
3162 Chain := Activation_Chain_Entity (P);
3164 else
3165 Chain := Activation_Chain_Entity (N);
3166 end if;
3168 if Present (Chain) then
3169 if Restricted_Profile then
3170 Name := New_Reference_To (RTE (RE_Activate_Restricted_Tasks), Loc);
3171 else
3172 Name := New_Reference_To (RTE (RE_Activate_Tasks), Loc);
3173 end if;
3175 Call :=
3176 Make_Procedure_Call_Statement (Loc,
3177 Name => Name,
3178 Parameter_Associations =>
3179 New_List (Make_Attribute_Reference (Loc,
3180 Prefix => New_Occurrence_Of (Chain, Loc),
3181 Attribute_Name => Name_Unchecked_Access)));
3183 if Nkind (N) = N_Package_Declaration then
3184 if Present (Corresponding_Body (N)) then
3185 null;
3187 elsif Present (Private_Declarations (Specification (N))) then
3188 Append (Call, Private_Declarations (Specification (N)));
3190 else
3191 Append (Call, Visible_Declarations (Specification (N)));
3192 end if;
3194 else
3195 if Present (Handled_Statement_Sequence (N)) then
3197 -- The call goes at the start of the statement sequence, but
3198 -- after the start of exception range label if one is present.
3200 declare
3201 Stm : Node_Id;
3203 begin
3204 Stm := First (Statements (Handled_Statement_Sequence (N)));
3206 if Nkind (Stm) = N_Label and then Exception_Junk (Stm) then
3207 Next (Stm);
3208 end if;
3210 Insert_Before (Stm, Call);
3211 end;
3213 else
3214 Set_Handled_Statement_Sequence (N,
3215 Make_Handled_Sequence_Of_Statements (Loc,
3216 Statements => New_List (Call)));
3217 end if;
3218 end if;
3220 Analyze (Call);
3221 Check_Task_Activation (N);
3222 end if;
3223 end Build_Task_Activation_Call;
3225 -------------------------------
3226 -- Build_Task_Allocate_Block --
3227 -------------------------------
3229 procedure Build_Task_Allocate_Block
3230 (Actions : List_Id;
3231 N : Node_Id;
3232 Args : List_Id)
3234 T : constant Entity_Id := Entity (Expression (N));
3235 Init : constant Entity_Id := Base_Init_Proc (T);
3236 Loc : constant Source_Ptr := Sloc (N);
3237 Chain : constant Entity_Id :=
3238 Make_Defining_Identifier (Loc, Name_uChain);
3240 Blkent : Entity_Id;
3241 Block : Node_Id;
3243 begin
3244 Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3246 Block :=
3247 Make_Block_Statement (Loc,
3248 Identifier => New_Reference_To (Blkent, Loc),
3249 Declarations => New_List (
3251 -- _Chain : Activation_Chain;
3253 Make_Object_Declaration (Loc,
3254 Defining_Identifier => Chain,
3255 Aliased_Present => True,
3256 Object_Definition =>
3257 New_Reference_To (RTE (RE_Activation_Chain), Loc))),
3259 Handled_Statement_Sequence =>
3260 Make_Handled_Sequence_Of_Statements (Loc,
3262 Statements => New_List (
3264 -- Init (Args);
3266 Make_Procedure_Call_Statement (Loc,
3267 Name => New_Reference_To (Init, Loc),
3268 Parameter_Associations => Args),
3270 -- Activate_Tasks (_Chain);
3272 Make_Procedure_Call_Statement (Loc,
3273 Name => New_Reference_To (RTE (RE_Activate_Tasks), Loc),
3274 Parameter_Associations => New_List (
3275 Make_Attribute_Reference (Loc,
3276 Prefix => New_Reference_To (Chain, Loc),
3277 Attribute_Name => Name_Unchecked_Access))))),
3279 Has_Created_Identifier => True,
3280 Is_Task_Allocation_Block => True);
3282 Append_To (Actions,
3283 Make_Implicit_Label_Declaration (Loc,
3284 Defining_Identifier => Blkent,
3285 Label_Construct => Block));
3287 Append_To (Actions, Block);
3289 Set_Activation_Chain_Entity (Block, Chain);
3290 end Build_Task_Allocate_Block;
3292 -----------------------------------------------
3293 -- Build_Task_Allocate_Block_With_Init_Stmts --
3294 -----------------------------------------------
3296 procedure Build_Task_Allocate_Block_With_Init_Stmts
3297 (Actions : List_Id;
3298 N : Node_Id;
3299 Init_Stmts : List_Id)
3301 Loc : constant Source_Ptr := Sloc (N);
3302 Chain : constant Entity_Id :=
3303 Make_Defining_Identifier (Loc, Name_uChain);
3304 Blkent : Entity_Id;
3305 Block : Node_Id;
3307 begin
3308 Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3310 Append_To (Init_Stmts,
3311 Make_Procedure_Call_Statement (Loc,
3312 Name => New_Reference_To (RTE (RE_Activate_Tasks), Loc),
3313 Parameter_Associations => New_List (
3314 Make_Attribute_Reference (Loc,
3315 Prefix => New_Reference_To (Chain, Loc),
3316 Attribute_Name => Name_Unchecked_Access))));
3318 Block :=
3319 Make_Block_Statement (Loc,
3320 Identifier => New_Reference_To (Blkent, Loc),
3321 Declarations => New_List (
3323 -- _Chain : Activation_Chain;
3325 Make_Object_Declaration (Loc,
3326 Defining_Identifier => Chain,
3327 Aliased_Present => True,
3328 Object_Definition =>
3329 New_Reference_To (RTE (RE_Activation_Chain), Loc))),
3331 Handled_Statement_Sequence =>
3332 Make_Handled_Sequence_Of_Statements (Loc, Init_Stmts),
3334 Has_Created_Identifier => True,
3335 Is_Task_Allocation_Block => True);
3337 Append_To (Actions,
3338 Make_Implicit_Label_Declaration (Loc,
3339 Defining_Identifier => Blkent,
3340 Label_Construct => Block));
3342 Append_To (Actions, Block);
3344 Set_Activation_Chain_Entity (Block, Chain);
3345 end Build_Task_Allocate_Block_With_Init_Stmts;
3347 -----------------------------------
3348 -- Build_Task_Proc_Specification --
3349 -----------------------------------
3351 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
3352 Loc : constant Source_Ptr := Sloc (T);
3353 Nam : constant Name_Id := Chars (T);
3354 Ent : Entity_Id;
3356 begin
3357 Ent :=
3358 Make_Defining_Identifier (Loc,
3359 Chars => New_External_Name (Nam, 'B'));
3360 Set_Is_Internal (Ent);
3362 -- Associate the procedure with the task, if this is the declaration
3363 -- (and not the body) of the procedure.
3365 if No (Task_Body_Procedure (T)) then
3366 Set_Task_Body_Procedure (T, Ent);
3367 end if;
3369 return
3370 Make_Procedure_Specification (Loc,
3371 Defining_Unit_Name => Ent,
3372 Parameter_Specifications =>
3373 New_List (
3374 Make_Parameter_Specification (Loc,
3375 Defining_Identifier =>
3376 Make_Defining_Identifier (Loc, Name_uTask),
3377 Parameter_Type =>
3378 Make_Access_Definition (Loc,
3379 Subtype_Mark =>
3380 New_Reference_To
3381 (Corresponding_Record_Type (T), Loc)))));
3382 end Build_Task_Proc_Specification;
3384 ---------------------------------------
3385 -- Build_Unprotected_Subprogram_Body --
3386 ---------------------------------------
3388 function Build_Unprotected_Subprogram_Body
3389 (N : Node_Id;
3390 Pid : Node_Id) return Node_Id
3392 Loc : constant Source_Ptr := Sloc (N);
3393 N_Op_Spec : Node_Id;
3394 Op_Decls : List_Id;
3396 begin
3397 -- Make an unprotected version of the subprogram for use
3398 -- within the same object, with a new name and an additional
3399 -- parameter representing the object.
3401 Op_Decls := Declarations (N);
3402 N_Op_Spec :=
3403 Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode);
3405 return
3406 Make_Subprogram_Body (Loc,
3407 Specification => N_Op_Spec,
3408 Declarations => Op_Decls,
3409 Handled_Statement_Sequence =>
3410 Handled_Statement_Sequence (N));
3411 end Build_Unprotected_Subprogram_Body;
3413 ----------------------------
3414 -- Collect_Entry_Families --
3415 ----------------------------
3417 procedure Collect_Entry_Families
3418 (Loc : Source_Ptr;
3419 Cdecls : List_Id;
3420 Current_Node : in out Node_Id;
3421 Conctyp : Entity_Id)
3423 Efam : Entity_Id;
3424 Efam_Decl : Node_Id;
3425 Efam_Type : Entity_Id;
3427 begin
3428 Efam := First_Entity (Conctyp);
3430 while Present (Efam) loop
3432 if Ekind (Efam) = E_Entry_Family then
3433 Efam_Type :=
3434 Make_Defining_Identifier (Loc,
3435 Chars => New_Internal_Name ('F'));
3437 Efam_Decl :=
3438 Make_Full_Type_Declaration (Loc,
3439 Defining_Identifier => Efam_Type,
3440 Type_Definition =>
3441 Make_Unconstrained_Array_Definition (Loc,
3442 Subtype_Marks => (New_List (
3443 New_Occurrence_Of (
3444 Base_Type
3445 (Etype (Discrete_Subtype_Definition
3446 (Parent (Efam)))), Loc))),
3448 Component_Definition =>
3449 Make_Component_Definition (Loc,
3450 Aliased_Present => False,
3451 Subtype_Indication =>
3452 New_Reference_To (Standard_Character, Loc))));
3454 Insert_After (Current_Node, Efam_Decl);
3455 Current_Node := Efam_Decl;
3456 Analyze (Efam_Decl);
3458 Append_To (Cdecls,
3459 Make_Component_Declaration (Loc,
3460 Defining_Identifier =>
3461 Make_Defining_Identifier (Loc, Chars (Efam)),
3463 Component_Definition =>
3464 Make_Component_Definition (Loc,
3465 Aliased_Present => False,
3466 Subtype_Indication =>
3467 Make_Subtype_Indication (Loc,
3468 Subtype_Mark =>
3469 New_Occurrence_Of (Efam_Type, Loc),
3471 Constraint =>
3472 Make_Index_Or_Discriminant_Constraint (Loc,
3473 Constraints => New_List (
3474 New_Occurrence_Of
3475 (Etype (Discrete_Subtype_Definition
3476 (Parent (Efam))), Loc)))))));
3478 end if;
3480 Next_Entity (Efam);
3481 end loop;
3482 end Collect_Entry_Families;
3484 --------------------
3485 -- Concurrent_Ref --
3486 --------------------
3488 -- The expression returned for a reference to a concurrent
3489 -- object has the form:
3491 -- taskV!(name)._Task_Id
3493 -- for a task, and
3495 -- objectV!(name)._Object
3497 -- for a protected object. For the case of an access to a concurrent
3498 -- object, there is an extra explicit dereference:
3500 -- taskV!(name.all)._Task_Id
3501 -- objectV!(name.all)._Object
3503 -- here taskV and objectV are the types for the associated records, which
3504 -- contain the required _Task_Id and _Object fields for tasks and
3505 -- protected objects, respectively.
3507 -- For the case of a task type name, the expression is
3509 -- Self;
3511 -- i.e. a call to the Self function which returns precisely this Task_Id
3513 -- For the case of a protected type name, the expression is
3515 -- objectR
3517 -- which is a renaming of the _object field of the current object
3518 -- object record, passed into protected operations as a parameter.
3520 function Concurrent_Ref (N : Node_Id) return Node_Id is
3521 Loc : constant Source_Ptr := Sloc (N);
3522 Ntyp : constant Entity_Id := Etype (N);
3523 Dtyp : Entity_Id;
3524 Sel : Name_Id;
3526 function Is_Current_Task (T : Entity_Id) return Boolean;
3527 -- Check whether the reference is to the immediately enclosing task
3528 -- type, or to an outer one (rare but legal).
3530 ---------------------
3531 -- Is_Current_Task --
3532 ---------------------
3534 function Is_Current_Task (T : Entity_Id) return Boolean is
3535 Scop : Entity_Id;
3537 begin
3538 Scop := Current_Scope;
3539 while Present (Scop)
3540 and then Scop /= Standard_Standard
3541 loop
3543 if Scop = T then
3544 return True;
3546 elsif Is_Task_Type (Scop) then
3547 return False;
3549 -- If this is a procedure nested within the task type, we must
3550 -- assume that it can be called from an inner task, and therefore
3551 -- cannot treat it as a local reference.
3553 elsif Is_Overloadable (Scop)
3554 and then In_Open_Scopes (T)
3555 then
3556 return False;
3558 else
3559 Scop := Scope (Scop);
3560 end if;
3561 end loop;
3563 -- We know that we are within the task body, so should have
3564 -- found it in scope.
3566 raise Program_Error;
3567 end Is_Current_Task;
3569 -- Start of processing for Concurrent_Ref
3571 begin
3572 if Is_Access_Type (Ntyp) then
3573 Dtyp := Designated_Type (Ntyp);
3575 if Is_Protected_Type (Dtyp) then
3576 Sel := Name_uObject;
3577 else
3578 Sel := Name_uTask_Id;
3579 end if;
3581 return
3582 Make_Selected_Component (Loc,
3583 Prefix =>
3584 Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
3585 Make_Explicit_Dereference (Loc, N)),
3586 Selector_Name => Make_Identifier (Loc, Sel));
3588 elsif Is_Entity_Name (N)
3589 and then Is_Concurrent_Type (Entity (N))
3590 then
3591 if Is_Task_Type (Entity (N)) then
3593 if Is_Current_Task (Entity (N)) then
3594 return
3595 Make_Function_Call (Loc,
3596 Name => New_Reference_To (RTE (RE_Self), Loc));
3598 else
3599 declare
3600 Decl : Node_Id;
3601 T_Self : constant Entity_Id
3602 := Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
3603 T_Body : constant Node_Id
3604 := Parent (Corresponding_Body (Parent (Entity (N))));
3606 begin
3607 Decl := Make_Object_Declaration (Loc,
3608 Defining_Identifier => T_Self,
3609 Object_Definition =>
3610 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
3611 Expression =>
3612 Make_Function_Call (Loc,
3613 Name => New_Reference_To (RTE (RE_Self), Loc)));
3614 Prepend (Decl, Declarations (T_Body));
3615 Analyze (Decl);
3616 Set_Scope (T_Self, Entity (N));
3617 return New_Occurrence_Of (T_Self, Loc);
3618 end;
3619 end if;
3621 else
3622 pragma Assert (Is_Protected_Type (Entity (N)));
3623 return
3624 New_Reference_To (
3625 Object_Ref (Corresponding_Body (Parent (Base_Type (Ntyp)))),
3626 Loc);
3627 end if;
3629 else
3630 pragma Assert (Is_Concurrent_Type (Ntyp));
3632 if Is_Protected_Type (Ntyp) then
3633 Sel := Name_uObject;
3634 else
3635 Sel := Name_uTask_Id;
3636 end if;
3638 return
3639 Make_Selected_Component (Loc,
3640 Prefix =>
3641 Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
3642 New_Copy_Tree (N)),
3643 Selector_Name => Make_Identifier (Loc, Sel));
3644 end if;
3645 end Concurrent_Ref;
3647 ------------------------
3648 -- Convert_Concurrent --
3649 ------------------------
3651 function Convert_Concurrent
3652 (N : Node_Id;
3653 Typ : Entity_Id) return Node_Id
3655 begin
3656 if not Is_Concurrent_Type (Typ) then
3657 return N;
3658 else
3659 return
3660 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
3661 New_Copy_Tree (N));
3662 end if;
3663 end Convert_Concurrent;
3665 ----------------------------
3666 -- Entry_Index_Expression --
3667 ----------------------------
3669 function Entry_Index_Expression
3670 (Sloc : Source_Ptr;
3671 Ent : Entity_Id;
3672 Index : Node_Id;
3673 Ttyp : Entity_Id) return Node_Id
3675 Expr : Node_Id;
3676 Num : Node_Id;
3677 Lo : Node_Id;
3678 Hi : Node_Id;
3679 Prev : Entity_Id;
3680 S : Node_Id;
3682 begin
3683 -- The queues of entries and entry families appear in textual
3684 -- order in the associated record. The entry index is computed as
3685 -- the sum of the number of queues for all entries that precede the
3686 -- designated one, to which is added the index expression, if this
3687 -- expression denotes a member of a family.
3689 -- The following is a place holder for the count of simple entries
3691 Num := Make_Integer_Literal (Sloc, 1);
3693 -- We construct an expression which is a series of addition
3694 -- operations. The first operand is the number of single entries that
3695 -- precede this one, the second operand is the index value relative
3696 -- to the start of the referenced family, and the remaining operands
3697 -- are the lengths of the entry families that precede this entry, i.e.
3698 -- the constructed expression is:
3700 -- number_simple_entries +
3701 -- (s'pos (index-value) - s'pos (family'first)) + 1 +
3702 -- family'length + ...
3704 -- where index-value is the given index value, and s is the index
3705 -- subtype (we have to use pos because the subtype might be an
3706 -- enumeration type preventing direct subtraction).
3707 -- Note that the task entry array is one-indexed.
3709 -- The upper bound of the entry family may be a discriminant, so we
3710 -- retrieve the lower bound explicitly to compute offset, rather than
3711 -- using the index subtype which may mention a discriminant.
3713 if Present (Index) then
3714 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
3716 Expr :=
3717 Make_Op_Add (Sloc,
3718 Left_Opnd => Num,
3720 Right_Opnd =>
3721 Family_Offset (
3722 Sloc,
3723 Make_Attribute_Reference (Sloc,
3724 Attribute_Name => Name_Pos,
3725 Prefix => New_Reference_To (Base_Type (S), Sloc),
3726 Expressions => New_List (Relocate_Node (Index))),
3727 Type_Low_Bound (S),
3728 Ttyp));
3729 else
3730 Expr := Num;
3731 end if;
3733 -- Now add lengths of preceding entries and entry families
3735 Prev := First_Entity (Ttyp);
3737 while Chars (Prev) /= Chars (Ent)
3738 or else (Ekind (Prev) /= Ekind (Ent))
3739 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
3740 loop
3741 if Ekind (Prev) = E_Entry then
3742 Set_Intval (Num, Intval (Num) + 1);
3744 elsif Ekind (Prev) = E_Entry_Family then
3745 S :=
3746 Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
3747 Lo := Type_Low_Bound (S);
3748 Hi := Type_High_Bound (S);
3750 Expr :=
3751 Make_Op_Add (Sloc,
3752 Left_Opnd => Expr,
3753 Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp));
3755 -- Other components are anonymous types to be ignored
3757 else
3758 null;
3759 end if;
3761 Next_Entity (Prev);
3762 end loop;
3764 return Expr;
3765 end Entry_Index_Expression;
3767 ---------------------------
3768 -- Establish_Task_Master --
3769 ---------------------------
3771 procedure Establish_Task_Master (N : Node_Id) is
3772 Call : Node_Id;
3774 begin
3775 if Restriction_Active (No_Task_Hierarchy) = False then
3776 Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
3777 Prepend_To (Declarations (N), Call);
3778 Analyze (Call);
3779 end if;
3780 end Establish_Task_Master;
3782 --------------------------------
3783 -- Expand_Accept_Declarations --
3784 --------------------------------
3786 -- Part of the expansion of an accept statement involves the creation of
3787 -- a declaration that can be referenced from the statement sequence of
3788 -- the accept:
3790 -- Ann : Address;
3792 -- This declaration is inserted immediately before the accept statement
3793 -- and it is important that it be inserted before the statements of the
3794 -- statement sequence are analyzed. Thus it would be too late to create
3795 -- this declaration in the Expand_N_Accept_Statement routine, which is
3796 -- why there is a separate procedure to be called directly from Sem_Ch9.
3798 -- Ann is used to hold the address of the record containing the parameters
3799 -- (see Expand_N_Entry_Call for more details on how this record is built).
3800 -- References to the parameters do an unchecked conversion of this address
3801 -- to a pointer to the required record type, and then access the field that
3802 -- holds the value of the required parameter. The entity for the address
3803 -- variable is held as the top stack element (i.e. the last element) of the
3804 -- Accept_Address stack in the corresponding entry entity, and this element
3805 -- must be set in place before the statements are processed.
3807 -- The above description applies to the case of a stand alone accept
3808 -- statement, i.e. one not appearing as part of a select alternative.
3810 -- For the case of an accept that appears as part of a select alternative
3811 -- of a selective accept, we must still create the declaration right away,
3812 -- since Ann is needed immediately, but there is an important difference:
3814 -- The declaration is inserted before the selective accept, not before
3815 -- the accept statement (which is not part of a list anyway, and so would
3816 -- not accommodate inserted declarations)
3818 -- We only need one address variable for the entire selective accept. So
3819 -- the Ann declaration is created only for the first accept alternative,
3820 -- and subsequent accept alternatives reference the same Ann variable.
3822 -- We can distinguish the two cases by seeing whether the accept statement
3823 -- is part of a list. If not, then it must be in an accept alternative.
3825 -- To expand the requeue statement, a label is provided at the end of
3826 -- the accept statement or alternative of which it is a part, so that
3827 -- the statement can be skipped after the requeue is complete.
3828 -- This label is created here rather than during the expansion of the
3829 -- accept statement, because it will be needed by any requeue
3830 -- statements within the accept, which are expanded before the
3831 -- accept.
3833 procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
3834 Loc : constant Source_Ptr := Sloc (N);
3835 Ann : Entity_Id := Empty;
3836 Adecl : Node_Id;
3837 Lab_Id : Node_Id;
3838 Lab : Node_Id;
3839 Ldecl : Node_Id;
3840 Ldecl2 : Node_Id;
3842 begin
3843 if Expander_Active then
3845 -- If we have no handled statement sequence, then build a dummy
3846 -- sequence consisting of a null statement. This is only done if
3847 -- pragma FIFO_Within_Priorities is specified. The issue here is
3848 -- that even a null accept body has an effect on the called task
3849 -- in terms of its position in the queue, so we cannot optimize
3850 -- the context switch away. However, if FIFO_Within_Priorities
3851 -- is not active, the optimization is legitimate, since we can
3852 -- say that our dispatching policy (i.e. the default dispatching
3853 -- policy) reorders the queue to be the same as just before the
3854 -- call. In the absence of a specified dispatching policy, we are
3855 -- allowed to modify queue orders for a given priority at will!
3857 if Opt.Task_Dispatching_Policy = 'F' and then
3858 not Present (Handled_Statement_Sequence (N))
3859 then
3860 Set_Handled_Statement_Sequence (N,
3861 Make_Handled_Sequence_Of_Statements (Loc,
3862 New_List (Make_Null_Statement (Loc))));
3863 end if;
3865 -- Create and declare two labels to be placed at the end of the
3866 -- accept statement. The first label is used to allow requeues to
3867 -- skip the remainder of entry processing. The second label is
3868 -- used to skip the remainder of entry processing if the rendezvous
3869 -- completes in the middle of the accept body.
3871 if Present (Handled_Statement_Sequence (N)) then
3872 Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
3873 Set_Entity (Lab_Id,
3874 Make_Defining_Identifier (Loc, Chars (Lab_Id)));
3875 Lab := Make_Label (Loc, Lab_Id);
3876 Ldecl :=
3877 Make_Implicit_Label_Declaration (Loc,
3878 Defining_Identifier => Entity (Lab_Id),
3879 Label_Construct => Lab);
3880 Append (Lab, Statements (Handled_Statement_Sequence (N)));
3882 Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
3883 Set_Entity (Lab_Id,
3884 Make_Defining_Identifier (Loc, Chars (Lab_Id)));
3885 Lab := Make_Label (Loc, Lab_Id);
3886 Ldecl2 :=
3887 Make_Implicit_Label_Declaration (Loc,
3888 Defining_Identifier => Entity (Lab_Id),
3889 Label_Construct => Lab);
3890 Append (Lab, Statements (Handled_Statement_Sequence (N)));
3892 else
3893 Ldecl := Empty;
3894 Ldecl2 := Empty;
3895 end if;
3897 -- Case of stand alone accept statement
3899 if Is_List_Member (N) then
3901 if Present (Handled_Statement_Sequence (N)) then
3902 Ann :=
3903 Make_Defining_Identifier (Loc,
3904 Chars => New_Internal_Name ('A'));
3906 Adecl :=
3907 Make_Object_Declaration (Loc,
3908 Defining_Identifier => Ann,
3909 Object_Definition =>
3910 New_Reference_To (RTE (RE_Address), Loc));
3912 Insert_Before (N, Adecl);
3913 Analyze (Adecl);
3915 Insert_Before (N, Ldecl);
3916 Analyze (Ldecl);
3918 Insert_Before (N, Ldecl2);
3919 Analyze (Ldecl2);
3920 end if;
3922 -- Case of accept statement which is in an accept alternative
3924 else
3925 declare
3926 Acc_Alt : constant Node_Id := Parent (N);
3927 Sel_Acc : constant Node_Id := Parent (Acc_Alt);
3928 Alt : Node_Id;
3930 begin
3931 pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
3932 pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
3934 -- ??? Consider a single label for select statements
3936 if Present (Handled_Statement_Sequence (N)) then
3937 Prepend (Ldecl2,
3938 Statements (Handled_Statement_Sequence (N)));
3939 Analyze (Ldecl2);
3941 Prepend (Ldecl,
3942 Statements (Handled_Statement_Sequence (N)));
3943 Analyze (Ldecl);
3944 end if;
3946 -- Find first accept alternative of the selective accept. A
3947 -- valid selective accept must have at least one accept in it.
3949 Alt := First (Select_Alternatives (Sel_Acc));
3951 while Nkind (Alt) /= N_Accept_Alternative loop
3952 Next (Alt);
3953 end loop;
3955 -- If we are the first accept statement, then we have to
3956 -- create the Ann variable, as for the stand alone case,
3957 -- except that it is inserted before the selective accept.
3958 -- Similarly, a label for requeue expansion must be
3959 -- declared.
3961 if N = Accept_Statement (Alt) then
3962 Ann :=
3963 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3965 Adecl :=
3966 Make_Object_Declaration (Loc,
3967 Defining_Identifier => Ann,
3968 Object_Definition =>
3969 New_Reference_To (RTE (RE_Address), Loc));
3971 Insert_Before (Sel_Acc, Adecl);
3972 Analyze (Adecl);
3974 -- If we are not the first accept statement, then find the
3975 -- Ann variable allocated by the first accept and use it.
3977 else
3978 Ann :=
3979 Node (Last_Elmt (Accept_Address
3980 (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
3981 end if;
3982 end;
3983 end if;
3985 -- Merge here with Ann either created or referenced, and Adecl
3986 -- pointing to the corresponding declaration. Remaining processing
3987 -- is the same for the two cases.
3989 if Present (Ann) then
3990 Append_Elmt (Ann, Accept_Address (Ent));
3991 Set_Needs_Debug_Info (Ann);
3992 end if;
3994 -- Create renaming declarations for the entry formals. Each
3995 -- reference to a formal becomes a dereference of a component
3996 -- of the parameter block, whose address is held in Ann.
3997 -- These declarations are eventually inserted into the accept
3998 -- block, and analyzed there so that they have the proper scope
3999 -- for gdb and do not conflict with other declarations.
4001 if Present (Parameter_Specifications (N))
4002 and then Present (Handled_Statement_Sequence (N))
4003 then
4004 declare
4005 Formal : Entity_Id;
4006 New_F : Entity_Id;
4007 Comp : Entity_Id;
4008 Decl : Node_Id;
4010 begin
4011 New_Scope (Ent);
4012 Formal := First_Formal (Ent);
4014 while Present (Formal) loop
4015 Comp := Entry_Component (Formal);
4016 New_F :=
4017 Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
4018 Set_Etype (New_F, Etype (Formal));
4019 Set_Scope (New_F, Ent);
4020 Set_Needs_Debug_Info (New_F); -- That's the whole point.
4022 if Ekind (Formal) = E_In_Parameter then
4023 Set_Ekind (New_F, E_Constant);
4024 else
4025 Set_Ekind (New_F, E_Variable);
4026 Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
4027 end if;
4029 Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
4031 Decl :=
4032 Make_Object_Renaming_Declaration (Loc,
4033 Defining_Identifier => New_F,
4034 Subtype_Mark => New_Reference_To (Etype (Formal), Loc),
4035 Name =>
4036 Make_Explicit_Dereference (Loc,
4037 Make_Selected_Component (Loc,
4038 Prefix =>
4039 Unchecked_Convert_To (Entry_Parameters_Type (Ent),
4040 New_Reference_To (Ann, Loc)),
4041 Selector_Name =>
4042 New_Reference_To (Comp, Loc))));
4044 if No (Declarations (N)) then
4045 Set_Declarations (N, New_List);
4046 end if;
4048 Append (Decl, Declarations (N));
4049 Set_Renamed_Object (Formal, New_F);
4050 Next_Formal (Formal);
4051 end loop;
4053 End_Scope;
4054 end;
4055 end if;
4056 end if;
4057 end Expand_Accept_Declarations;
4059 ---------------------------------------------
4060 -- Expand_Access_Protected_Subprogram_Type --
4061 ---------------------------------------------
4063 procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
4064 Loc : constant Source_Ptr := Sloc (N);
4065 Comps : List_Id;
4066 T : constant Entity_Id := Defining_Identifier (N);
4067 D_T : constant Entity_Id := Designated_Type (T);
4068 D_T2 : constant Entity_Id := Make_Defining_Identifier
4069 (Loc, New_Internal_Name ('D'));
4070 E_T : constant Entity_Id := Make_Defining_Identifier
4071 (Loc, New_Internal_Name ('E'));
4072 P_List : constant List_Id := Build_Protected_Spec
4073 (N, RTE (RE_Address), False, D_T);
4074 Decl1 : Node_Id;
4075 Decl2 : Node_Id;
4076 Def1 : Node_Id;
4078 begin
4079 -- Create access to protected subprogram with full signature
4081 if Nkind (Type_Definition (N)) = N_Access_Function_Definition then
4082 Def1 :=
4083 Make_Access_Function_Definition (Loc,
4084 Parameter_Specifications => P_List,
4085 Result_Definition =>
4086 New_Copy (Result_Definition (Type_Definition (N))));
4088 else
4089 Def1 :=
4090 Make_Access_Procedure_Definition (Loc,
4091 Parameter_Specifications => P_List);
4092 end if;
4094 Decl1 :=
4095 Make_Full_Type_Declaration (Loc,
4096 Defining_Identifier => D_T2,
4097 Type_Definition => Def1);
4099 Analyze (Decl1);
4100 Insert_After (N, Decl1);
4102 -- Create Equivalent_Type, a record with two components for an
4103 -- access to object and an access to subprogram.
4105 Comps := New_List (
4106 Make_Component_Declaration (Loc,
4107 Defining_Identifier =>
4108 Make_Defining_Identifier (Loc, New_Internal_Name ('P')),
4109 Component_Definition =>
4110 Make_Component_Definition (Loc,
4111 Aliased_Present => False,
4112 Subtype_Indication =>
4113 New_Occurrence_Of (RTE (RE_Address), Loc))),
4115 Make_Component_Declaration (Loc,
4116 Defining_Identifier =>
4117 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
4118 Component_Definition =>
4119 Make_Component_Definition (Loc,
4120 Aliased_Present => False,
4121 Subtype_Indication => New_Occurrence_Of (D_T2, Loc))));
4123 Decl2 :=
4124 Make_Full_Type_Declaration (Loc,
4125 Defining_Identifier => E_T,
4126 Type_Definition =>
4127 Make_Record_Definition (Loc,
4128 Component_List =>
4129 Make_Component_List (Loc,
4130 Component_Items => Comps)));
4132 Analyze (Decl2);
4133 Insert_After (Decl1, Decl2);
4134 Set_Equivalent_Type (T, E_T);
4135 end Expand_Access_Protected_Subprogram_Type;
4137 --------------------------
4138 -- Expand_Entry_Barrier --
4139 --------------------------
4141 procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
4142 Loc : constant Source_Ptr := Sloc (N);
4143 Prot : constant Entity_Id := Scope (Ent);
4144 Spec_Decl : constant Node_Id := Parent (Prot);
4145 Cond : constant Node_Id :=
4146 Condition (Entry_Body_Formal_Part (N));
4147 Func : Node_Id;
4148 B_F : Node_Id;
4149 Body_Decl : Node_Id;
4151 begin
4152 if No_Run_Time_Mode then
4153 Error_Msg_CRT ("entry barrier", N);
4154 return;
4155 end if;
4157 -- The body of the entry barrier must be analyzed in the context of
4158 -- the protected object, but its scope is external to it, just as any
4159 -- other unprotected version of a protected operation. The specification
4160 -- has been produced when the protected type declaration was elaborated.
4161 -- We build the body, insert it in the enclosing scope, but analyze it
4162 -- in the current context. A more uniform approach would be to treat a
4163 -- barrier just as a protected function, and discard the protected
4164 -- version of it because it is never called.
4166 if Expander_Active then
4167 B_F := Build_Barrier_Function (N, Ent, Prot);
4168 Func := Barrier_Function (Ent);
4169 Set_Corresponding_Spec (B_F, Func);
4171 Body_Decl := Parent (Corresponding_Body (Spec_Decl));
4173 if Nkind (Parent (Body_Decl)) = N_Subunit then
4174 Body_Decl := Corresponding_Stub (Parent (Body_Decl));
4175 end if;
4177 Insert_Before_And_Analyze (Body_Decl, B_F);
4179 Update_Prival_Subtypes (B_F);
4181 Set_Privals (Spec_Decl, N, Loc);
4182 Set_Discriminals (Spec_Decl);
4183 Set_Scope (Func, Scope (Prot));
4185 else
4186 Analyze_And_Resolve (Cond, Any_Boolean);
4187 end if;
4189 -- The Ravenscar profile restricts barriers to simple variables
4190 -- declared within the protected object. We also allow Boolean
4191 -- constants, since these appear in several published examples
4192 -- and are also allowed by the Aonix compiler.
4194 -- Note that after analysis variables in this context will be
4195 -- replaced by the corresponding prival, that is to say a renaming
4196 -- of a selected component of the form _Object.Var. If expansion is
4197 -- disabled, as within a generic, we check that the entity appears in
4198 -- the current scope.
4200 if Is_Entity_Name (Cond) then
4202 if Entity (Cond) = Standard_False
4203 or else
4204 Entity (Cond) = Standard_True
4205 then
4206 return;
4208 elsif not Expander_Active
4209 and then Scope (Entity (Cond)) = Current_Scope
4210 then
4211 return;
4213 -- Check for case of _object.all.field (note that the explicit
4214 -- dereference gets inserted by analyze/expand of _object.field)
4216 elsif Present (Renamed_Object (Entity (Cond)))
4217 and then
4218 Nkind (Renamed_Object (Entity (Cond))) = N_Selected_Component
4219 and then
4220 Chars
4221 (Prefix
4222 (Prefix (Renamed_Object (Entity (Cond))))) = Name_uObject
4223 then
4224 return;
4225 end if;
4226 end if;
4228 -- It is not a boolean variable or literal, so check the restriction
4230 Check_Restriction (Simple_Barriers, Cond);
4231 end Expand_Entry_Barrier;
4233 ------------------------------------
4234 -- Expand_Entry_Body_Declarations --
4235 ------------------------------------
4237 procedure Expand_Entry_Body_Declarations (N : Node_Id) is
4238 Loc : constant Source_Ptr := Sloc (N);
4239 Index_Spec : Node_Id;
4241 begin
4242 if Expander_Active then
4244 -- Expand entry bodies corresponding to entry families
4245 -- by assigning a placeholder for the constant that will
4246 -- be used to expand references to the entry index parameter.
4248 Index_Spec :=
4249 Entry_Index_Specification (Entry_Body_Formal_Part (N));
4251 if Present (Index_Spec) then
4252 Set_Entry_Index_Constant (
4253 Defining_Identifier (Index_Spec),
4254 Make_Defining_Identifier (Loc, New_Internal_Name ('J')));
4255 end if;
4256 end if;
4257 end Expand_Entry_Body_Declarations;
4259 ------------------------------
4260 -- Expand_N_Abort_Statement --
4261 ------------------------------
4263 -- Expand abort T1, T2, .. Tn; into:
4264 -- Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
4266 procedure Expand_N_Abort_Statement (N : Node_Id) is
4267 Loc : constant Source_Ptr := Sloc (N);
4268 Tlist : constant List_Id := Names (N);
4269 Count : Nat;
4270 Aggr : Node_Id;
4271 Tasknm : Node_Id;
4273 begin
4274 Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
4275 Count := 0;
4277 Tasknm := First (Tlist);
4279 while Present (Tasknm) loop
4280 Count := Count + 1;
4281 Append_To (Component_Associations (Aggr),
4282 Make_Component_Association (Loc,
4283 Choices => New_List (
4284 Make_Integer_Literal (Loc, Count)),
4285 Expression => Concurrent_Ref (Tasknm)));
4286 Next (Tasknm);
4287 end loop;
4289 Rewrite (N,
4290 Make_Procedure_Call_Statement (Loc,
4291 Name => New_Reference_To (RTE (RE_Abort_Tasks), Loc),
4292 Parameter_Associations => New_List (
4293 Make_Qualified_Expression (Loc,
4294 Subtype_Mark => New_Reference_To (RTE (RE_Task_List), Loc),
4295 Expression => Aggr))));
4297 Analyze (N);
4298 end Expand_N_Abort_Statement;
4300 -------------------------------
4301 -- Expand_N_Accept_Statement --
4302 -------------------------------
4304 -- This procedure handles expansion of accept statements that stand
4305 -- alone, i.e. they are not part of an accept alternative. The expansion
4306 -- of accept statement in accept alternatives is handled by the routines
4307 -- Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
4308 -- following description applies only to stand alone accept statements.
4310 -- If there is no handled statement sequence, or only null statements,
4311 -- then this is called a trivial accept, and the expansion is:
4313 -- Accept_Trivial (entry-index)
4315 -- If there is a handled statement sequence, then the expansion is:
4317 -- Ann : Address;
4318 -- {Lnn : Label}
4320 -- begin
4321 -- begin
4322 -- Accept_Call (entry-index, Ann);
4323 -- Renaming_Declarations for formals
4324 -- <statement sequence from N_Accept_Statement node>
4325 -- Complete_Rendezvous;
4326 -- <<Lnn>>
4328 -- exception
4329 -- when ... =>
4330 -- <exception handler from N_Accept_Statement node>
4331 -- Complete_Rendezvous;
4332 -- when ... =>
4333 -- <exception handler from N_Accept_Statement node>
4334 -- Complete_Rendezvous;
4335 -- ...
4336 -- end;
4338 -- exception
4339 -- when all others =>
4340 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
4341 -- end;
4343 -- The first three declarations were already inserted ahead of the
4344 -- accept statement by the Expand_Accept_Declarations procedure, which
4345 -- was called directly from the semantics during analysis of the accept.
4346 -- statement, before analyzing its contained statements.
4348 -- The declarations from the N_Accept_Statement, as noted in Sinfo, come
4349 -- from possible expansion activity (the original source of course does
4350 -- not have any declarations associated with the accept statement, since
4351 -- an accept statement has no declarative part). In particular, if the
4352 -- expander is active, the first such declaration is the declaration of
4353 -- the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
4355 -- The two blocks are merged into a single block if the inner block has
4356 -- no exception handlers, but otherwise two blocks are required, since
4357 -- exceptions might be raised in the exception handlers of the inner
4358 -- block, and Exceptional_Complete_Rendezvous must be called.
4360 procedure Expand_N_Accept_Statement (N : Node_Id) is
4361 Loc : constant Source_Ptr := Sloc (N);
4362 Stats : constant Node_Id := Handled_Statement_Sequence (N);
4363 Ename : constant Node_Id := Entry_Direct_Name (N);
4364 Eindx : constant Node_Id := Entry_Index (N);
4365 Eent : constant Entity_Id := Entity (Ename);
4366 Acstack : constant Elist_Id := Accept_Address (Eent);
4367 Ann : constant Entity_Id := Node (Last_Elmt (Acstack));
4368 Ttyp : constant Entity_Id := Etype (Scope (Eent));
4369 Blkent : Entity_Id;
4370 Call : Node_Id;
4371 Block : Node_Id;
4373 function Null_Statements (Stats : List_Id) return Boolean;
4374 -- Check for null statement sequence (i.e a list of labels and
4375 -- null statements)
4377 function Null_Statements (Stats : List_Id) return Boolean is
4378 Stmt : Node_Id;
4380 begin
4381 Stmt := First (Stats);
4382 while Nkind (Stmt) /= N_Empty
4383 and then (Nkind (Stmt) = N_Null_Statement
4384 or else
4385 Nkind (Stmt) = N_Label)
4386 loop
4387 Next (Stmt);
4388 end loop;
4390 return Nkind (Stmt) = N_Empty;
4391 end Null_Statements;
4393 -- Start of processing for Expand_N_Accept_Statement
4395 begin
4396 -- If accept statement is not part of a list, then its parent must be
4397 -- an accept alternative, and, as described above, we do not do any
4398 -- expansion for such accept statements at this level.
4400 if not Is_List_Member (N) then
4401 pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
4402 return;
4404 -- Trivial accept case (no statement sequence, or null statements).
4405 -- If the accept statement has declarations, then just insert them
4406 -- before the procedure call.
4408 -- We avoid this optimization when FIFO_Within_Priorities is active,
4409 -- since it is not correct according to annex D semantics. The problem
4410 -- is that the call is required to reorder the acceptors position on
4411 -- its ready queue, even though there is nothing to be done. However,
4412 -- if no policy is specified, then we decide that our dispatching
4413 -- policy always reorders the queue right after the RV to look the
4414 -- way they were just before the RV. Since we are allowed to freely
4415 -- reorder same-priority queues (this is part of what dispatching
4416 -- policies are all about), the optimization is legitimate.
4418 elsif Opt.Task_Dispatching_Policy /= 'F'
4419 and then (No (Stats) or else Null_Statements (Statements (Stats)))
4420 then
4421 -- Remove declarations for renamings, because the parameter block
4422 -- will not be assigned.
4424 declare
4425 D : Node_Id;
4426 Next_D : Node_Id;
4428 begin
4429 D := First (Declarations (N));
4431 while Present (D) loop
4432 Next_D := Next (D);
4433 if Nkind (D) = N_Object_Renaming_Declaration then
4434 Remove (D);
4435 end if;
4437 D := Next_D;
4438 end loop;
4439 end;
4441 if Present (Declarations (N)) then
4442 Insert_Actions (N, Declarations (N));
4443 end if;
4445 Rewrite (N,
4446 Make_Procedure_Call_Statement (Loc,
4447 Name => New_Reference_To (RTE (RE_Accept_Trivial), Loc),
4448 Parameter_Associations => New_List (
4449 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
4451 Analyze (N);
4453 -- Discard Entry_Address that was created for it, so it will not be
4454 -- emitted if this accept statement is in the statement part of a
4455 -- delay alternative.
4457 if Present (Stats) then
4458 Remove_Last_Elmt (Acstack);
4459 end if;
4461 -- Case of statement sequence present
4463 else
4464 -- Construct the block, using the declarations from the accept
4465 -- statement if any to initialize the declarations of the block.
4467 Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4468 Set_Ekind (Blkent, E_Block);
4469 Set_Etype (Blkent, Standard_Void_Type);
4470 Set_Scope (Blkent, Current_Scope);
4472 Block :=
4473 Make_Block_Statement (Loc,
4474 Identifier => New_Reference_To (Blkent, Loc),
4475 Declarations => Declarations (N),
4476 Handled_Statement_Sequence => Build_Accept_Body (N));
4478 -- Prepend call to Accept_Call to main statement sequence
4479 -- If the accept has exception handlers, the statement sequence
4480 -- is wrapped in a block. Insert call and renaming declarations
4481 -- in the declarations of the block, so they are elaborated before
4482 -- the handlers.
4484 Call :=
4485 Make_Procedure_Call_Statement (Loc,
4486 Name => New_Reference_To (RTE (RE_Accept_Call), Loc),
4487 Parameter_Associations => New_List (
4488 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
4489 New_Reference_To (Ann, Loc)));
4491 if Parent (Stats) = N then
4492 Prepend (Call, Statements (Stats));
4493 else
4494 Set_Declarations
4495 (Parent (Stats),
4496 New_List (Call));
4497 end if;
4499 Analyze (Call);
4501 New_Scope (Blkent);
4503 declare
4504 D : Node_Id;
4505 Next_D : Node_Id;
4506 Typ : Entity_Id;
4507 begin
4508 D := First (Declarations (N));
4510 while Present (D) loop
4511 Next_D := Next (D);
4513 if Nkind (D) = N_Object_Renaming_Declaration then
4514 -- The renaming declarations for the formals were
4515 -- created during analysis of the accept statement,
4516 -- and attached to the list of declarations. Place
4517 -- them now in the context of the accept block or
4518 -- subprogram.
4520 Remove (D);
4521 Typ := Entity (Subtype_Mark (D));
4522 Insert_After (Call, D);
4523 Analyze (D);
4525 -- If the formal is class_wide, it does not have an
4526 -- actual subtype. The analysis of the renaming declaration
4527 -- creates one, but we need to retain the class-wide
4528 -- nature of the entity.
4530 if Is_Class_Wide_Type (Typ) then
4531 Set_Etype (Defining_Identifier (D), Typ);
4532 end if;
4534 end if;
4536 D := Next_D;
4537 end loop;
4538 end;
4540 End_Scope;
4542 -- Replace the accept statement by the new block
4544 Rewrite (N, Block);
4545 Analyze (N);
4547 -- Last step is to unstack the Accept_Address value
4549 Remove_Last_Elmt (Acstack);
4550 end if;
4551 end Expand_N_Accept_Statement;
4553 ----------------------------------
4554 -- Expand_N_Asynchronous_Select --
4555 ----------------------------------
4557 -- This procedure assumes that the trigger statement is an entry call or
4558 -- a dispatching procedure call. A delay alternative should already have
4559 -- been expanded into an entry call to the appropriate delay object Wait
4560 -- entry.
4562 -- If the trigger is a task entry call, the select is implemented with
4563 -- a Task_Entry_Call:
4565 -- declare
4566 -- B : Boolean;
4567 -- C : Boolean;
4568 -- P : parms := (parm, parm, parm);
4570 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
4572 -- procedure _clean is
4573 -- begin
4574 -- ...
4575 -- Cancel_Task_Entry_Call (C);
4576 -- ...
4577 -- end _clean;
4579 -- begin
4580 -- Abort_Defer;
4581 -- Task_Entry_Call
4582 -- (acceptor-task,
4583 -- entry-index,
4584 -- P'Address,
4585 -- Asynchronous_Call,
4586 -- B);
4588 -- begin
4589 -- begin
4590 -- Abort_Undefer;
4591 -- <abortable-part>
4592 -- at end
4593 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions.
4594 -- end;
4595 -- exception
4596 -- when Abort_Signal => Abort_Undefer;
4597 -- end;
4599 -- parm := P.param;
4600 -- parm := P.param;
4601 -- ...
4602 -- if not C then
4603 -- <triggered-statements>
4604 -- end if;
4605 -- end;
4607 -- Note that Build_Simple_Entry_Call is used to expand the entry
4608 -- of the asynchronous entry call (by the
4609 -- Expand_N_Entry_Call_Statement procedure) as follows:
4611 -- declare
4612 -- P : parms := (parm, parm, parm);
4613 -- begin
4614 -- Call_Simple (acceptor-task, entry-index, P'Address);
4615 -- parm := P.param;
4616 -- parm := P.param;
4617 -- ...
4618 -- end;
4620 -- so the task at hand is to convert the latter expansion into the former
4622 -- If the trigger is a protected entry call, the select is
4623 -- implemented with Protected_Entry_Call:
4625 -- declare
4626 -- P : E1_Params := (param, param, param);
4627 -- Bnn : Communications_Block;
4629 -- begin
4630 -- declare
4631 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions.
4632 -- procedure _clean is
4633 -- begin
4634 -- ...
4635 -- if Enqueued (Bnn) then
4636 -- Cancel_Protected_Entry_Call (Bnn);
4637 -- end if;
4638 -- ...
4639 -- end _clean;
4641 -- begin
4642 -- begin
4643 -- Protected_Entry_Call (
4644 -- Object => po._object'Access,
4645 -- E => <entry index>;
4646 -- Uninterpreted_Data => P'Address;
4647 -- Mode => Asynchronous_Call;
4648 -- Block => Bnn);
4649 -- if Enqueued (Bnn) then
4650 -- <abortable-part>
4651 -- end if;
4652 -- at end
4653 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions.
4654 -- end;
4655 -- exception
4656 -- when Abort_Signal => Abort_Undefer;
4657 -- end;
4659 -- if not Cancelled (Bnn) then
4660 -- <triggered-statements>
4661 -- end if;
4662 -- end;
4664 -- Build_Simple_Entry_Call is used to expand the all to a simple
4665 -- protected entry call:
4667 -- declare
4668 -- P : E1_Params := (param, param, param);
4669 -- Bnn : Communications_Block;
4671 -- begin
4672 -- Protected_Entry_Call (
4673 -- Object => po._object'Access,
4674 -- E => <entry index>;
4675 -- Uninterpreted_Data => P'Address;
4676 -- Mode => Simple_Call;
4677 -- Block => Bnn);
4678 -- parm := P.param;
4679 -- parm := P.param;
4680 -- ...
4681 -- end;
4683 -- Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
4684 -- expanded into:
4686 -- declare
4687 -- B : Boolean := False;
4688 -- Bnn : Communication_Block;
4689 -- C : Ada.Tags.Prim_Op_Kind;
4690 -- P : Parameters := (Param1 .. ParamN)
4691 -- S : constant Integer := DT_Position (<dispatching-call>);
4692 -- U : Boolean;
4694 -- procedure <temp>A is
4695 -- begin
4696 -- <abortable-statements>
4697 -- end <temp>A;
4699 -- procedure <temp>T is
4700 -- begin
4701 -- <triggered-statements>
4702 -- end <temp>T;
4704 -- begin
4705 -- disp_get_prim_op_kind (<object>, S, C);
4707 -- if C = POK_Protected_Entry then
4708 -- declare
4709 -- procedure _clean is
4710 -- begin
4711 -- if Enqueued (Bnn) then
4712 -- Cancel_Protected_Entry_Call (Bnn);
4713 -- end if;
4714 -- end _clean;
4716 -- begin
4717 -- begin
4718 -- disp_asynchronous_select
4719 -- (Obj, S, P'address, Bnn, B);
4721 -- Param1 := P.Param1;
4722 -- ...
4723 -- ParamN := P.ParamN;
4725 -- if Enqueued (Bnn) then
4726 -- <temp>A;
4727 -- end if;
4728 -- at end
4729 -- _clean;
4730 -- end;
4731 -- exception
4732 -- when Abort_Signal => Abort_Undefer;
4733 -- end;
4735 -- if not Cancelled (Bnn) then
4736 -- <temp>T;
4737 -- end if;
4739 -- elsif C = POK_Task_Entry then
4740 -- declare
4741 -- procedure _clean is
4742 -- begin
4743 -- Cancel_Task_Entry_Call (U);
4744 -- end _clean;
4746 -- begin
4747 -- Abort_Defer;
4749 -- disp_asynchronous_select
4750 -- (<object>, S, P'address, Bnn, B);
4752 -- Param1 := P.Param1;
4753 -- ...
4754 -- ParamN := P.ParamN;
4756 -- begin
4757 -- begin
4758 -- Abort_Undefer;
4759 -- <temp>A;
4760 -- at end
4761 -- _clean;
4762 -- end;
4763 -- exception
4764 -- when Abort_Signal => Abort_Undefer;
4765 -- end;
4767 -- if not U then
4768 -- <temp>T;
4769 -- end if;
4770 -- end;
4772 -- else
4773 -- <dispatching-call>;
4774 -- <temp>T;
4775 -- end if;
4777 -- The job is to convert this to the asynchronous form
4779 -- If the trigger is a delay statement, it will have been expanded into a
4780 -- call to one of the GNARL delay procedures. This routine will convert
4781 -- this into a protected entry call on a delay object and then continue
4782 -- processing as for a protected entry call trigger. This requires
4783 -- declaring a Delay_Block object and adding a pointer to this object to
4784 -- the parameter list of the delay procedure to form the parameter list of
4785 -- the entry call. This object is used by the runtime to queue the delay
4786 -- request.
4788 -- For a description of the use of P and the assignments after the
4789 -- call, see Expand_N_Entry_Call_Statement.
4791 procedure Expand_N_Asynchronous_Select (N : Node_Id) is
4792 Loc : constant Source_Ptr := Sloc (N);
4793 Abrt : constant Node_Id := Abortable_Part (N);
4794 Astats : constant List_Id := Statements (Abrt);
4795 Trig : constant Node_Id := Triggering_Alternative (N);
4796 Tstats : constant List_Id := Statements (Trig);
4798 Abortable_Block : Node_Id;
4799 Actuals : List_Id;
4800 Aproc : Entity_Id;
4801 Blk_Ent : Entity_Id;
4802 Blk_Typ : Entity_Id;
4803 Call : Node_Id;
4804 Call_Ent : Entity_Id;
4805 Cancel_Param : Entity_Id;
4806 Cleanup_Block : Node_Id;
4807 Cleanup_Stmts : List_Id;
4808 Concval : Node_Id;
4809 Dblock_Ent : Entity_Id;
4810 Decl : Node_Id;
4811 Decls : List_Id;
4812 Ecall : Node_Id;
4813 Ename : Node_Id;
4814 Enqueue_Call : Node_Id;
4815 Formals : List_Id;
4816 Hdle : List_Id;
4817 Index : Node_Id;
4818 N_Orig : Node_Id;
4819 Obj : Entity_Id;
4820 Param : Node_Id;
4821 Params : List_Id;
4822 Pdef : Entity_Id;
4823 ProtE_Stmts : List_Id;
4824 ProtP_Stmts : List_Id;
4825 Stmt : Node_Id;
4826 Stmts : List_Id;
4827 Target_Undefer : RE_Id;
4828 TaskE_Stmts : List_Id;
4829 Tproc : Entity_Id;
4830 Undefer_Args : List_Id := No_List;
4832 B : Entity_Id; -- Call status flag
4833 Bnn : Entity_Id; -- Communication block
4834 C : Entity_Id; -- Call kind
4835 P : Node_Id; -- Parameter block
4836 S : Entity_Id; -- Primitive operation slot
4837 U : Entity_Id; -- Additional status flag
4839 begin
4840 Blk_Ent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4841 Ecall := Triggering_Statement (Trig);
4843 -- The arguments in the call may require dynamic allocation, and the
4844 -- call statement may have been transformed into a block. The block
4845 -- may contain additional declarations for internal entities, and the
4846 -- original call is found by sequential search.
4848 if Nkind (Ecall) = N_Block_Statement then
4849 Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
4850 while Nkind (Ecall) /= N_Procedure_Call_Statement
4851 and then Nkind (Ecall) /= N_Entry_Call_Statement
4852 loop
4853 Next (Ecall);
4854 end loop;
4855 end if;
4857 -- This is either a dispatching call or a delay statement used as a
4858 -- trigger which was expanded into a procedure call.
4860 if Nkind (Ecall) = N_Procedure_Call_Statement then
4861 if Ada_Version >= Ada_05
4862 and then
4863 (not Present (Original_Node (Ecall))
4864 or else
4865 Nkind (Original_Node (Ecall)) /= N_Delay_Relative_Statement)
4866 then
4867 Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
4869 Decls := New_List;
4870 Stmts := New_List;
4872 -- Call status flag processing, generate:
4873 -- B : Boolean := False;
4875 B := SEU.Build_B (Loc, Decls);
4877 -- Communication block processing, generate:
4878 -- Bnn : Communication_Block;
4880 Bnn := Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
4882 Append_To (Decls,
4883 Make_Object_Declaration (Loc,
4884 Defining_Identifier =>
4885 Bnn,
4886 Object_Definition =>
4887 New_Reference_To (RTE (RE_Communication_Block), Loc)));
4889 -- Call kind processing, generate:
4890 -- C : Ada.Tags.Prim_Op_Kind;
4892 C := SEU.Build_C (Loc, Decls);
4894 -- Parameter block processing
4896 Blk_Typ := Build_Parameter_Block
4897 (Loc, Actuals, Formals, Decls);
4898 P := Parameter_Block_Pack
4899 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
4901 -- Dispatch table slot processing, generate:
4902 -- S : constant Integer :=
4903 -- DT_Position (<dispatching-procedure>);
4905 S := SEU.Build_S (Loc, Decls, Call_Ent);
4907 -- Additional status flag processing, generate:
4909 U := Make_Defining_Identifier (Loc, Name_uU);
4911 Append_To (Decls,
4912 Make_Object_Declaration (Loc,
4913 Defining_Identifier =>
4915 Object_Definition =>
4916 New_Reference_To (Standard_Boolean, Loc)));
4918 -- Generate:
4919 -- procedure <temp>A is
4920 -- begin
4921 -- Astmts
4922 -- end <temp>A;
4924 Aproc := SEU.Build_Wrapping_Procedure (Loc, 'A', Decls, Astats);
4926 -- Generate:
4927 -- procedure <temp>T is
4928 -- begin
4929 -- Tstmts
4930 -- end <temp>T;
4932 Tproc := SEU.Build_Wrapping_Procedure (Loc, 'T', Decls, Tstats);
4934 -- Generate:
4935 -- _dispatching_get_prim_op_kind (<object>, S, C);
4937 Append_To (Stmts,
4938 Make_Procedure_Call_Statement (Loc,
4939 Name =>
4940 Make_Identifier (Loc, Name_uDisp_Get_Prim_Op_Kind),
4941 Parameter_Associations =>
4942 New_List (
4943 New_Copy_Tree (Obj),
4944 New_Reference_To (S, Loc),
4945 New_Reference_To (C, Loc))));
4947 -- Protected entry handling
4949 -- Generate:
4950 -- Param1 := P.Param1;
4951 -- ...
4952 -- ParamN := P.ParamN;
4954 Cleanup_Stmts := Parameter_Block_Unpack (Loc, Actuals, Formals);
4956 -- Generate:
4957 -- _dispatching_asynchronous_select
4958 -- (<object>, S, P'address, Bnn, B);
4960 Prepend_To (Cleanup_Stmts,
4961 Make_Procedure_Call_Statement (Loc,
4962 Name =>
4963 Make_Identifier (Loc, Name_uDisp_Asynchronous_Select),
4964 Parameter_Associations =>
4965 New_List (
4966 New_Copy_Tree (Obj),
4967 New_Reference_To (S, Loc),
4969 New_Reference_To (Bnn, Loc),
4970 New_Reference_To (B, Loc))));
4972 -- Generate:
4973 -- if Enqueued (Bnn) then
4974 -- <temp>A
4975 -- end if;
4977 -- where <temp>A is the abort statements wrapping procedure
4979 Append_To (Cleanup_Stmts,
4980 Make_If_Statement (Loc,
4981 Condition =>
4982 Make_Function_Call (Loc,
4983 Name =>
4984 New_Reference_To (RTE (RE_Enqueued), Loc),
4985 Parameter_Associations =>
4986 New_List (
4987 New_Reference_To (Bnn, Loc))),
4989 Then_Statements =>
4990 New_List (
4991 Make_Procedure_Call_Statement (Loc,
4992 Name =>
4993 New_Reference_To (Aproc, Loc),
4994 Parameter_Associations =>
4995 No_List))));
4997 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
4998 -- will then generate a _clean for the communication block Bnn.
5000 -- Generate:
5001 -- declare
5002 -- procedure _clean is
5003 -- begin
5004 -- if Enqueued (Bnn) then
5005 -- Cancel_Protected_Entry_Call (Bnn);
5006 -- end if;
5007 -- end _clean;
5008 -- begin
5009 -- Cleanup_Stmts
5010 -- at end
5011 -- _clean;
5012 -- end;
5014 Cleanup_Block :=
5015 SEU.Build_Cleanup_Block (Loc, Blk_Ent, Cleanup_Stmts, Bnn);
5017 -- Wrap the cleanup block in an exception handling block.
5019 -- Generate:
5020 -- begin
5021 -- Cleanup_Block
5022 -- exception
5023 -- when Abort_Signal => Abort_Undefer;
5024 -- end;
5026 ProtE_Stmts :=
5027 New_List (
5028 SEU.Build_Abort_Block (Loc, Blk_Ent, Cleanup_Block));
5030 -- Generate:
5031 -- if not Cancelled (Bnn) then
5032 -- <temp>T
5033 -- end if;
5035 -- there <temp>T is the triggering statements wrapping procedure
5037 Append_To (ProtE_Stmts,
5038 Make_If_Statement (Loc,
5039 Condition =>
5040 Make_Op_Not (Loc,
5041 Right_Opnd =>
5042 Make_Function_Call (Loc,
5043 Name =>
5044 New_Reference_To (RTE (RE_Cancelled), Loc),
5045 Parameter_Associations =>
5046 New_List (
5047 New_Reference_To (Bnn, Loc)))),
5049 Then_Statements =>
5050 New_List (
5051 Make_Procedure_Call_Statement (Loc,
5052 Name =>
5053 New_Reference_To (Tproc, Loc),
5054 Parameter_Associations =>
5055 No_List))));
5057 -------------------------------------------------------------------
5058 -- Task entry handling
5060 -- Generate:
5061 -- Param1 := P.Param1;
5062 -- ...
5063 -- ParamN := P.ParamN;
5065 TaskE_Stmts := Parameter_Block_Unpack (Loc, Actuals, Formals);
5067 -- Generate:
5068 -- _dispatching_asynchronous_select
5069 -- (<object>, S, P'address, Bnn, B);
5071 Prepend_To (TaskE_Stmts,
5072 Make_Procedure_Call_Statement (Loc,
5073 Name =>
5074 Make_Identifier (Loc, Name_uDisp_Asynchronous_Select),
5075 Parameter_Associations =>
5076 New_List (
5077 New_Copy_Tree (Obj),
5078 New_Reference_To (S, Loc),
5079 New_Copy_Tree (P),
5080 New_Reference_To (Bnn, Loc),
5081 New_Reference_To (B, Loc))));
5083 -- Generate:
5084 -- Abort_Defer;
5086 Prepend_To (TaskE_Stmts,
5087 Make_Procedure_Call_Statement (Loc,
5088 Name =>
5089 New_Reference_To (RTE (RE_Abort_Defer), Loc),
5090 Parameter_Associations =>
5091 No_List));
5093 -- Generate:
5094 -- Abort_Undefer;
5095 -- <temp>A
5097 -- where <temp>A is the abortable statements wrapping procedure
5099 Cleanup_Stmts :=
5100 New_List (
5101 Make_Procedure_Call_Statement (Loc,
5102 Name =>
5103 New_Reference_To (RTE (RE_Abort_Undefer), Loc),
5104 Parameter_Associations =>
5105 No_List),
5107 Make_Procedure_Call_Statement (Loc,
5108 Name =>
5109 New_Reference_To (Aproc, Loc),
5110 Parameter_Associations =>
5111 No_List));
5113 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
5114 -- will generate a _clean for the additional status flag.
5116 -- Generate:
5117 -- declare
5118 -- procedure _clean is
5119 -- begin
5120 -- Cancel_Task_Entry_Call (U);
5121 -- end _clean;
5122 -- begin
5123 -- Cleanup_Stmts
5124 -- at end
5125 -- _clean;
5126 -- end;
5128 Blk_Ent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5130 Cleanup_Block :=
5131 SEU.Build_Cleanup_Block (Loc, Blk_Ent, Cleanup_Stmts, U);
5133 -- Wrap the cleanup block in an exception handling block
5135 -- Generate:
5136 -- begin
5137 -- Cleanup_Block
5138 -- exception
5139 -- when Abort_Signal => Abort_Undefer;
5140 -- end;
5142 Append_To (TaskE_Stmts,
5143 SEU.Build_Abort_Block (Loc, Blk_Ent, Cleanup_Block));
5145 -- Generate:
5146 -- if not U then
5147 -- <temp>T
5148 -- end if;
5150 -- where <temp>T is the triggering statements wrapping procedure
5152 Append_To (TaskE_Stmts,
5153 Make_If_Statement (Loc,
5154 Condition =>
5155 Make_Op_Not (Loc,
5156 Right_Opnd =>
5157 New_Reference_To (U, Loc)),
5158 Then_Statements =>
5159 New_List (
5160 Make_Procedure_Call_Statement (Loc,
5161 Name =>
5162 New_Reference_To (Tproc, Loc),
5163 Parameter_Associations =>
5164 No_List))));
5166 -------------------------------------------------------------------
5167 -- Protected procedure handling
5169 -- Generate:
5170 -- <dispatching-call>;
5171 -- <temp>T;
5173 -- where <temp>T is the triggering statements wrapping procedure
5175 ProtP_Stmts :=
5176 New_List (
5177 New_Copy_Tree (Ecall),
5179 Make_Procedure_Call_Statement (Loc,
5180 Name =>
5181 New_Reference_To (Tproc, Loc),
5182 Parameter_Associations =>
5183 No_List));
5185 -- Generate:
5186 -- if C = POK_Procedure_Entry then
5187 -- ProtE_Stmts
5188 -- elsif C = POK_Task_Entry then
5189 -- TaskE_Stmts
5190 -- else
5191 -- ProtP_Stmts
5192 -- end if;
5194 Append_To (Stmts,
5195 Make_If_Statement (Loc,
5196 Condition =>
5197 Make_Op_Eq (Loc,
5198 Left_Opnd =>
5199 New_Reference_To (C, Loc),
5200 Right_Opnd =>
5201 New_Reference_To (RTE (RE_POK_Protected_Entry), Loc)),
5203 Then_Statements =>
5204 ProtE_Stmts,
5206 Elsif_Parts =>
5207 New_List (
5208 Make_Elsif_Part (Loc,
5209 Condition =>
5210 Make_Op_Eq (Loc,
5211 Left_Opnd =>
5212 New_Reference_To (C, Loc),
5213 Right_Opnd =>
5214 New_Reference_To (RTE (RE_POK_Task_Entry), Loc)),
5215 Then_Statements =>
5216 TaskE_Stmts)),
5218 Else_Statements =>
5219 ProtP_Stmts));
5221 Rewrite (N,
5222 Make_Block_Statement (Loc,
5223 Declarations =>
5224 Decls,
5225 Handled_Statement_Sequence =>
5226 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5228 Analyze (N);
5229 return;
5231 -- Delay triggering statement processing
5233 else
5234 -- Add a Delay_Block object to the parameter list of the delay
5235 -- procedure to form the parameter list of the Wait entry call.
5237 Dblock_Ent :=
5238 Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
5240 Pdef := Entity (Name (Ecall));
5242 if Is_RTE (Pdef, RO_CA_Delay_For) then
5243 Enqueue_Call :=
5244 New_Reference_To (RTE (RE_Enqueue_Duration), Loc);
5246 elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
5247 Enqueue_Call :=
5248 New_Reference_To (RTE (RE_Enqueue_Calendar), Loc);
5250 else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
5251 Enqueue_Call := New_Reference_To (RTE (RE_Enqueue_RT), Loc);
5252 end if;
5254 Append_To (Parameter_Associations (Ecall),
5255 Make_Attribute_Reference (Loc,
5256 Prefix => New_Reference_To (Dblock_Ent, Loc),
5257 Attribute_Name => Name_Unchecked_Access));
5259 -- Create the inner block to protect the abortable part
5261 Hdle := New_List (
5262 Make_Exception_Handler (Loc,
5263 Exception_Choices =>
5264 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5265 Statements => New_List (
5266 Make_Procedure_Call_Statement (Loc,
5267 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
5269 Prepend_To (Astats,
5270 Make_Procedure_Call_Statement (Loc,
5271 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
5273 Abortable_Block :=
5274 Make_Block_Statement (Loc,
5275 Identifier => New_Reference_To (Blk_Ent, Loc),
5276 Handled_Statement_Sequence =>
5277 Make_Handled_Sequence_Of_Statements (Loc,
5278 Statements => Astats),
5279 Has_Created_Identifier => True,
5280 Is_Asynchronous_Call_Block => True);
5282 -- Append call to if Enqueue (When, DB'Unchecked_Access) then
5284 Rewrite (Ecall,
5285 Make_Implicit_If_Statement (N,
5286 Condition => Make_Function_Call (Loc,
5287 Name => Enqueue_Call,
5288 Parameter_Associations => Parameter_Associations (Ecall)),
5289 Then_Statements =>
5290 New_List (Make_Block_Statement (Loc,
5291 Handled_Statement_Sequence =>
5292 Make_Handled_Sequence_Of_Statements (Loc,
5293 Statements => New_List (
5294 Make_Implicit_Label_Declaration (Loc,
5295 Defining_Identifier => Blk_Ent,
5296 Label_Construct => Abortable_Block),
5297 Abortable_Block),
5298 Exception_Handlers => Hdle)))));
5300 Stmts := New_List (Ecall);
5302 -- Construct statement sequence for new block
5304 Append_To (Stmts,
5305 Make_Implicit_If_Statement (N,
5306 Condition => Make_Function_Call (Loc,
5307 Name => New_Reference_To (
5308 RTE (RE_Timed_Out), Loc),
5309 Parameter_Associations => New_List (
5310 Make_Attribute_Reference (Loc,
5311 Prefix => New_Reference_To (Dblock_Ent, Loc),
5312 Attribute_Name => Name_Unchecked_Access))),
5313 Then_Statements => Tstats));
5315 -- The result is the new block
5317 Set_Entry_Cancel_Parameter (Blk_Ent, Dblock_Ent);
5319 Rewrite (N,
5320 Make_Block_Statement (Loc,
5321 Declarations => New_List (
5322 Make_Object_Declaration (Loc,
5323 Defining_Identifier => Dblock_Ent,
5324 Aliased_Present => True,
5325 Object_Definition => New_Reference_To (
5326 RTE (RE_Delay_Block), Loc))),
5328 Handled_Statement_Sequence =>
5329 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5331 Analyze (N);
5332 return;
5333 end if;
5334 else
5335 N_Orig := N;
5336 end if;
5338 Extract_Entry (Ecall, Concval, Ename, Index);
5339 Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
5341 Stmts := Statements (Handled_Statement_Sequence (Ecall));
5342 Decls := Declarations (Ecall);
5344 if Is_Protected_Type (Etype (Concval)) then
5346 -- Get the declarations of the block expanded from the entry call
5348 Decl := First (Decls);
5349 while Present (Decl)
5350 and then
5351 (Nkind (Decl) /= N_Object_Declaration
5352 or else not Is_RTE (Etype (Object_Definition (Decl)),
5353 RE_Communication_Block))
5354 loop
5355 Next (Decl);
5356 end loop;
5358 pragma Assert (Present (Decl));
5359 Cancel_Param := Defining_Identifier (Decl);
5361 -- Change the mode of the Protected_Entry_Call call
5363 -- Protected_Entry_Call (
5364 -- Object => po._object'Access,
5365 -- E => <entry index>;
5366 -- Uninterpreted_Data => P'Address;
5367 -- Mode => Asynchronous_Call;
5368 -- Block => Bnn);
5370 Stmt := First (Stmts);
5372 -- Skip assignments to temporaries created for in-out parameters
5374 -- This makes unwarranted assumptions about the shape of the expanded
5375 -- tree for the call, and should be cleaned up ???
5377 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
5378 Next (Stmt);
5379 end loop;
5381 Call := Stmt;
5383 Param := First (Parameter_Associations (Call));
5384 while Present (Param)
5385 and then not Is_RTE (Etype (Param), RE_Call_Modes)
5386 loop
5387 Next (Param);
5388 end loop;
5390 pragma Assert (Present (Param));
5391 Rewrite (Param, New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
5392 Analyze (Param);
5394 -- Append an if statement to execute the abortable part
5396 -- Generate:
5397 -- if Enqueued (Bnn) then
5399 Append_To (Stmts,
5400 Make_Implicit_If_Statement (N,
5401 Condition => Make_Function_Call (Loc,
5402 Name => New_Reference_To (
5403 RTE (RE_Enqueued), Loc),
5404 Parameter_Associations => New_List (
5405 New_Reference_To (Cancel_Param, Loc))),
5406 Then_Statements => Astats));
5408 Abortable_Block :=
5409 Make_Block_Statement (Loc,
5410 Identifier => New_Reference_To (Blk_Ent, Loc),
5411 Handled_Statement_Sequence =>
5412 Make_Handled_Sequence_Of_Statements (Loc,
5413 Statements => Stmts),
5414 Has_Created_Identifier => True,
5415 Is_Asynchronous_Call_Block => True);
5417 -- For the JVM call Update_Exception instead of Abort_Undefer.
5418 -- See 4jexcept.ads for an explanation.
5420 if Hostparm.Java_VM then
5421 Target_Undefer := RE_Update_Exception;
5422 Undefer_Args :=
5423 New_List (Make_Function_Call (Loc,
5424 Name => New_Occurrence_Of
5425 (RTE (RE_Current_Target_Exception), Loc)));
5426 else
5427 Target_Undefer := RE_Abort_Undefer;
5428 end if;
5430 Stmts := New_List (
5431 Make_Block_Statement (Loc,
5432 Handled_Statement_Sequence =>
5433 Make_Handled_Sequence_Of_Statements (Loc,
5434 Statements => New_List (
5435 Make_Implicit_Label_Declaration (Loc,
5436 Defining_Identifier => Blk_Ent,
5437 Label_Construct => Abortable_Block),
5438 Abortable_Block),
5440 -- exception
5442 Exception_Handlers => New_List (
5443 Make_Exception_Handler (Loc,
5445 -- when Abort_Signal =>
5446 -- Abort_Undefer.all;
5448 Exception_Choices =>
5449 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5450 Statements => New_List (
5451 Make_Procedure_Call_Statement (Loc,
5452 Name => New_Reference_To (
5453 RTE (Target_Undefer), Loc),
5454 Parameter_Associations => Undefer_Args)))))),
5456 -- if not Cancelled (Bnn) then
5457 -- triggered statements
5458 -- end if;
5460 Make_Implicit_If_Statement (N,
5461 Condition => Make_Op_Not (Loc,
5462 Right_Opnd =>
5463 Make_Function_Call (Loc,
5464 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
5465 Parameter_Associations => New_List (
5466 New_Occurrence_Of (Cancel_Param, Loc)))),
5467 Then_Statements => Tstats));
5469 -- Asynchronous task entry call
5471 else
5472 if No (Decls) then
5473 Decls := New_List;
5474 end if;
5476 B := Make_Defining_Identifier (Loc, Name_uB);
5478 -- Insert declaration of B in declarations of existing block
5480 Prepend_To (Decls,
5481 Make_Object_Declaration (Loc,
5482 Defining_Identifier => B,
5483 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
5485 Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
5487 -- Insert declaration of C in declarations of existing block
5489 Prepend_To (Decls,
5490 Make_Object_Declaration (Loc,
5491 Defining_Identifier => Cancel_Param,
5492 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
5494 -- Remove and save the call to Call_Simple
5496 Stmt := First (Stmts);
5498 -- Skip assignments to temporaries created for in-out parameters.
5499 -- This makes unwarranted assumptions about the shape of the expanded
5500 -- tree for the call, and should be cleaned up ???
5502 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
5503 Next (Stmt);
5504 end loop;
5506 Call := Stmt;
5508 -- Create the inner block to protect the abortable part
5510 Hdle := New_List (
5511 Make_Exception_Handler (Loc,
5512 Exception_Choices =>
5513 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5514 Statements => New_List (
5515 Make_Procedure_Call_Statement (Loc,
5516 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
5518 Prepend_To (Astats,
5519 Make_Procedure_Call_Statement (Loc,
5520 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
5522 Abortable_Block :=
5523 Make_Block_Statement (Loc,
5524 Identifier => New_Reference_To (Blk_Ent, Loc),
5525 Handled_Statement_Sequence =>
5526 Make_Handled_Sequence_Of_Statements (Loc,
5527 Statements => Astats),
5528 Has_Created_Identifier => True,
5529 Is_Asynchronous_Call_Block => True);
5531 Insert_After (Call,
5532 Make_Block_Statement (Loc,
5533 Handled_Statement_Sequence =>
5534 Make_Handled_Sequence_Of_Statements (Loc,
5535 Statements => New_List (
5536 Make_Implicit_Label_Declaration (Loc,
5537 Defining_Identifier => Blk_Ent,
5538 Label_Construct => Abortable_Block),
5539 Abortable_Block),
5540 Exception_Handlers => Hdle)));
5542 -- Create new call statement
5544 Params := Parameter_Associations (Call);
5546 Append_To (Params,
5547 New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
5548 Append_To (Params,
5549 New_Reference_To (B, Loc));
5551 Rewrite (Call,
5552 Make_Procedure_Call_Statement (Loc,
5553 Name =>
5554 New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
5555 Parameter_Associations => Params));
5557 -- Construct statement sequence for new block
5559 Append_To (Stmts,
5560 Make_Implicit_If_Statement (N,
5561 Condition =>
5562 Make_Op_Not (Loc,
5563 New_Reference_To (Cancel_Param, Loc)),
5564 Then_Statements => Tstats));
5566 -- Protected the call against abort
5568 Prepend_To (Stmts,
5569 Make_Procedure_Call_Statement (Loc,
5570 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
5571 Parameter_Associations => Empty_List));
5572 end if;
5574 Set_Entry_Cancel_Parameter (Blk_Ent, Cancel_Param);
5576 -- The result is the new block
5578 Rewrite (N_Orig,
5579 Make_Block_Statement (Loc,
5580 Declarations => Decls,
5581 Handled_Statement_Sequence =>
5582 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5584 Analyze (N_Orig);
5585 end Expand_N_Asynchronous_Select;
5587 -------------------------------------
5588 -- Expand_N_Conditional_Entry_Call --
5589 -------------------------------------
5591 -- The conditional task entry call is converted to a call to
5592 -- Task_Entry_Call:
5594 -- declare
5595 -- B : Boolean;
5596 -- P : parms := (parm, parm, parm);
5598 -- begin
5599 -- Task_Entry_Call
5600 -- (acceptor-task,
5601 -- entry-index,
5602 -- P'Address,
5603 -- Conditional_Call,
5604 -- B);
5605 -- parm := P.param;
5606 -- parm := P.param;
5607 -- ...
5608 -- if B then
5609 -- normal-statements
5610 -- else
5611 -- else-statements
5612 -- end if;
5613 -- end;
5615 -- For a description of the use of P and the assignments after the
5616 -- call, see Expand_N_Entry_Call_Statement. Note that the entry call
5617 -- of the conditional entry call has already been expanded (by the
5618 -- Expand_N_Entry_Call_Statement procedure) as follows:
5620 -- declare
5621 -- P : parms := (parm, parm, parm);
5622 -- begin
5623 -- ... info for in-out parameters
5624 -- Call_Simple (acceptor-task, entry-index, P'Address);
5625 -- parm := P.param;
5626 -- parm := P.param;
5627 -- ...
5628 -- end;
5630 -- so the task at hand is to convert the latter expansion into the former
5632 -- The conditional protected entry call is converted to a call to
5633 -- Protected_Entry_Call:
5635 -- declare
5636 -- P : parms := (parm, parm, parm);
5637 -- Bnn : Communications_Block;
5639 -- begin
5640 -- Protected_Entry_Call (
5641 -- Object => po._object'Access,
5642 -- E => <entry index>;
5643 -- Uninterpreted_Data => P'Address;
5644 -- Mode => Conditional_Call;
5645 -- Block => Bnn);
5646 -- parm := P.param;
5647 -- parm := P.param;
5648 -- ...
5649 -- if Cancelled (Bnn) then
5650 -- else-statements
5651 -- else
5652 -- normal-statements
5653 -- end if;
5654 -- end;
5656 -- As for tasks, the entry call of the conditional entry call has
5657 -- already been expanded (by the Expand_N_Entry_Call_Statement procedure)
5658 -- as follows:
5660 -- declare
5661 -- P : E1_Params := (param, param, param);
5662 -- Bnn : Communications_Block;
5664 -- begin
5665 -- Protected_Entry_Call (
5666 -- Object => po._object'Access,
5667 -- E => <entry index>;
5668 -- Uninterpreted_Data => P'Address;
5669 -- Mode => Simple_Call;
5670 -- Block => Bnn);
5671 -- parm := P.param;
5672 -- parm := P.param;
5673 -- ...
5674 -- end;
5676 -- Ada 2005 (AI-345): A dispatching conditional entry call is converted
5677 -- into:
5679 -- declare
5680 -- B : Boolean := False;
5681 -- C : Ada.Tags.Prim_Op_Kind;
5682 -- P : Parameters := (Param1 .. ParamN);
5683 -- S : constant Integer := DT_Position (<dispatching-procedure>);
5685 -- begin
5686 -- disp_conditional_select (<object>, S, P'address, C, B);
5688 -- if C = POK_Protected_Entry
5689 -- or else C = POK_Task_Entry
5690 -- then
5691 -- Param1 := P.Param1;
5692 -- ...
5693 -- ParamN := P.ParamN;
5694 -- end if;
5696 -- if B then
5697 -- if C = POK_Procedure
5698 -- or else C = POK_Protected_Procedure
5699 -- or else C = POK_Task_Procedure
5700 -- then
5701 -- <dispatching-procedure> (<object>, Param1 .. ParamN);
5702 -- end if;
5703 -- <normal-statements>
5704 -- else
5705 -- <else-statements>
5706 -- end if;
5707 -- end;
5709 procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
5710 Loc : constant Source_Ptr := Sloc (N);
5711 Alt : constant Node_Id := Entry_Call_Alternative (N);
5712 Blk : Node_Id := Entry_Call_Statement (Alt);
5713 Transient_Blk : Node_Id;
5715 Actuals : List_Id;
5716 Blk_Typ : Entity_Id;
5717 Call : Node_Id;
5718 Call_Ent : Entity_Id;
5719 Decl : Node_Id;
5720 Decls : List_Id;
5721 Formals : List_Id;
5722 N_Stats : List_Id;
5723 Obj : Entity_Id;
5724 Param : Node_Id;
5725 Params : List_Id;
5726 Stmt : Node_Id;
5727 Stmts : List_Id;
5729 B : Entity_Id; -- Call status flag
5730 C : Entity_Id; -- Call kind
5731 P : Node_Id; -- Parameter block
5732 S : Entity_Id; -- Primitive operation slot
5734 begin
5735 if Ada_Version >= Ada_05
5736 and then Nkind (Blk) = N_Procedure_Call_Statement
5737 then
5738 Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
5740 Decls := New_List;
5741 Stmts := New_List;
5743 -- Call status flag processing, generate:
5744 -- B : Boolean := False;
5746 B := SEU.Build_B (Loc, Decls);
5748 -- Call kind processing, generate:
5749 -- C : Ada.Tags.Prim_Op_Kind;
5751 C := SEU.Build_C (Loc, Decls);
5753 -- Parameter block processing
5755 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
5756 P := Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals,
5757 Decls, Stmts);
5759 -- Dispatch table slot processing, generate:
5760 -- S : constant Integer :=
5761 -- DT_Position (<dispatching-procedure>);
5763 S := SEU.Build_S (Loc, Decls, Call_Ent);
5765 -- Generate:
5766 -- _dispatching_conditional_select (<object>, S, P'address, C, B);
5768 Append_To (Stmts,
5769 Make_Procedure_Call_Statement (Loc,
5770 Name =>
5771 Make_Identifier (Loc, Name_uDisp_Conditional_Select),
5772 Parameter_Associations =>
5773 New_List (
5774 New_Copy_Tree (Obj),
5775 New_Reference_To (S, Loc),
5777 New_Reference_To (C, Loc),
5778 New_Reference_To (B, Loc))));
5780 -- Generate:
5781 -- if C = POK_Protected_Entry
5782 -- or else C = POK_Task_Entry
5783 -- then
5784 -- Param1 := P.Param1;
5785 -- ...
5786 -- ParamN := P.ParamN;
5787 -- end if;
5789 Append_To (Stmts,
5790 Make_If_Statement (Loc,
5792 Condition =>
5793 Make_Or_Else (Loc,
5794 Left_Opnd =>
5795 Make_Op_Eq (Loc,
5796 Left_Opnd =>
5797 New_Reference_To (C, Loc),
5798 Right_Opnd =>
5799 New_Reference_To (RTE (RE_POK_Protected_Entry), Loc)),
5800 Right_Opnd =>
5801 Make_Op_Eq (Loc,
5802 Left_Opnd =>
5803 New_Reference_To (C, Loc),
5804 Right_Opnd =>
5805 New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
5807 Then_Statements =>
5808 Parameter_Block_Unpack (Loc, Actuals, Formals)));
5810 -- Generate:
5811 -- if B then
5812 -- if C = POK_Procedure
5813 -- or else C = POK_Protected_Procedure
5814 -- or else C = POK_Task_Procedure
5815 -- then
5816 -- <dispatching-procedure-call>
5817 -- end if;
5818 -- <normal-statements>
5819 -- else
5820 -- <else-statements>
5821 -- end if;
5823 N_Stats := New_Copy_List (Statements (Alt));
5825 Prepend_To (N_Stats,
5826 Make_If_Statement (Loc,
5827 Condition =>
5828 Make_Or_Else (Loc,
5829 Left_Opnd =>
5830 Make_Op_Eq (Loc,
5831 Left_Opnd =>
5832 New_Reference_To (C, Loc),
5833 Right_Opnd =>
5834 New_Reference_To (RTE (RE_POK_Procedure), Loc)),
5836 Right_Opnd =>
5837 Make_Or_Else (Loc,
5838 Left_Opnd =>
5839 Make_Op_Eq (Loc,
5840 Left_Opnd =>
5841 New_Reference_To (C, Loc),
5842 Right_Opnd =>
5843 New_Reference_To (RTE (
5844 RE_POK_Protected_Procedure), Loc)),
5846 Right_Opnd =>
5847 Make_Op_Eq (Loc,
5848 Left_Opnd =>
5849 New_Reference_To (C, Loc),
5850 Right_Opnd =>
5851 New_Reference_To (RTE (
5852 RE_POK_Task_Procedure), Loc)))),
5854 Then_Statements =>
5855 New_List (Blk)));
5857 Append_To (Stmts,
5858 Make_If_Statement (Loc,
5859 Condition => New_Reference_To (B, Loc),
5860 Then_Statements => N_Stats,
5861 Else_Statements => Else_Statements (N)));
5863 Rewrite (N,
5864 Make_Block_Statement (Loc,
5865 Declarations => Decls,
5866 Handled_Statement_Sequence =>
5867 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5869 -- As described above, The entry alternative is transformed into a
5870 -- block that contains the gnulli call, and possibly assignment
5871 -- statements for in-out parameters. The gnulli call may itself be
5872 -- rewritten into a transient block if some unconstrained parameters
5873 -- require it. We need to retrieve the call to complete its parameter
5874 -- list.
5876 else
5877 Transient_Blk :=
5878 First_Real_Statement (Handled_Statement_Sequence (Blk));
5880 if Present (Transient_Blk)
5881 and then Nkind (Transient_Blk) = N_Block_Statement
5882 then
5883 Blk := Transient_Blk;
5884 end if;
5886 Stmts := Statements (Handled_Statement_Sequence (Blk));
5887 Stmt := First (Stmts);
5888 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
5889 Next (Stmt);
5890 end loop;
5892 Call := Stmt;
5893 Params := Parameter_Associations (Call);
5895 if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
5897 -- Substitute Conditional_Entry_Call for Simple_Call parameter
5899 Param := First (Params);
5900 while Present (Param)
5901 and then not Is_RTE (Etype (Param), RE_Call_Modes)
5902 loop
5903 Next (Param);
5904 end loop;
5906 pragma Assert (Present (Param));
5907 Rewrite (Param, New_Reference_To (RTE (RE_Conditional_Call), Loc));
5909 Analyze (Param);
5911 -- Find the Communication_Block parameter for the call to the
5912 -- Cancelled function.
5914 Decl := First (Declarations (Blk));
5915 while Present (Decl)
5916 and then not Is_RTE (Etype (Object_Definition (Decl)),
5917 RE_Communication_Block)
5918 loop
5919 Next (Decl);
5920 end loop;
5922 -- Add an if statement to execute the else part if the call
5923 -- does not succeed (as indicated by the Cancelled predicate).
5925 Append_To (Stmts,
5926 Make_Implicit_If_Statement (N,
5927 Condition => Make_Function_Call (Loc,
5928 Name => New_Reference_To (RTE (RE_Cancelled), Loc),
5929 Parameter_Associations => New_List (
5930 New_Reference_To (Defining_Identifier (Decl), Loc))),
5931 Then_Statements => Else_Statements (N),
5932 Else_Statements => Statements (Alt)));
5934 else
5935 B := Make_Defining_Identifier (Loc, Name_uB);
5937 -- Insert declaration of B in declarations of existing block
5939 if No (Declarations (Blk)) then
5940 Set_Declarations (Blk, New_List);
5941 end if;
5943 Prepend_To (Declarations (Blk),
5944 Make_Object_Declaration (Loc,
5945 Defining_Identifier => B,
5946 Object_Definition =>
5947 New_Reference_To (Standard_Boolean, Loc)));
5949 -- Create new call statement
5951 Append_To (Params,
5952 New_Reference_To (RTE (RE_Conditional_Call), Loc));
5953 Append_To (Params, New_Reference_To (B, Loc));
5955 Rewrite (Call,
5956 Make_Procedure_Call_Statement (Loc,
5957 Name => New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
5958 Parameter_Associations => Params));
5960 -- Construct statement sequence for new block
5962 Append_To (Stmts,
5963 Make_Implicit_If_Statement (N,
5964 Condition => New_Reference_To (B, Loc),
5965 Then_Statements => Statements (Alt),
5966 Else_Statements => Else_Statements (N)));
5967 end if;
5969 -- The result is the new block
5971 Rewrite (N,
5972 Make_Block_Statement (Loc,
5973 Declarations => Declarations (Blk),
5974 Handled_Statement_Sequence =>
5975 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5976 end if;
5978 Analyze (N);
5979 end Expand_N_Conditional_Entry_Call;
5981 ---------------------------------------
5982 -- Expand_N_Delay_Relative_Statement --
5983 ---------------------------------------
5985 -- Delay statement is implemented as a procedure call to Delay_For
5986 -- defined in Ada.Calendar.Delays in order to reduce the overhead of
5987 -- simple delays imposed by the use of Protected Objects.
5989 procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
5990 Loc : constant Source_Ptr := Sloc (N);
5991 begin
5992 Rewrite (N,
5993 Make_Procedure_Call_Statement (Loc,
5994 Name => New_Reference_To (RTE (RO_CA_Delay_For), Loc),
5995 Parameter_Associations => New_List (Expression (N))));
5996 Analyze (N);
5997 end Expand_N_Delay_Relative_Statement;
5999 ------------------------------------
6000 -- Expand_N_Delay_Until_Statement --
6001 ------------------------------------
6003 -- Delay Until statement is implemented as a procedure call to
6004 -- Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
6006 procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
6007 Loc : constant Source_Ptr := Sloc (N);
6008 Typ : Entity_Id;
6010 begin
6011 if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
6012 Typ := RTE (RO_CA_Delay_Until);
6013 else
6014 Typ := RTE (RO_RT_Delay_Until);
6015 end if;
6017 Rewrite (N,
6018 Make_Procedure_Call_Statement (Loc,
6019 Name => New_Reference_To (Typ, Loc),
6020 Parameter_Associations => New_List (Expression (N))));
6022 Analyze (N);
6023 end Expand_N_Delay_Until_Statement;
6025 -------------------------
6026 -- Expand_N_Entry_Body --
6027 -------------------------
6029 procedure Expand_N_Entry_Body (N : Node_Id) is
6030 Loc : constant Source_Ptr := Sloc (N);
6031 Dec : constant Node_Id := Parent (Current_Scope);
6032 Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
6033 Index_Spec : constant Node_Id :=
6034 Entry_Index_Specification (Ent_Formals);
6035 Next_Op : Node_Id;
6036 First_Decl : constant Node_Id := First (Declarations (N));
6037 Index_Decl : List_Id;
6039 begin
6040 -- Add the renamings for private declarations and discriminants
6042 Add_Discriminal_Declarations
6043 (Declarations (N), Defining_Identifier (Dec), Name_uObject, Loc);
6044 Add_Private_Declarations
6045 (Declarations (N), Defining_Identifier (Dec), Name_uObject, Loc);
6047 if Present (Index_Spec) then
6048 Index_Decl :=
6049 Index_Constant_Declaration
6051 Defining_Identifier (Index_Spec), Defining_Identifier (Dec));
6053 -- If the entry has local declarations, insert index declaration
6054 -- before them, because the index may be used therein.
6056 if Present (First_Decl) then
6057 Insert_List_Before (First_Decl, Index_Decl);
6058 else
6059 Append_List_To (Declarations (N), Index_Decl);
6060 end if;
6061 end if;
6063 -- Associate privals and discriminals with the next protected
6064 -- operation body to be expanded. These are used to expand
6065 -- references to private data objects and discriminants,
6066 -- respectively.
6068 Next_Op := Next_Protected_Operation (N);
6070 if Present (Next_Op) then
6071 Set_Privals (Dec, Next_Op, Loc);
6072 Set_Discriminals (Dec);
6073 end if;
6074 end Expand_N_Entry_Body;
6076 -----------------------------------
6077 -- Expand_N_Entry_Call_Statement --
6078 -----------------------------------
6080 -- An entry call is expanded into GNARLI calls to implement
6081 -- a simple entry call (see Build_Simple_Entry_Call).
6083 procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
6084 Concval : Node_Id;
6085 Ename : Node_Id;
6086 Index : Node_Id;
6088 begin
6089 if No_Run_Time_Mode then
6090 Error_Msg_CRT ("entry call", N);
6091 return;
6092 end if;
6094 -- If this entry call is part of an asynchronous select, don't
6095 -- expand it here; it will be expanded with the select statement.
6096 -- Don't expand timed entry calls either, as they are translated
6097 -- into asynchronous entry calls.
6099 -- ??? This whole approach is questionable; it may be better
6100 -- to go back to allowing the expansion to take place and then
6101 -- attempting to fix it up in Expand_N_Asynchronous_Select.
6102 -- The tricky part is figuring out whether the expanded
6103 -- call is on a task or protected entry.
6105 if (Nkind (Parent (N)) /= N_Triggering_Alternative
6106 or else N /= Triggering_Statement (Parent (N)))
6107 and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
6108 or else N /= Entry_Call_Statement (Parent (N))
6109 or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
6110 then
6111 Extract_Entry (N, Concval, Ename, Index);
6112 Build_Simple_Entry_Call (N, Concval, Ename, Index);
6113 end if;
6114 end Expand_N_Entry_Call_Statement;
6116 --------------------------------
6117 -- Expand_N_Entry_Declaration --
6118 --------------------------------
6120 -- If there are parameters, then first, each of the formals is marked
6121 -- by setting Is_Entry_Formal. Next a record type is built which is
6122 -- used to hold the parameter values. The name of this record type is
6123 -- entryP where entry is the name of the entry, with an additional
6124 -- corresponding access type called entryPA. The record type has matching
6125 -- components for each formal (the component names are the same as the
6126 -- formal names). For elementary types, the component type matches the
6127 -- formal type. For composite types, an access type is declared (with
6128 -- the name formalA) which designates the formal type, and the type of
6129 -- the component is this access type. Finally the Entry_Component of
6130 -- each formal is set to reference the corresponding record component.
6132 procedure Expand_N_Entry_Declaration (N : Node_Id) is
6133 Loc : constant Source_Ptr := Sloc (N);
6134 Entry_Ent : constant Entity_Id := Defining_Identifier (N);
6135 Components : List_Id;
6136 Formal : Node_Id;
6137 Ftype : Entity_Id;
6138 Last_Decl : Node_Id;
6139 Component : Entity_Id;
6140 Ctype : Entity_Id;
6141 Decl : Node_Id;
6142 Rec_Ent : Entity_Id;
6143 Acc_Ent : Entity_Id;
6145 begin
6146 Formal := First_Formal (Entry_Ent);
6147 Last_Decl := N;
6149 -- Most processing is done only if parameters are present
6151 if Present (Formal) then
6152 Components := New_List;
6154 -- Loop through formals
6156 while Present (Formal) loop
6157 Set_Is_Entry_Formal (Formal);
6158 Component :=
6159 Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
6160 Set_Entry_Component (Formal, Component);
6161 Set_Entry_Formal (Component, Formal);
6162 Ftype := Etype (Formal);
6164 -- Declare new access type and then append
6166 Ctype :=
6167 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
6169 Decl :=
6170 Make_Full_Type_Declaration (Loc,
6171 Defining_Identifier => Ctype,
6172 Type_Definition =>
6173 Make_Access_To_Object_Definition (Loc,
6174 All_Present => True,
6175 Constant_Present => Ekind (Formal) = E_In_Parameter,
6176 Subtype_Indication => New_Reference_To (Ftype, Loc)));
6178 Insert_After (Last_Decl, Decl);
6179 Last_Decl := Decl;
6181 Append_To (Components,
6182 Make_Component_Declaration (Loc,
6183 Defining_Identifier => Component,
6184 Component_Definition =>
6185 Make_Component_Definition (Loc,
6186 Aliased_Present => False,
6187 Subtype_Indication => New_Reference_To (Ctype, Loc))));
6189 Next_Formal_With_Extras (Formal);
6190 end loop;
6192 -- Create the Entry_Parameter_Record declaration
6194 Rec_Ent :=
6195 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
6197 Decl :=
6198 Make_Full_Type_Declaration (Loc,
6199 Defining_Identifier => Rec_Ent,
6200 Type_Definition =>
6201 Make_Record_Definition (Loc,
6202 Component_List =>
6203 Make_Component_List (Loc,
6204 Component_Items => Components)));
6206 Insert_After (Last_Decl, Decl);
6207 Last_Decl := Decl;
6209 -- Construct and link in the corresponding access type
6211 Acc_Ent :=
6212 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
6214 Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
6216 Decl :=
6217 Make_Full_Type_Declaration (Loc,
6218 Defining_Identifier => Acc_Ent,
6219 Type_Definition =>
6220 Make_Access_To_Object_Definition (Loc,
6221 All_Present => True,
6222 Subtype_Indication => New_Reference_To (Rec_Ent, Loc)));
6224 Insert_After (Last_Decl, Decl);
6225 Last_Decl := Decl;
6226 end if;
6227 end Expand_N_Entry_Declaration;
6229 -----------------------------
6230 -- Expand_N_Protected_Body --
6231 -----------------------------
6233 -- Protected bodies are expanded to the completion of the subprograms
6234 -- created for the corresponding protected type. These are a protected
6235 -- and unprotected version of each protected subprogram in the object,
6236 -- a function to calculate each entry barrier, and a procedure to
6237 -- execute the sequence of statements of each protected entry body.
6238 -- For example, for protected type ptype:
6240 -- function entB
6241 -- (O : System.Address;
6242 -- E : Protected_Entry_Index)
6243 -- return Boolean
6244 -- is
6245 -- <discriminant renamings>
6246 -- <private object renamings>
6247 -- begin
6248 -- return <barrier expression>;
6249 -- end entB;
6251 -- procedure pprocN (_object : in out poV;...) is
6252 -- <discriminant renamings>
6253 -- <private object renamings>
6254 -- begin
6255 -- <sequence of statements>
6256 -- end pprocN;
6258 -- procedure pprocP (_object : in out poV;...) is
6259 -- procedure _clean is
6260 -- Pn : Boolean;
6261 -- begin
6262 -- ptypeS (_object, Pn);
6263 -- Unlock (_object._object'Access);
6264 -- Abort_Undefer.all;
6265 -- end _clean;
6267 -- begin
6268 -- Abort_Defer.all;
6269 -- Lock (_object._object'Access);
6270 -- pprocN (_object;...);
6271 -- at end
6272 -- _clean;
6273 -- end pproc;
6275 -- function pfuncN (_object : poV;...) return Return_Type is
6276 -- <discriminant renamings>
6277 -- <private object renamings>
6278 -- begin
6279 -- <sequence of statements>
6280 -- end pfuncN;
6282 -- function pfuncP (_object : poV) return Return_Type is
6283 -- procedure _clean is
6284 -- begin
6285 -- Unlock (_object._object'Access);
6286 -- Abort_Undefer.all;
6287 -- end _clean;
6289 -- begin
6290 -- Abort_Defer.all;
6291 -- Lock (_object._object'Access);
6292 -- return pfuncN (_object);
6294 -- at end
6295 -- _clean;
6296 -- end pfunc;
6298 -- procedure entE
6299 -- (O : System.Address;
6300 -- P : System.Address;
6301 -- E : Protected_Entry_Index)
6302 -- is
6303 -- <discriminant renamings>
6304 -- <private object renamings>
6305 -- type poVP is access poV;
6306 -- _Object : ptVP := ptVP!(O);
6308 -- begin
6309 -- begin
6310 -- <statement sequence>
6311 -- Complete_Entry_Body (_Object._Object);
6312 -- exception
6313 -- when all others =>
6314 -- Exceptional_Complete_Entry_Body (
6315 -- _Object._Object, Get_GNAT_Exception);
6316 -- end;
6317 -- end entE;
6319 -- The type poV is the record created for the protected type to hold
6320 -- the state of the protected object.
6322 procedure Expand_N_Protected_Body (N : Node_Id) is
6323 Loc : constant Source_Ptr := Sloc (N);
6324 Pid : constant Entity_Id := Corresponding_Spec (N);
6325 Has_Entries : Boolean := False;
6326 Op_Decl : Node_Id;
6327 Op_Body : Node_Id;
6328 Op_Id : Entity_Id;
6329 Disp_Op_Body : Node_Id;
6330 New_Op_Body : Node_Id;
6331 Current_Node : Node_Id;
6332 Num_Entries : Natural := 0;
6334 function Build_Dispatching_Subprogram_Body
6335 (N : Node_Id;
6336 Pid : Node_Id;
6337 Prot_Bod : Node_Id) return Node_Id;
6338 -- Build a dispatching version of the protected subprogram body. The
6339 -- newly generated subprogram contains a call to the original protected
6340 -- body. The following code is generated:
6342 -- function <protected-function-name> (Param1 .. ParamN) return
6343 -- <return-type> is
6344 -- begin
6345 -- return <protected-function-name>P (Param1 .. ParamN);
6346 -- end <protected-function-name>;
6348 -- or
6350 -- procedure <protected-procedure-name> (Param1 .. ParamN) is
6351 -- begin
6352 -- <protected-procedure-name>P (Param1 .. ParamN);
6353 -- end <protected-procedure-name>
6355 ---------------------------------------
6356 -- Build_Dispatching_Subprogram_Body --
6357 ---------------------------------------
6359 function Build_Dispatching_Subprogram_Body
6360 (N : Node_Id;
6361 Pid : Node_Id;
6362 Prot_Bod : Node_Id) return Node_Id
6364 Loc : constant Source_Ptr := Sloc (N);
6365 Actuals : List_Id;
6366 Formal : Node_Id;
6367 Spec : Node_Id;
6368 Stmts : List_Id;
6370 begin
6371 -- Generate a specification without a letter suffix in order to
6372 -- override an interface function or procedure.
6374 Spec :=
6375 Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
6377 -- The formal parameters become the actuals of the protected
6378 -- function or procedure call.
6380 Actuals := New_List;
6381 Formal := First (Parameter_Specifications (Spec));
6383 while Present (Formal) loop
6384 Append_To (Actuals,
6385 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
6387 Next (Formal);
6388 end loop;
6390 if Nkind (Spec) = N_Procedure_Specification then
6391 Stmts :=
6392 New_List (
6393 Make_Procedure_Call_Statement (Loc,
6394 Name =>
6395 New_Reference_To (Corresponding_Spec (Prot_Bod), Loc),
6396 Parameter_Associations => Actuals));
6397 else
6398 pragma Assert (Nkind (Spec) = N_Function_Specification);
6400 Stmts :=
6401 New_List (
6402 Make_Return_Statement (Loc,
6403 Expression =>
6404 Make_Function_Call (Loc,
6405 Name =>
6406 New_Reference_To (Corresponding_Spec (Prot_Bod), Loc),
6407 Parameter_Associations => Actuals)));
6408 end if;
6410 return
6411 Make_Subprogram_Body (Loc,
6412 Declarations => Empty_List,
6413 Specification => Spec,
6414 Handled_Statement_Sequence =>
6415 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6416 end Build_Dispatching_Subprogram_Body;
6418 -- Start of processing for Expand_N_Protected_Body
6420 begin
6421 if No_Run_Time_Mode then
6422 Error_Msg_CRT ("protected body", N);
6423 return;
6424 end if;
6426 if Nkind (Parent (N)) = N_Subunit then
6428 -- This is the proper body corresponding to a stub. The declarations
6429 -- must be inserted at the point of the stub, which is in the decla-
6430 -- rative part of the parent unit.
6432 Current_Node := Corresponding_Stub (Parent (N));
6434 else
6435 Current_Node := N;
6436 end if;
6438 Op_Body := First (Declarations (N));
6440 -- The protected body is replaced with the bodies of its
6441 -- protected operations, and the declarations for internal objects
6442 -- that may have been created for entry family bounds.
6444 Rewrite (N, Make_Null_Statement (Sloc (N)));
6445 Analyze (N);
6447 while Present (Op_Body) loop
6448 case Nkind (Op_Body) is
6449 when N_Subprogram_Declaration =>
6450 null;
6452 when N_Subprogram_Body =>
6454 -- Exclude functions created to analyze defaults
6456 if not Is_Eliminated (Defining_Entity (Op_Body))
6457 and then not Is_Eliminated (Corresponding_Spec (Op_Body))
6458 then
6459 New_Op_Body :=
6460 Build_Unprotected_Subprogram_Body (Op_Body, Pid);
6462 Insert_After (Current_Node, New_Op_Body);
6463 Current_Node := New_Op_Body;
6464 Analyze (New_Op_Body);
6466 Update_Prival_Subtypes (New_Op_Body);
6468 -- Build the corresponding protected operation only if
6469 -- this is a visible operation of the type, or if it is
6470 -- an interrupt handler. Otherwise it is only callable
6471 -- from within the object, and the unprotected version
6472 -- is sufficient.
6474 if Present (Corresponding_Spec (Op_Body)) then
6475 Op_Decl :=
6476 Unit_Declaration_Node (Corresponding_Spec (Op_Body));
6478 if Nkind (Parent (Op_Decl)) = N_Protected_Definition
6479 and then
6480 (List_Containing (Op_Decl) =
6481 Visible_Declarations (Parent (Op_Decl))
6482 or else
6483 Is_Interrupt_Handler
6484 (Corresponding_Spec (Op_Body)))
6485 then
6486 New_Op_Body :=
6487 Build_Protected_Subprogram_Body (
6488 Op_Body, Pid, Specification (New_Op_Body));
6490 Insert_After (Current_Node, New_Op_Body);
6491 Analyze (New_Op_Body);
6493 Current_Node := New_Op_Body;
6495 -- Generate an overriding primitive operation body for
6496 -- this subprogram if the protected type implements
6497 -- an inerface.
6499 if Ada_Version >= Ada_05
6500 and then Present (Abstract_Interfaces (
6501 Corresponding_Record_Type (Pid)))
6502 then
6503 Disp_Op_Body :=
6504 Build_Dispatching_Subprogram_Body (
6505 Op_Body, Pid, New_Op_Body);
6507 Insert_After (Current_Node, Disp_Op_Body);
6508 Analyze (Disp_Op_Body);
6510 Current_Node := Disp_Op_Body;
6511 end if;
6512 end if;
6513 end if;
6514 end if;
6516 when N_Entry_Body =>
6517 Op_Id := Defining_Identifier (Op_Body);
6518 Has_Entries := True;
6519 Num_Entries := Num_Entries + 1;
6521 New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
6523 Insert_After (Current_Node, New_Op_Body);
6524 Current_Node := New_Op_Body;
6525 Analyze (New_Op_Body);
6527 Update_Prival_Subtypes (New_Op_Body);
6529 when N_Implicit_Label_Declaration =>
6530 null;
6532 when N_Itype_Reference =>
6533 Insert_After (Current_Node, New_Copy (Op_Body));
6535 when N_Freeze_Entity =>
6536 New_Op_Body := New_Copy (Op_Body);
6538 if Present (Entity (Op_Body))
6539 and then Freeze_Node (Entity (Op_Body)) = Op_Body
6540 then
6541 Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
6542 end if;
6544 Insert_After (Current_Node, New_Op_Body);
6545 Current_Node := New_Op_Body;
6546 Analyze (New_Op_Body);
6548 when N_Pragma =>
6549 New_Op_Body := New_Copy (Op_Body);
6550 Insert_After (Current_Node, New_Op_Body);
6551 Current_Node := New_Op_Body;
6552 Analyze (New_Op_Body);
6554 when N_Object_Declaration =>
6555 pragma Assert (not Comes_From_Source (Op_Body));
6556 New_Op_Body := New_Copy (Op_Body);
6557 Insert_After (Current_Node, New_Op_Body);
6558 Current_Node := New_Op_Body;
6559 Analyze (New_Op_Body);
6561 when others =>
6562 raise Program_Error;
6564 end case;
6566 Next (Op_Body);
6567 end loop;
6569 -- Finally, create the body of the function that maps an entry index
6570 -- into the corresponding body index, except when there is no entry,
6571 -- or in a ravenscar-like profile (no abort, no entry queue, 1 entry)
6573 if Has_Entries
6574 and then (Abort_Allowed
6575 or else Restriction_Active (No_Entry_Queue) = False
6576 or else Num_Entries > 1)
6577 then
6578 New_Op_Body := Build_Find_Body_Index (Pid);
6579 Insert_After (Current_Node, New_Op_Body);
6580 Current_Node := New_Op_Body;
6581 Analyze (New_Op_Body);
6582 end if;
6584 -- Ada 2005 (AI-345): Construct the primitive entry wrapper bodies
6585 -- after the protected body. At this point the entry specs have been
6586 -- created, frozen and included in the dispatch table for the
6587 -- protected type.
6589 pragma Assert (Present (Corresponding_Record_Type (Pid)));
6591 if Ada_Version >= Ada_05
6592 and then Present (Protected_Definition (Parent (Pid)))
6593 and then Present (Abstract_Interfaces
6594 (Corresponding_Record_Type (Pid)))
6595 then
6596 declare
6597 Vis_Decl : Node_Id :=
6598 First (Visible_Declarations
6599 (Protected_Definition (Parent (Pid))));
6600 Wrap_Body : Node_Id;
6602 begin
6603 -- Examine the visible declarations of the protected type,
6604 -- looking for an entry declaration. We do not consider
6605 -- entry families since they can not have dispatching
6606 -- operations, thus they do not need entry wrappers.
6608 while Present (Vis_Decl) loop
6609 if Nkind (Vis_Decl) = N_Entry_Declaration then
6610 Wrap_Body :=
6611 Build_Wrapper_Body (Loc,
6612 Proc_Nam => Defining_Identifier (Vis_Decl),
6613 Obj_Typ => Corresponding_Record_Type (Pid),
6614 Formals => Parameter_Specifications (Vis_Decl));
6616 if Wrap_Body /= Empty then
6617 Insert_After (Current_Node, Wrap_Body);
6618 Current_Node := Wrap_Body;
6620 Analyze (Wrap_Body);
6621 end if;
6623 elsif Nkind (Vis_Decl) = N_Subprogram_Declaration then
6624 Wrap_Body :=
6625 Build_Wrapper_Body (Loc,
6626 Proc_Nam => Defining_Unit_Name
6627 (Specification (Vis_Decl)),
6628 Obj_Typ => Corresponding_Record_Type (Pid),
6629 Formals => Parameter_Specifications
6630 (Specification (Vis_Decl)));
6632 if Wrap_Body /= Empty then
6633 Insert_After (Current_Node, Wrap_Body);
6634 Current_Node := Wrap_Body;
6636 Analyze (Wrap_Body);
6637 end if;
6638 end if;
6640 Next (Vis_Decl);
6641 end loop;
6642 end;
6643 end if;
6644 end Expand_N_Protected_Body;
6646 -----------------------------------------
6647 -- Expand_N_Protected_Type_Declaration --
6648 -----------------------------------------
6650 -- First we create a corresponding record type declaration used to
6651 -- represent values of this protected type.
6652 -- The general form of this type declaration is
6654 -- type poV (discriminants) is record
6655 -- _Object : aliased <kind>Protection
6656 -- [(<entry count> [, <handler count>])];
6657 -- [entry_family : array (bounds) of Void;]
6658 -- <private data fields>
6659 -- end record;
6661 -- The discriminants are present only if the corresponding protected
6662 -- type has discriminants, and they exactly mirror the protected type
6663 -- discriminants. The private data fields similarly mirror the
6664 -- private declarations of the protected type.
6666 -- The Object field is always present. It contains RTS specific data
6667 -- used to control the protected object. It is declared as Aliased
6668 -- so that it can be passed as a pointer to the RTS. This allows the
6669 -- protected record to be referenced within RTS data structures.
6670 -- An appropriate Protection type and discriminant are generated.
6672 -- The Service field is present for protected objects with entries. It
6673 -- contains sufficient information to allow the entry service procedure
6674 -- for this object to be called when the object is not known till runtime.
6676 -- One entry_family component is present for each entry family in the
6677 -- task definition (see Expand_N_Task_Type_Declaration).
6679 -- When a protected object is declared, an instance of the protected type
6680 -- value record is created. The elaboration of this declaration creates
6681 -- the correct bounds for the entry families, and also evaluates the
6682 -- priority expression if needed. The initialization routine for
6683 -- the protected type itself then calls Initialize_Protection with
6684 -- appropriate parameters to initialize the value of the Task_Id field.
6685 -- Install_Handlers may be also called if a pragma Attach_Handler applies.
6687 -- Note: this record is passed to the subprograms created by the
6688 -- expansion of protected subprograms and entries. It is an in parameter
6689 -- to protected functions and an in out parameter to procedures and
6690 -- entry bodies. The Entity_Id for this created record type is placed
6691 -- in the Corresponding_Record_Type field of the associated protected
6692 -- type entity.
6694 -- Next we create a procedure specifications for protected subprograms
6695 -- and entry bodies. For each protected subprograms two subprograms are
6696 -- created, an unprotected and a protected version. The unprotected
6697 -- version is called from within other operations of the same protected
6698 -- object.
6700 -- We also build the call to register the procedure if a pragma
6701 -- Interrupt_Handler applies.
6703 -- A single subprogram is created to service all entry bodies; it has an
6704 -- additional boolean out parameter indicating that the previous entry
6705 -- call made by the current task was serviced immediately, i.e. not by
6706 -- proxy. The O parameter contains a pointer to a record object of the
6707 -- type described above. An untyped interface is used here to allow this
6708 -- procedure to be called in places where the type of the object to be
6709 -- serviced is not known. This must be done, for example, when a call
6710 -- that may have been requeued is cancelled; the corresponding object
6711 -- must be serviced, but which object that is not known till runtime.
6713 -- procedure ptypeS
6714 -- (O : System.Address; P : out Boolean);
6715 -- procedure pprocN (_object : in out poV);
6716 -- procedure pproc (_object : in out poV);
6717 -- function pfuncN (_object : poV);
6718 -- function pfunc (_object : poV);
6719 -- ...
6721 -- Note that this must come after the record type declaration, since
6722 -- the specs refer to this type.
6724 procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
6725 Loc : constant Source_Ptr := Sloc (N);
6726 Prottyp : constant Entity_Id := Defining_Identifier (N);
6727 Protnm : constant Name_Id := Chars (Prottyp);
6729 Pdef : constant Node_Id := Protected_Definition (N);
6730 -- This contains two lists; one for visible and one for private decls
6732 Rec_Decl : Node_Id;
6733 Cdecls : List_Id;
6734 Discr_Map : constant Elist_Id := New_Elmt_List;
6735 Priv : Node_Id;
6736 Pent : Entity_Id;
6737 New_Priv : Node_Id;
6738 Comp : Node_Id;
6739 Comp_Id : Entity_Id;
6740 Sub : Node_Id;
6741 Current_Node : Node_Id := N;
6742 Bdef : Entity_Id := Empty; -- avoid uninit warning
6743 Edef : Entity_Id := Empty; -- avoid uninit warning
6744 Entries_Aggr : Node_Id;
6745 Body_Id : Entity_Id;
6746 Body_Arr : Node_Id;
6747 E_Count : Int;
6748 Object_Comp : Node_Id;
6750 procedure Register_Handler;
6751 -- for a protected operation that is an interrupt handler, add the
6752 -- freeze action that will register it as such.
6754 ----------------------
6755 -- Register_Handler --
6756 ----------------------
6758 procedure Register_Handler is
6760 -- All semantic checks already done in Sem_Prag
6762 Prot_Proc : constant Entity_Id :=
6763 Defining_Unit_Name
6764 (Specification (Current_Node));
6766 Proc_Address : constant Node_Id :=
6767 Make_Attribute_Reference (Loc,
6768 Prefix => New_Reference_To (Prot_Proc, Loc),
6769 Attribute_Name => Name_Address);
6771 RTS_Call : constant Entity_Id :=
6772 Make_Procedure_Call_Statement (Loc,
6773 Name =>
6774 New_Reference_To (
6775 RTE (RE_Register_Interrupt_Handler), Loc),
6776 Parameter_Associations =>
6777 New_List (Proc_Address));
6778 begin
6779 Append_Freeze_Action (Prot_Proc, RTS_Call);
6780 end Register_Handler;
6782 -- Start of processing for Expand_N_Protected_Type_Declaration
6784 begin
6785 if Present (Corresponding_Record_Type (Prottyp)) then
6786 return;
6787 else
6788 Rec_Decl := Build_Corresponding_Record (N, Prottyp, Loc);
6789 Cdecls := Component_Items
6790 (Component_List (Type_Definition (Rec_Decl)));
6791 end if;
6793 -- Ada 2005 (AI-345): Propagate the attribute that contains the list
6794 -- of implemented interfaces.
6796 Set_Interface_List (Type_Definition (Rec_Decl), Interface_List (N));
6798 Qualify_Entity_Names (N);
6800 -- If the type has discriminants, their occurrences in the declaration
6801 -- have been replaced by the corresponding discriminals. For components
6802 -- that are constrained by discriminants, their homologues in the
6803 -- corresponding record type must refer to the discriminants of that
6804 -- record, so we must apply a new renaming to subtypes_indications:
6806 -- protected discriminant => discriminal => record discriminant.
6807 -- This replacement is not applied to default expressions, for which
6808 -- the discriminal is correct.
6810 if Has_Discriminants (Prottyp) then
6811 declare
6812 Disc : Entity_Id;
6813 Decl : Node_Id;
6815 begin
6816 Disc := First_Discriminant (Prottyp);
6817 Decl := First (Discriminant_Specifications (Rec_Decl));
6819 while Present (Disc) loop
6820 Append_Elmt (Discriminal (Disc), Discr_Map);
6821 Append_Elmt (Defining_Identifier (Decl), Discr_Map);
6822 Next_Discriminant (Disc);
6823 Next (Decl);
6824 end loop;
6825 end;
6826 end if;
6828 -- Fill in the component declarations
6830 -- Add components for entry families. For each entry family,
6831 -- create an anonymous type declaration with the same size, and
6832 -- analyze the type.
6834 Collect_Entry_Families (Loc, Cdecls, Current_Node, Prottyp);
6836 -- Prepend the _Object field with the right type to the component
6837 -- list. We need to compute the number of entries, and in some cases
6838 -- the number of Attach_Handler pragmas.
6840 declare
6841 Ritem : Node_Id;
6842 Num_Attach_Handler : Int := 0;
6843 Protection_Subtype : Node_Id;
6844 Entry_Count_Expr : constant Node_Id :=
6845 Build_Entry_Count_Expression
6846 (Prottyp, Cdecls, Loc);
6848 begin
6849 if Has_Attach_Handler (Prottyp) then
6850 Ritem := First_Rep_Item (Prottyp);
6851 while Present (Ritem) loop
6852 if Nkind (Ritem) = N_Pragma
6853 and then Chars (Ritem) = Name_Attach_Handler
6854 then
6855 Num_Attach_Handler := Num_Attach_Handler + 1;
6856 end if;
6858 Next_Rep_Item (Ritem);
6859 end loop;
6861 if Restricted_Profile then
6862 if Has_Entries (Prottyp) then
6863 Protection_Subtype :=
6864 New_Reference_To (RTE (RE_Protection_Entry), Loc);
6865 else
6866 Protection_Subtype :=
6867 New_Reference_To (RTE (RE_Protection), Loc);
6868 end if;
6869 else
6870 Protection_Subtype :=
6871 Make_Subtype_Indication
6872 (Sloc => Loc,
6873 Subtype_Mark =>
6874 New_Reference_To
6875 (RTE (RE_Static_Interrupt_Protection), Loc),
6876 Constraint =>
6877 Make_Index_Or_Discriminant_Constraint (
6878 Sloc => Loc,
6879 Constraints => New_List (
6880 Entry_Count_Expr,
6881 Make_Integer_Literal (Loc, Num_Attach_Handler))));
6882 end if;
6884 elsif Has_Interrupt_Handler (Prottyp) then
6885 Protection_Subtype :=
6886 Make_Subtype_Indication (
6887 Sloc => Loc,
6888 Subtype_Mark => New_Reference_To
6889 (RTE (RE_Dynamic_Interrupt_Protection), Loc),
6890 Constraint =>
6891 Make_Index_Or_Discriminant_Constraint (
6892 Sloc => Loc,
6893 Constraints => New_List (Entry_Count_Expr)));
6895 -- The type has explicit entries or generated primitive entry
6896 -- wrappers.
6898 elsif Has_Entries (Prottyp)
6899 or else (Ada_Version >= Ada_05
6900 and then Present (Interface_List (N)))
6901 then
6902 if Abort_Allowed
6903 or else Restriction_Active (No_Entry_Queue) = False
6904 or else Number_Entries (Prottyp) > 1
6905 then
6906 Protection_Subtype :=
6907 Make_Subtype_Indication (
6908 Sloc => Loc,
6909 Subtype_Mark =>
6910 New_Reference_To (RTE (RE_Protection_Entries), Loc),
6911 Constraint =>
6912 Make_Index_Or_Discriminant_Constraint (
6913 Sloc => Loc,
6914 Constraints => New_List (Entry_Count_Expr)));
6916 else
6917 Protection_Subtype :=
6918 New_Reference_To (RTE (RE_Protection_Entry), Loc);
6919 end if;
6921 else
6922 Protection_Subtype := New_Reference_To (RTE (RE_Protection), Loc);
6923 end if;
6925 Object_Comp :=
6926 Make_Component_Declaration (Loc,
6927 Defining_Identifier =>
6928 Make_Defining_Identifier (Loc, Name_uObject),
6929 Component_Definition =>
6930 Make_Component_Definition (Loc,
6931 Aliased_Present => True,
6932 Subtype_Indication => Protection_Subtype));
6933 end;
6935 pragma Assert (Present (Pdef));
6937 -- Add private field components
6939 if Present (Private_Declarations (Pdef)) then
6940 Priv := First (Private_Declarations (Pdef));
6942 while Present (Priv) loop
6944 if Nkind (Priv) = N_Component_Declaration then
6945 Pent := Defining_Identifier (Priv);
6946 New_Priv :=
6947 Make_Component_Declaration (Loc,
6948 Defining_Identifier =>
6949 Make_Defining_Identifier (Sloc (Pent), Chars (Pent)),
6950 Component_Definition =>
6951 Make_Component_Definition (Sloc (Pent),
6952 Aliased_Present => False,
6953 Subtype_Indication =>
6954 New_Copy_Tree (Subtype_Indication
6955 (Component_Definition (Priv)),
6956 Discr_Map)),
6957 Expression => Expression (Priv));
6959 Append_To (Cdecls, New_Priv);
6961 elsif Nkind (Priv) = N_Subprogram_Declaration then
6963 -- Make the unprotected version of the subprogram available
6964 -- for expansion of intra object calls. There is need for
6965 -- a protected version only if the subprogram is an interrupt
6966 -- handler, otherwise this operation can only be called from
6967 -- within the body.
6969 Sub :=
6970 Make_Subprogram_Declaration (Loc,
6971 Specification =>
6972 Build_Protected_Sub_Specification
6973 (Priv, Prottyp, Unprotected_Mode));
6975 Insert_After (Current_Node, Sub);
6976 Analyze (Sub);
6978 Set_Protected_Body_Subprogram
6979 (Defining_Unit_Name (Specification (Priv)),
6980 Defining_Unit_Name (Specification (Sub)));
6982 Current_Node := Sub;
6984 if Is_Interrupt_Handler
6985 (Defining_Unit_Name (Specification (Priv)))
6986 then
6987 Sub :=
6988 Make_Subprogram_Declaration (Loc,
6989 Specification =>
6990 Build_Protected_Sub_Specification
6991 (Priv, Prottyp, Protected_Mode));
6993 Insert_After (Current_Node, Sub);
6994 Analyze (Sub);
6995 Current_Node := Sub;
6997 if not Restricted_Profile then
6998 Register_Handler;
6999 end if;
7000 end if;
7001 end if;
7003 Next (Priv);
7004 end loop;
7005 end if;
7007 -- Put the _Object component after the private component so that it
7008 -- be finalized early as required by 9.4 (20)
7010 Append_To (Cdecls, Object_Comp);
7012 Insert_After (Current_Node, Rec_Decl);
7013 Current_Node := Rec_Decl;
7015 -- Analyze the record declaration immediately after construction,
7016 -- because the initialization procedure is needed for single object
7017 -- declarations before the next entity is analyzed (the freeze call
7018 -- that generates this initialization procedure is found below).
7020 Analyze (Rec_Decl, Suppress => All_Checks);
7022 -- Ada 2005 (AI-345): Construct the primitive entry wrappers before
7023 -- the corresponding record is frozen
7025 if Ada_Version >= Ada_05
7026 and then Present (Visible_Declarations (Pdef))
7027 and then Present (Corresponding_Record_Type
7028 (Defining_Identifier (Parent (Pdef))))
7029 and then Present (Abstract_Interfaces
7030 (Corresponding_Record_Type
7031 (Defining_Identifier (Parent (Pdef)))))
7032 then
7033 declare
7034 Current_Node : Node_Id := Rec_Decl;
7035 Vis_Decl : Node_Id;
7036 Wrap_Spec : Node_Id;
7037 New_N : Node_Id;
7039 begin
7040 -- Examine the visible declarations of the protected type, looking
7041 -- for declarations of entries, and subprograms. We do not
7042 -- consider entry families since they can not have dispatching
7043 -- operations, thus they do not need entry wrappers.
7045 Vis_Decl := First (Visible_Declarations (Pdef));
7047 while Present (Vis_Decl) loop
7049 Wrap_Spec := Empty;
7051 if Nkind (Vis_Decl) = N_Entry_Declaration
7052 and then not Present (Discrete_Subtype_Definition (Vis_Decl))
7053 then
7054 Wrap_Spec :=
7055 Build_Wrapper_Spec (Loc,
7056 Proc_Nam => Defining_Identifier (Vis_Decl),
7057 Obj_Typ => Defining_Identifier (Rec_Decl),
7058 Formals => Parameter_Specifications (Vis_Decl));
7060 elsif Nkind (Vis_Decl) = N_Subprogram_Declaration then
7061 Wrap_Spec :=
7062 Build_Wrapper_Spec (Loc,
7063 Proc_Nam => Defining_Unit_Name
7064 (Specification (Vis_Decl)),
7065 Obj_Typ => Defining_Identifier (Rec_Decl),
7066 Formals => Parameter_Specifications
7067 (Specification (Vis_Decl)));
7069 end if;
7071 if Wrap_Spec /= Empty then
7072 New_N := Make_Subprogram_Declaration (Loc,
7073 Specification => Wrap_Spec);
7075 Insert_After (Current_Node, New_N);
7076 Current_Node := New_N;
7078 Analyze (New_N);
7079 end if;
7081 Next (Vis_Decl);
7082 end loop;
7083 end;
7084 end if;
7086 -- Collect pointers to entry bodies and their barriers, to be placed
7087 -- in the Entry_Bodies_Array for the type. For each entry/family we
7088 -- add an expression to the aggregate which is the initial value of
7089 -- this array. The array is declared after all protected subprograms.
7091 if Has_Entries (Prottyp) then
7092 Entries_Aggr :=
7093 Make_Aggregate (Loc, Expressions => New_List);
7095 else
7096 Entries_Aggr := Empty;
7097 end if;
7099 -- Build two new procedure specifications for each protected
7100 -- subprogram; one to call from outside the object and one to
7101 -- call from inside. Build a barrier function and an entry
7102 -- body action procedure specification for each protected entry.
7103 -- Initialize the entry body array. If subprogram is flagged as
7104 -- eliminated, do not generate any internal operations.
7106 E_Count := 0;
7108 Comp := First (Visible_Declarations (Pdef));
7110 while Present (Comp) loop
7111 if Nkind (Comp) = N_Subprogram_Declaration
7112 and then not Is_Eliminated (Defining_Entity (Comp))
7113 then
7114 Sub :=
7115 Make_Subprogram_Declaration (Loc,
7116 Specification =>
7117 Build_Protected_Sub_Specification
7118 (Comp, Prottyp, Unprotected_Mode));
7120 Insert_After (Current_Node, Sub);
7121 Analyze (Sub);
7123 Set_Protected_Body_Subprogram
7124 (Defining_Unit_Name (Specification (Comp)),
7125 Defining_Unit_Name (Specification (Sub)));
7127 -- Make the protected version of the subprogram available
7128 -- for expansion of external calls.
7130 Current_Node := Sub;
7132 Sub :=
7133 Make_Subprogram_Declaration (Loc,
7134 Specification =>
7135 Build_Protected_Sub_Specification
7136 (Comp, Prottyp, Protected_Mode));
7138 Insert_After (Current_Node, Sub);
7139 Analyze (Sub);
7141 Current_Node := Sub;
7143 -- Generate an overriding primitive operation specification for
7144 -- this subprogram if the protected type implements an inerface.
7146 if Ada_Version >= Ada_05
7147 and then
7148 Present (Abstract_Interfaces
7149 (Corresponding_Record_Type (Prottyp)))
7150 then
7151 Sub :=
7152 Make_Subprogram_Declaration (Loc,
7153 Specification =>
7154 Build_Protected_Sub_Specification
7155 (Comp, Prottyp, Dispatching_Mode));
7157 Insert_After (Current_Node, Sub);
7158 Analyze (Sub);
7160 Current_Node := Sub;
7161 end if;
7163 -- If a pragma Interrupt_Handler applies, build and add
7164 -- a call to Register_Interrupt_Handler to the freezing actions
7165 -- of the protected version (Current_Node) of the subprogram:
7166 -- system.interrupts.register_interrupt_handler
7167 -- (prot_procP'address);
7169 if not Restricted_Profile
7170 and then Is_Interrupt_Handler
7171 (Defining_Unit_Name (Specification (Comp)))
7172 then
7173 Register_Handler;
7174 end if;
7176 elsif Nkind (Comp) = N_Entry_Declaration then
7177 E_Count := E_Count + 1;
7178 Comp_Id := Defining_Identifier (Comp);
7179 Set_Privals_Chain (Comp_Id, New_Elmt_List);
7180 Edef :=
7181 Make_Defining_Identifier (Loc,
7182 Build_Selected_Name
7183 (Protnm,
7184 New_External_Name (Chars (Comp_Id), Suffix_Index => -1),
7185 'E'));
7186 Sub :=
7187 Make_Subprogram_Declaration (Loc,
7188 Specification =>
7189 Build_Protected_Entry_Specification (Edef, Comp_Id, Loc));
7191 Insert_After (Current_Node, Sub);
7192 Analyze (Sub);
7194 Set_Protected_Body_Subprogram (
7195 Defining_Identifier (Comp),
7196 Defining_Unit_Name (Specification (Sub)));
7198 Current_Node := Sub;
7200 Bdef :=
7201 Make_Defining_Identifier (Loc,
7202 Build_Selected_Name
7203 (Protnm,
7204 New_External_Name (Chars (Comp_Id), Suffix_Index => -1),
7205 'B'));
7206 Sub :=
7207 Make_Subprogram_Declaration (Loc,
7208 Specification =>
7209 Build_Barrier_Function_Specification (Bdef, Loc));
7211 Insert_After (Current_Node, Sub);
7212 Analyze (Sub);
7213 Set_Protected_Body_Subprogram (Bdef, Bdef);
7214 Set_Barrier_Function (Comp_Id, Bdef);
7215 Set_Scope (Bdef, Scope (Comp_Id));
7216 Current_Node := Sub;
7218 -- Collect pointers to the protected subprogram and the barrier
7219 -- of the current entry, for insertion into Entry_Bodies_Array.
7221 Append (
7222 Make_Aggregate (Loc,
7223 Expressions => New_List (
7224 Make_Attribute_Reference (Loc,
7225 Prefix => New_Reference_To (Bdef, Loc),
7226 Attribute_Name => Name_Unrestricted_Access),
7227 Make_Attribute_Reference (Loc,
7228 Prefix => New_Reference_To (Edef, Loc),
7229 Attribute_Name => Name_Unrestricted_Access))),
7230 Expressions (Entries_Aggr));
7232 end if;
7234 Next (Comp);
7235 end loop;
7237 -- If there are some private entry declarations, expand it as if they
7238 -- were visible entries.
7240 if Present (Private_Declarations (Pdef)) then
7241 Comp := First (Private_Declarations (Pdef));
7242 while Present (Comp) loop
7243 if Nkind (Comp) = N_Entry_Declaration then
7244 E_Count := E_Count + 1;
7245 Comp_Id := Defining_Identifier (Comp);
7246 Set_Privals_Chain (Comp_Id, New_Elmt_List);
7247 Edef :=
7248 Make_Defining_Identifier (Loc,
7249 Build_Selected_Name
7250 (Protnm,
7251 New_External_Name (Chars (Comp_Id), Suffix_Index => -1),
7252 'E'));
7254 Sub :=
7255 Make_Subprogram_Declaration (Loc,
7256 Specification =>
7257 Build_Protected_Entry_Specification (Edef, Comp_Id, Loc));
7259 Insert_After (Current_Node, Sub);
7260 Analyze (Sub);
7262 Set_Protected_Body_Subprogram (
7263 Defining_Identifier (Comp),
7264 Defining_Unit_Name (Specification (Sub)));
7266 Current_Node := Sub;
7268 Bdef :=
7269 Make_Defining_Identifier (Loc,
7270 Build_Selected_Name
7271 (Protnm,
7272 New_External_Name (Chars (Comp_Id), Suffix_Index => -1),
7273 'B'));
7274 Sub :=
7275 Make_Subprogram_Declaration (Loc,
7276 Specification =>
7277 Build_Barrier_Function_Specification (Bdef, Loc));
7279 Insert_After (Current_Node, Sub);
7280 Analyze (Sub);
7281 Set_Protected_Body_Subprogram (Bdef, Bdef);
7282 Set_Barrier_Function (Comp_Id, Bdef);
7283 Set_Scope (Bdef, Scope (Comp_Id));
7284 Current_Node := Sub;
7286 -- Collect pointers to the protected subprogram and the
7287 -- barrier of the current entry, for insertion into
7288 -- Entry_Bodies_Array.
7290 Append (
7291 Make_Aggregate (Loc,
7292 Expressions => New_List (
7293 Make_Attribute_Reference (Loc,
7294 Prefix => New_Reference_To (Bdef, Loc),
7295 Attribute_Name => Name_Unrestricted_Access),
7296 Make_Attribute_Reference (Loc,
7297 Prefix => New_Reference_To (Edef, Loc),
7298 Attribute_Name => Name_Unrestricted_Access))),
7299 Expressions (Entries_Aggr));
7300 end if;
7302 Next (Comp);
7303 end loop;
7304 end if;
7306 -- Emit declaration for Entry_Bodies_Array, now that the addresses of
7307 -- all protected subprograms have been collected.
7309 if Has_Entries (Prottyp) then
7310 Body_Id := Make_Defining_Identifier (Sloc (Prottyp),
7311 New_External_Name (Chars (Prottyp), 'A'));
7313 if Abort_Allowed
7314 or else Restriction_Active (No_Entry_Queue) = False
7315 or else E_Count > 1
7316 then
7317 Body_Arr := Make_Object_Declaration (Loc,
7318 Defining_Identifier => Body_Id,
7319 Aliased_Present => True,
7320 Object_Definition =>
7321 Make_Subtype_Indication (Loc,
7322 Subtype_Mark => New_Reference_To (
7323 RTE (RE_Protected_Entry_Body_Array), Loc),
7324 Constraint =>
7325 Make_Index_Or_Discriminant_Constraint (Loc,
7326 Constraints => New_List (
7327 Make_Range (Loc,
7328 Make_Integer_Literal (Loc, 1),
7329 Make_Integer_Literal (Loc, E_Count))))),
7330 Expression => Entries_Aggr);
7332 else
7333 Body_Arr := Make_Object_Declaration (Loc,
7334 Defining_Identifier => Body_Id,
7335 Aliased_Present => True,
7336 Object_Definition => New_Reference_To (RTE (RE_Entry_Body), Loc),
7337 Expression =>
7338 Make_Aggregate (Loc,
7339 Expressions => New_List (
7340 Make_Attribute_Reference (Loc,
7341 Prefix => New_Reference_To (Bdef, Loc),
7342 Attribute_Name => Name_Unrestricted_Access),
7343 Make_Attribute_Reference (Loc,
7344 Prefix => New_Reference_To (Edef, Loc),
7345 Attribute_Name => Name_Unrestricted_Access))));
7346 end if;
7348 -- A pointer to this array will be placed in the corresponding
7349 -- record by its initialization procedure, so this needs to be
7350 -- analyzed here.
7352 Insert_After (Current_Node, Body_Arr);
7353 Current_Node := Body_Arr;
7354 Analyze (Body_Arr);
7356 Set_Entry_Bodies_Array (Prottyp, Body_Id);
7358 -- Finally, build the function that maps an entry index into the
7359 -- corresponding body. A pointer to this function is placed in each
7360 -- object of the type. Except for a ravenscar-like profile (no abort,
7361 -- no entry queue, 1 entry)
7363 if Abort_Allowed
7364 or else Restriction_Active (No_Entry_Queue) = False
7365 or else E_Count > 1
7366 then
7367 Sub :=
7368 Make_Subprogram_Declaration (Loc,
7369 Specification => Build_Find_Body_Index_Spec (Prottyp));
7370 Insert_After (Current_Node, Sub);
7371 Analyze (Sub);
7372 end if;
7373 end if;
7374 end Expand_N_Protected_Type_Declaration;
7376 --------------------------------
7377 -- Expand_N_Requeue_Statement --
7378 --------------------------------
7380 -- A requeue statement is expanded into one of four GNARLI operations,
7381 -- depending on the source and destination (task or protected object).
7382 -- In addition, code must be generated to jump around the remainder of
7383 -- processing for the original entry and, if the destination is a
7384 -- (different) protected object, to attempt to service it.
7385 -- The following illustrates the various cases:
7387 -- procedure entE
7388 -- (O : System.Address;
7389 -- P : System.Address;
7390 -- E : Protected_Entry_Index)
7391 -- is
7392 -- <discriminant renamings>
7393 -- <private object renamings>
7394 -- type poVP is access poV;
7395 -- _Object : ptVP := ptVP!(O);
7397 -- begin
7398 -- begin
7399 -- <start of statement sequence for entry>
7401 -- -- Requeue from one protected entry body to another protected
7402 -- -- entry.
7404 -- Requeue_Protected_Entry (
7405 -- _object._object'Access,
7406 -- new._object'Access,
7407 -- E,
7408 -- Abort_Present);
7409 -- return;
7411 -- <some more of the statement sequence for entry>
7413 -- -- Requeue from an entry body to a task entry
7415 -- Requeue_Protected_To_Task_Entry (
7416 -- New._task_id,
7417 -- E,
7418 -- Abort_Present);
7419 -- return;
7421 -- <rest of statement sequence for entry>
7422 -- Complete_Entry_Body (_Object._Object);
7424 -- exception
7425 -- when all others =>
7426 -- Exceptional_Complete_Entry_Body (
7427 -- _Object._Object, Get_GNAT_Exception);
7428 -- end;
7429 -- end entE;
7431 -- Requeue of a task entry call to a task entry
7433 -- Accept_Call (E, Ann);
7434 -- <start of statement sequence for accept statement>
7435 -- Requeue_Task_Entry (New._task_id, E, Abort_Present);
7436 -- goto Lnn;
7437 -- <rest of statement sequence for accept statement>
7438 -- <<Lnn>>
7439 -- Complete_Rendezvous;
7441 -- exception
7442 -- when all others =>
7443 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
7445 -- Requeue of a task entry call to a protected entry
7447 -- Accept_Call (E, Ann);
7448 -- <start of statement sequence for accept statement>
7449 -- Requeue_Task_To_Protected_Entry (
7450 -- new._object'Access,
7451 -- E,
7452 -- Abort_Present);
7453 -- newS (new, Pnn);
7454 -- goto Lnn;
7455 -- <rest of statement sequence for accept statement>
7456 -- <<Lnn>>
7457 -- Complete_Rendezvous;
7459 -- exception
7460 -- when all others =>
7461 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
7463 -- Further details on these expansions can be found in
7464 -- Expand_N_Protected_Body and Expand_N_Accept_Statement.
7466 procedure Expand_N_Requeue_Statement (N : Node_Id) is
7467 Loc : constant Source_Ptr := Sloc (N);
7468 Acc_Stat : Node_Id;
7469 Concval : Node_Id;
7470 Ename : Node_Id;
7471 Index : Node_Id;
7472 Conctyp : Entity_Id;
7473 Oldtyp : Entity_Id;
7474 Lab_Node : Node_Id;
7475 Rcall : Node_Id;
7476 Abortable : Node_Id;
7477 Skip_Stat : Node_Id;
7478 Self_Param : Node_Id;
7479 New_Param : Node_Id;
7480 Params : List_Id;
7481 RTS_Call : Entity_Id;
7483 begin
7484 Abortable :=
7485 New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc);
7487 -- Set up the target object
7489 Extract_Entry (N, Concval, Ename, Index);
7490 Conctyp := Etype (Concval);
7491 New_Param := Concurrent_Ref (Concval);
7493 -- The target entry index and abortable flag are the same for all cases
7495 Params := New_List (
7496 Entry_Index_Expression (Loc, Entity (Ename), Index, Conctyp),
7497 Abortable);
7499 -- Determine proper GNARLI call and required additional parameters
7500 -- Loop to find nearest enclosing task type or protected type
7502 Oldtyp := Current_Scope;
7503 loop
7504 if Is_Task_Type (Oldtyp) then
7505 if Is_Task_Type (Conctyp) then
7506 RTS_Call := RTE (RE_Requeue_Task_Entry);
7508 else
7509 pragma Assert (Is_Protected_Type (Conctyp));
7510 RTS_Call := RTE (RE_Requeue_Task_To_Protected_Entry);
7511 New_Param :=
7512 Make_Attribute_Reference (Loc,
7513 Prefix => New_Param,
7514 Attribute_Name => Name_Unchecked_Access);
7515 end if;
7517 Prepend (New_Param, Params);
7518 exit;
7520 elsif Is_Protected_Type (Oldtyp) then
7521 Self_Param :=
7522 Make_Attribute_Reference (Loc,
7523 Prefix => Concurrent_Ref (New_Occurrence_Of (Oldtyp, Loc)),
7524 Attribute_Name => Name_Unchecked_Access);
7526 if Is_Task_Type (Conctyp) then
7527 RTS_Call := RTE (RE_Requeue_Protected_To_Task_Entry);
7529 else
7530 pragma Assert (Is_Protected_Type (Conctyp));
7531 RTS_Call := RTE (RE_Requeue_Protected_Entry);
7532 New_Param :=
7533 Make_Attribute_Reference (Loc,
7534 Prefix => New_Param,
7535 Attribute_Name => Name_Unchecked_Access);
7536 end if;
7538 Prepend (New_Param, Params);
7539 Prepend (Self_Param, Params);
7540 exit;
7542 -- If neither task type or protected type, must be in some
7543 -- inner enclosing block, so move on out
7545 else
7546 Oldtyp := Scope (Oldtyp);
7547 end if;
7548 end loop;
7550 -- Create the GNARLI call
7552 Rcall := Make_Procedure_Call_Statement (Loc,
7553 Name =>
7554 New_Occurrence_Of (RTS_Call, Loc),
7555 Parameter_Associations => Params);
7557 Rewrite (N, Rcall);
7558 Analyze (N);
7560 if Is_Protected_Type (Oldtyp) then
7562 -- Build the return statement to skip the rest of the entry body
7564 Skip_Stat := Make_Return_Statement (Loc);
7566 else
7567 -- If the requeue is within a task, find the end label of the
7568 -- enclosing accept statement.
7570 Acc_Stat := Parent (N);
7571 while Nkind (Acc_Stat) /= N_Accept_Statement loop
7572 Acc_Stat := Parent (Acc_Stat);
7573 end loop;
7575 -- The last statement is the second label, used for completing the
7576 -- rendezvous the usual way.
7577 -- The label we are looking for is right before it.
7579 Lab_Node :=
7580 Prev (Last (Statements (Handled_Statement_Sequence (Acc_Stat))));
7582 pragma Assert (Nkind (Lab_Node) = N_Label);
7584 -- Build the goto statement to skip the rest of the accept
7585 -- statement.
7587 Skip_Stat :=
7588 Make_Goto_Statement (Loc,
7589 Name => New_Occurrence_Of (Entity (Identifier (Lab_Node)), Loc));
7590 end if;
7592 Set_Analyzed (Skip_Stat);
7594 Insert_After (N, Skip_Stat);
7595 end Expand_N_Requeue_Statement;
7597 -------------------------------
7598 -- Expand_N_Selective_Accept --
7599 -------------------------------
7601 procedure Expand_N_Selective_Accept (N : Node_Id) is
7602 Loc : constant Source_Ptr := Sloc (N);
7603 Alts : constant List_Id := Select_Alternatives (N);
7605 -- Note: in the below declarations a lot of new lists are allocated
7606 -- unconditionally which may well not end up being used. That's
7607 -- not a good idea since it wastes space gratuitously ???
7609 Accept_Case : List_Id;
7610 Accept_List : constant List_Id := New_List;
7612 Alt : Node_Id;
7613 Alt_List : constant List_Id := New_List;
7614 Alt_Stats : List_Id;
7615 Ann : Entity_Id := Empty;
7617 Block : Node_Id;
7618 Check_Guard : Boolean := True;
7620 Decls : constant List_Id := New_List;
7621 Stats : constant List_Id := New_List;
7622 Body_List : constant List_Id := New_List;
7623 Trailing_List : constant List_Id := New_List;
7625 Choices : List_Id;
7626 Else_Present : Boolean := False;
7627 Terminate_Alt : Node_Id := Empty;
7628 Select_Mode : Node_Id;
7630 Delay_Case : List_Id;
7631 Delay_Count : Integer := 0;
7632 Delay_Val : Entity_Id;
7633 Delay_Index : Entity_Id;
7634 Delay_Min : Entity_Id;
7635 Delay_Num : Int := 1;
7636 Delay_Alt_List : List_Id := New_List;
7637 Delay_List : constant List_Id := New_List;
7638 D : Entity_Id;
7639 M : Entity_Id;
7641 First_Delay : Boolean := True;
7642 Guard_Open : Entity_Id;
7644 End_Lab : Node_Id;
7645 Index : Int := 1;
7646 Lab : Node_Id;
7647 Num_Alts : Int;
7648 Num_Accept : Nat := 0;
7649 Proc : Node_Id;
7650 Q : Node_Id;
7651 Time_Type : Entity_Id;
7652 X : Node_Id;
7653 Select_Call : Node_Id;
7655 Qnam : constant Entity_Id :=
7656 Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
7658 Xnam : constant Entity_Id :=
7659 Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
7661 -----------------------
7662 -- Local subprograms --
7663 -----------------------
7665 function Accept_Or_Raise return List_Id;
7666 -- For the rare case where delay alternatives all have guards, and
7667 -- all of them are closed, it is still possible that there were open
7668 -- accept alternatives with no callers. We must reexamine the
7669 -- Accept_List, and execute a selective wait with no else if some
7670 -- accept is open. If none, we raise program_error.
7672 procedure Add_Accept (Alt : Node_Id);
7673 -- Process a single accept statement in a select alternative. Build
7674 -- procedure for body of accept, and add entry to dispatch table with
7675 -- expression for guard, in preparation for call to run time select.
7677 function Make_And_Declare_Label (Num : Int) return Node_Id;
7678 -- Manufacture a label using Num as a serial number and declare it.
7679 -- The declaration is appended to Decls. The label marks the trailing
7680 -- statements of an accept or delay alternative.
7682 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
7683 -- Build call to Selective_Wait runtime routine
7685 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
7686 -- Add code to compare value of delay with previous values, and
7687 -- generate case entry for trailing statements.
7689 procedure Process_Accept_Alternative
7690 (Alt : Node_Id;
7691 Index : Int;
7692 Proc : Node_Id);
7693 -- Add code to call corresponding procedure, and branch to
7694 -- trailing statements, if any.
7696 ---------------------
7697 -- Accept_Or_Raise --
7698 ---------------------
7700 function Accept_Or_Raise return List_Id is
7701 Cond : Node_Id;
7702 Stats : List_Id;
7703 J : constant Entity_Id := Make_Defining_Identifier (Loc,
7704 New_Internal_Name ('J'));
7706 begin
7707 -- We generate the following:
7709 -- for J in q'range loop
7710 -- if q(J).S /=null_task_entry then
7711 -- selective_wait (simple_mode,...);
7712 -- done := True;
7713 -- exit;
7714 -- end if;
7715 -- end loop;
7717 -- if no rendez_vous then
7718 -- raise program_error;
7719 -- end if;
7721 -- Note that the code needs to know that the selector name
7722 -- in an Accept_Alternative is named S.
7724 Cond := Make_Op_Ne (Loc,
7725 Left_Opnd =>
7726 Make_Selected_Component (Loc,
7727 Prefix => Make_Indexed_Component (Loc,
7728 Prefix => New_Reference_To (Qnam, Loc),
7729 Expressions => New_List (New_Reference_To (J, Loc))),
7730 Selector_Name => Make_Identifier (Loc, Name_S)),
7731 Right_Opnd =>
7732 New_Reference_To (RTE (RE_Null_Task_Entry), Loc));
7734 Stats := New_List (
7735 Make_Implicit_Loop_Statement (N,
7736 Identifier => Empty,
7737 Iteration_Scheme =>
7738 Make_Iteration_Scheme (Loc,
7739 Loop_Parameter_Specification =>
7740 Make_Loop_Parameter_Specification (Loc,
7741 Defining_Identifier => J,
7742 Discrete_Subtype_Definition =>
7743 Make_Attribute_Reference (Loc,
7744 Prefix => New_Reference_To (Qnam, Loc),
7745 Attribute_Name => Name_Range,
7746 Expressions => New_List (
7747 Make_Integer_Literal (Loc, 1))))),
7749 Statements => New_List (
7750 Make_Implicit_If_Statement (N,
7751 Condition => Cond,
7752 Then_Statements => New_List (
7753 Make_Select_Call (
7754 New_Reference_To (RTE (RE_Simple_Mode), Loc)),
7755 Make_Exit_Statement (Loc))))));
7757 Append_To (Stats,
7758 Make_Raise_Program_Error (Loc,
7759 Condition => Make_Op_Eq (Loc,
7760 Left_Opnd => New_Reference_To (Xnam, Loc),
7761 Right_Opnd =>
7762 New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
7763 Reason => PE_All_Guards_Closed));
7765 return Stats;
7766 end Accept_Or_Raise;
7768 ----------------
7769 -- Add_Accept --
7770 ----------------
7772 procedure Add_Accept (Alt : Node_Id) is
7773 Acc_Stm : constant Node_Id := Accept_Statement (Alt);
7774 Ename : constant Node_Id := Entry_Direct_Name (Acc_Stm);
7775 Eent : constant Entity_Id := Entity (Ename);
7776 Index : constant Node_Id := Entry_Index (Acc_Stm);
7777 Null_Body : Node_Id;
7778 Proc_Body : Node_Id;
7779 PB_Ent : Entity_Id;
7780 Expr : Node_Id;
7781 Call : Node_Id;
7783 begin
7784 if No (Ann) then
7785 Ann := Node (Last_Elmt (Accept_Address (Eent)));
7786 end if;
7788 if Present (Condition (Alt)) then
7789 Expr :=
7790 Make_Conditional_Expression (Loc, New_List (
7791 Condition (Alt),
7792 Entry_Index_Expression (Loc, Eent, Index, Scope (Eent)),
7793 New_Reference_To (RTE (RE_Null_Task_Entry), Loc)));
7794 else
7795 Expr :=
7796 Entry_Index_Expression
7797 (Loc, Eent, Index, Scope (Eent));
7798 end if;
7800 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
7801 Null_Body := New_Reference_To (Standard_False, Loc);
7803 if Abort_Allowed then
7804 Call := Make_Procedure_Call_Statement (Loc,
7805 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc));
7806 Insert_Before (First (Statements (Handled_Statement_Sequence (
7807 Accept_Statement (Alt)))), Call);
7808 Analyze (Call);
7809 end if;
7811 PB_Ent :=
7812 Make_Defining_Identifier (Sloc (Ename),
7813 New_External_Name (Chars (Ename), 'A', Num_Accept));
7815 Set_Needs_Debug_Info (PB_Ent, Comes_From_Source (Alt));
7817 Proc_Body :=
7818 Make_Subprogram_Body (Loc,
7819 Specification =>
7820 Make_Procedure_Specification (Loc,
7821 Defining_Unit_Name => PB_Ent),
7822 Declarations => Declarations (Acc_Stm),
7823 Handled_Statement_Sequence =>
7824 Build_Accept_Body (Accept_Statement (Alt)));
7826 -- During the analysis of the body of the accept statement, any
7827 -- zero cost exception handler records were collected in the
7828 -- Accept_Handler_Records field of the N_Accept_Alternative
7829 -- node. This is where we move them to where they belong,
7830 -- namely the newly created procedure.
7832 Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
7833 Append (Proc_Body, Body_List);
7835 else
7836 Null_Body := New_Reference_To (Standard_True, Loc);
7838 -- if accept statement has declarations, insert above, given
7839 -- that we are not creating a body for the accept.
7841 if Present (Declarations (Acc_Stm)) then
7842 Insert_Actions (N, Declarations (Acc_Stm));
7843 end if;
7844 end if;
7846 Append_To (Accept_List,
7847 Make_Aggregate (Loc, Expressions => New_List (Null_Body, Expr)));
7849 Num_Accept := Num_Accept + 1;
7850 end Add_Accept;
7852 ----------------------------
7853 -- Make_And_Declare_Label --
7854 ----------------------------
7856 function Make_And_Declare_Label (Num : Int) return Node_Id is
7857 Lab_Id : Node_Id;
7859 begin
7860 Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
7861 Lab :=
7862 Make_Label (Loc, Lab_Id);
7864 Append_To (Decls,
7865 Make_Implicit_Label_Declaration (Loc,
7866 Defining_Identifier =>
7867 Make_Defining_Identifier (Loc, Chars (Lab_Id)),
7868 Label_Construct => Lab));
7870 return Lab;
7871 end Make_And_Declare_Label;
7873 ----------------------
7874 -- Make_Select_Call --
7875 ----------------------
7877 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
7878 Params : constant List_Id := New_List;
7880 begin
7881 Append (
7882 Make_Attribute_Reference (Loc,
7883 Prefix => New_Reference_To (Qnam, Loc),
7884 Attribute_Name => Name_Unchecked_Access),
7885 Params);
7886 Append (Select_Mode, Params);
7887 Append (New_Reference_To (Ann, Loc), Params);
7888 Append (New_Reference_To (Xnam, Loc), Params);
7890 return
7891 Make_Procedure_Call_Statement (Loc,
7892 Name => New_Reference_To (RTE (RE_Selective_Wait), Loc),
7893 Parameter_Associations => Params);
7894 end Make_Select_Call;
7896 --------------------------------
7897 -- Process_Accept_Alternative --
7898 --------------------------------
7900 procedure Process_Accept_Alternative
7901 (Alt : Node_Id;
7902 Index : Int;
7903 Proc : Node_Id)
7905 Choices : List_Id := No_List;
7906 Alt_Stats : List_Id;
7908 begin
7909 Adjust_Condition (Condition (Alt));
7910 Alt_Stats := No_List;
7912 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
7913 Choices := New_List (
7914 Make_Integer_Literal (Loc, Index));
7916 Alt_Stats := New_List (
7917 Make_Procedure_Call_Statement (Loc,
7918 Name => New_Reference_To (
7919 Defining_Unit_Name (Specification (Proc)), Loc)));
7920 end if;
7922 if Statements (Alt) /= Empty_List then
7924 if No (Alt_Stats) then
7926 -- Accept with no body, followed by trailing statements
7928 Choices := New_List (
7929 Make_Integer_Literal (Loc, Index));
7931 Alt_Stats := New_List;
7932 end if;
7934 -- After the call, if any, branch to to trailing statements.
7935 -- We create a label for each, as well as the corresponding
7936 -- label declaration.
7938 Lab := Make_And_Declare_Label (Index);
7939 Append_To (Alt_Stats,
7940 Make_Goto_Statement (Loc,
7941 Name => New_Copy (Identifier (Lab))));
7943 Append (Lab, Trailing_List);
7944 Append_List (Statements (Alt), Trailing_List);
7945 Append_To (Trailing_List,
7946 Make_Goto_Statement (Loc,
7947 Name => New_Copy (Identifier (End_Lab))));
7948 end if;
7950 if Present (Alt_Stats) then
7952 -- Procedure call. and/or trailing statements
7954 Append_To (Alt_List,
7955 Make_Case_Statement_Alternative (Loc,
7956 Discrete_Choices => Choices,
7957 Statements => Alt_Stats));
7958 end if;
7959 end Process_Accept_Alternative;
7961 -------------------------------
7962 -- Process_Delay_Alternative --
7963 -------------------------------
7965 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
7966 Choices : List_Id;
7967 Cond : Node_Id;
7968 Delay_Alt : List_Id;
7970 begin
7971 -- Deal with C/Fortran boolean as delay condition
7973 Adjust_Condition (Condition (Alt));
7975 -- Determine the smallest specified delay
7977 -- for each delay alternative generate:
7979 -- if guard-expression then
7980 -- Delay_Val := delay-expression;
7981 -- Guard_Open := True;
7982 -- if Delay_Val < Delay_Min then
7983 -- Delay_Min := Delay_Val;
7984 -- Delay_Index := Index;
7985 -- end if;
7986 -- end if;
7988 -- The enclosing if-statement is omitted if there is no guard
7990 if Delay_Count = 1
7991 or else First_Delay
7992 then
7993 First_Delay := False;
7995 Delay_Alt := New_List (
7996 Make_Assignment_Statement (Loc,
7997 Name => New_Reference_To (Delay_Min, Loc),
7998 Expression => Expression (Delay_Statement (Alt))));
8000 if Delay_Count > 1 then
8001 Append_To (Delay_Alt,
8002 Make_Assignment_Statement (Loc,
8003 Name => New_Reference_To (Delay_Index, Loc),
8004 Expression => Make_Integer_Literal (Loc, Index)));
8005 end if;
8007 else
8008 Delay_Alt := New_List (
8009 Make_Assignment_Statement (Loc,
8010 Name => New_Reference_To (Delay_Val, Loc),
8011 Expression => Expression (Delay_Statement (Alt))));
8013 if Time_Type = Standard_Duration then
8014 Cond :=
8015 Make_Op_Lt (Loc,
8016 Left_Opnd => New_Reference_To (Delay_Val, Loc),
8017 Right_Opnd => New_Reference_To (Delay_Min, Loc));
8019 else
8020 -- The scope of the time type must define a comparison
8021 -- operator. The scope itself may not be visible, so we
8022 -- construct a node with entity information to insure that
8023 -- semantic analysis can find the proper operator.
8025 Cond :=
8026 Make_Function_Call (Loc,
8027 Name => Make_Selected_Component (Loc,
8028 Prefix => New_Reference_To (Scope (Time_Type), Loc),
8029 Selector_Name =>
8030 Make_Operator_Symbol (Loc,
8031 Chars => Name_Op_Lt,
8032 Strval => No_String)),
8033 Parameter_Associations =>
8034 New_List (
8035 New_Reference_To (Delay_Val, Loc),
8036 New_Reference_To (Delay_Min, Loc)));
8038 Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
8039 end if;
8041 Append_To (Delay_Alt,
8042 Make_Implicit_If_Statement (N,
8043 Condition => Cond,
8044 Then_Statements => New_List (
8045 Make_Assignment_Statement (Loc,
8046 Name => New_Reference_To (Delay_Min, Loc),
8047 Expression => New_Reference_To (Delay_Val, Loc)),
8049 Make_Assignment_Statement (Loc,
8050 Name => New_Reference_To (Delay_Index, Loc),
8051 Expression => Make_Integer_Literal (Loc, Index)))));
8052 end if;
8054 if Check_Guard then
8055 Append_To (Delay_Alt,
8056 Make_Assignment_Statement (Loc,
8057 Name => New_Reference_To (Guard_Open, Loc),
8058 Expression => New_Reference_To (Standard_True, Loc)));
8059 end if;
8061 if Present (Condition (Alt)) then
8062 Delay_Alt := New_List (
8063 Make_Implicit_If_Statement (N,
8064 Condition => Condition (Alt),
8065 Then_Statements => Delay_Alt));
8066 end if;
8068 Append_List (Delay_Alt, Delay_List);
8070 -- If the delay alternative has a statement part, add a
8071 -- choice to the case statements for delays.
8073 if Present (Statements (Alt)) then
8075 if Delay_Count = 1 then
8076 Append_List (Statements (Alt), Delay_Alt_List);
8078 else
8079 Choices := New_List (
8080 Make_Integer_Literal (Loc, Index));
8082 Append_To (Delay_Alt_List,
8083 Make_Case_Statement_Alternative (Loc,
8084 Discrete_Choices => Choices,
8085 Statements => Statements (Alt)));
8086 end if;
8088 elsif Delay_Count = 1 then
8090 -- If the single delay has no trailing statements, add a branch
8091 -- to the exit label to the selective wait.
8093 Delay_Alt_List := New_List (
8094 Make_Goto_Statement (Loc,
8095 Name => New_Copy (Identifier (End_Lab))));
8097 end if;
8098 end Process_Delay_Alternative;
8100 -- Start of processing for Expand_N_Selective_Accept
8102 begin
8103 -- First insert some declarations before the select. The first is:
8105 -- Ann : Address
8107 -- This variable holds the parameters passed to the accept body. This
8108 -- declaration has already been inserted by the time we get here by
8109 -- a call to Expand_Accept_Declarations made from the semantics when
8110 -- processing the first accept statement contained in the select. We
8111 -- can find this entity as Accept_Address (E), where E is any of the
8112 -- entries references by contained accept statements.
8114 -- The first step is to scan the list of Selective_Accept_Statements
8115 -- to find this entity, and also count the number of accepts, and
8116 -- determine if terminated, delay or else is present:
8118 Num_Alts := 0;
8120 Alt := First (Alts);
8121 while Present (Alt) loop
8123 if Nkind (Alt) = N_Accept_Alternative then
8124 Add_Accept (Alt);
8126 elsif Nkind (Alt) = N_Delay_Alternative then
8127 Delay_Count := Delay_Count + 1;
8129 -- If the delays are relative delays, the delay expressions have
8130 -- type Standard_Duration. Otherwise they must have some time type
8131 -- recognized by GNAT.
8133 if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
8134 Time_Type := Standard_Duration;
8135 else
8136 Time_Type := Etype (Expression (Delay_Statement (Alt)));
8138 if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
8139 or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
8140 then
8141 null;
8142 else
8143 Error_Msg_NE (
8144 "& is not a time type ('R'M 9.6(6))",
8145 Expression (Delay_Statement (Alt)), Time_Type);
8146 Time_Type := Standard_Duration;
8147 Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
8148 end if;
8149 end if;
8151 if No (Condition (Alt)) then
8153 -- This guard will always be open
8155 Check_Guard := False;
8156 end if;
8158 elsif Nkind (Alt) = N_Terminate_Alternative then
8159 Adjust_Condition (Condition (Alt));
8160 Terminate_Alt := Alt;
8161 end if;
8163 Num_Alts := Num_Alts + 1;
8164 Next (Alt);
8165 end loop;
8167 Else_Present := Present (Else_Statements (N));
8169 -- At the same time (see procedure Add_Accept) we build the accept list:
8171 -- Qnn : Accept_List (1 .. num-select) := (
8172 -- (null-body, entry-index),
8173 -- (null-body, entry-index),
8174 -- ..
8175 -- (null_body, entry-index));
8177 -- In the above declaration, null-body is True if the corresponding
8178 -- accept has no body, and false otherwise. The entry is either the
8179 -- entry index expression if there is no guard, or if a guard is
8180 -- present, then a conditional expression of the form:
8182 -- (if guard then entry-index else Null_Task_Entry)
8184 -- If a guard is statically known to be false, the entry can simply
8185 -- be omitted from the accept list.
8187 Q :=
8188 Make_Object_Declaration (Loc,
8189 Defining_Identifier => Qnam,
8190 Object_Definition =>
8191 New_Reference_To (RTE (RE_Accept_List), Loc),
8192 Aliased_Present => True,
8194 Expression =>
8195 Make_Qualified_Expression (Loc,
8196 Subtype_Mark =>
8197 New_Reference_To (RTE (RE_Accept_List), Loc),
8198 Expression =>
8199 Make_Aggregate (Loc, Expressions => Accept_List)));
8201 Append (Q, Decls);
8203 -- Then we declare the variable that holds the index for the accept
8204 -- that will be selected for service:
8206 -- Xnn : Select_Index;
8208 X :=
8209 Make_Object_Declaration (Loc,
8210 Defining_Identifier => Xnam,
8211 Object_Definition =>
8212 New_Reference_To (RTE (RE_Select_Index), Loc),
8213 Expression =>
8214 New_Reference_To (RTE (RE_No_Rendezvous), Loc));
8216 Append (X, Decls);
8218 -- After this follow procedure declarations for each accept body
8220 -- procedure Pnn is
8221 -- begin
8222 -- ...
8223 -- end;
8225 -- where the ... are statements from the corresponding procedure body.
8226 -- No parameters are involved, since the parameters are passed via Ann
8227 -- and the parameter references have already been expanded to be direct
8228 -- references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
8229 -- any embedded tasking statements (which would normally be illegal in
8230 -- procedures, have been converted to calls to the tasking runtime so
8231 -- there is no problem in putting them into procedures.
8233 -- The original accept statement has been expanded into a block in
8234 -- the same fashion as for simple accepts (see Build_Accept_Body).
8236 -- Note: we don't really need to build these procedures for the case
8237 -- where no delay statement is present, but it is just as easy to
8238 -- build them unconditionally, and not significantly inefficient,
8239 -- since if they are short they will be inlined anyway.
8241 -- The procedure declarations have been assembled in Body_List
8243 -- If delays are present, we must compute the required delay.
8244 -- We first generate the declarations:
8246 -- Delay_Index : Boolean := 0;
8247 -- Delay_Min : Some_Time_Type.Time;
8248 -- Delay_Val : Some_Time_Type.Time;
8250 -- Delay_Index will be set to the index of the minimum delay, i.e. the
8251 -- active delay that is actually chosen as the basis for the possible
8252 -- delay if an immediate rendez-vous is not possible.
8254 -- In the most common case there is a single delay statement, and this
8255 -- is handled specially.
8257 if Delay_Count > 0 then
8259 -- Generate the required declarations
8261 Delay_Val :=
8262 Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
8263 Delay_Index :=
8264 Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
8265 Delay_Min :=
8266 Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
8268 Append_To (Decls,
8269 Make_Object_Declaration (Loc,
8270 Defining_Identifier => Delay_Val,
8271 Object_Definition => New_Reference_To (Time_Type, Loc)));
8273 Append_To (Decls,
8274 Make_Object_Declaration (Loc,
8275 Defining_Identifier => Delay_Index,
8276 Object_Definition => New_Reference_To (Standard_Integer, Loc),
8277 Expression => Make_Integer_Literal (Loc, 0)));
8279 Append_To (Decls,
8280 Make_Object_Declaration (Loc,
8281 Defining_Identifier => Delay_Min,
8282 Object_Definition => New_Reference_To (Time_Type, Loc),
8283 Expression =>
8284 Unchecked_Convert_To (Time_Type,
8285 Make_Attribute_Reference (Loc,
8286 Prefix =>
8287 New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
8288 Attribute_Name => Name_Last))));
8290 -- Create Duration and Delay_Mode objects used for passing a delay
8291 -- value to RTS
8293 D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
8294 M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
8296 declare
8297 Discr : Entity_Id;
8299 begin
8300 -- Note that these values are defined in s-osprim.ads and must
8301 -- be kept in sync:
8303 -- Relative : constant := 0;
8304 -- Absolute_Calendar : constant := 1;
8305 -- Absolute_RT : constant := 2;
8307 if Time_Type = Standard_Duration then
8308 Discr := Make_Integer_Literal (Loc, 0);
8310 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
8311 Discr := Make_Integer_Literal (Loc, 1);
8313 else
8314 pragma Assert
8315 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
8316 Discr := Make_Integer_Literal (Loc, 2);
8317 end if;
8319 Append_To (Decls,
8320 Make_Object_Declaration (Loc,
8321 Defining_Identifier => D,
8322 Object_Definition =>
8323 New_Reference_To (Standard_Duration, Loc)));
8325 Append_To (Decls,
8326 Make_Object_Declaration (Loc,
8327 Defining_Identifier => M,
8328 Object_Definition =>
8329 New_Reference_To (Standard_Integer, Loc),
8330 Expression => Discr));
8331 end;
8333 if Check_Guard then
8334 Guard_Open :=
8335 Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
8337 Append_To (Decls,
8338 Make_Object_Declaration (Loc,
8339 Defining_Identifier => Guard_Open,
8340 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
8341 Expression => New_Reference_To (Standard_False, Loc)));
8342 end if;
8344 -- Delay_Count is zero, don't need M and D set (suppress warning)
8346 else
8347 M := Empty;
8348 D := Empty;
8349 end if;
8351 if Present (Terminate_Alt) then
8353 -- If the terminate alternative guard is False, use
8354 -- Simple_Mode; otherwise use Terminate_Mode.
8356 if Present (Condition (Terminate_Alt)) then
8357 Select_Mode := Make_Conditional_Expression (Loc,
8358 New_List (Condition (Terminate_Alt),
8359 New_Reference_To (RTE (RE_Terminate_Mode), Loc),
8360 New_Reference_To (RTE (RE_Simple_Mode), Loc)));
8361 else
8362 Select_Mode := New_Reference_To (RTE (RE_Terminate_Mode), Loc);
8363 end if;
8365 elsif Else_Present or Delay_Count > 0 then
8366 Select_Mode := New_Reference_To (RTE (RE_Else_Mode), Loc);
8368 else
8369 Select_Mode := New_Reference_To (RTE (RE_Simple_Mode), Loc);
8370 end if;
8372 Select_Call := Make_Select_Call (Select_Mode);
8373 Append (Select_Call, Stats);
8375 -- Now generate code to act on the result. There is an entry
8376 -- in this case for each accept statement with a non-null body,
8377 -- followed by a branch to the statements that follow the Accept.
8378 -- In the absence of delay alternatives, we generate:
8380 -- case X is
8381 -- when No_Rendezvous => -- omitted if simple mode
8382 -- goto Lab0;
8384 -- when 1 =>
8385 -- P1n;
8386 -- goto Lab1;
8388 -- when 2 =>
8389 -- P2n;
8390 -- goto Lab2;
8392 -- when others =>
8393 -- goto Exit;
8394 -- end case;
8396 -- Lab0: Else_Statements;
8397 -- goto exit;
8399 -- Lab1: Trailing_Statements1;
8400 -- goto Exit;
8402 -- Lab2: Trailing_Statements2;
8403 -- goto Exit;
8404 -- ...
8405 -- Exit:
8407 -- Generate label for common exit
8409 End_Lab := Make_And_Declare_Label (Num_Alts + 1);
8411 -- First entry is the default case, when no rendezvous is possible
8413 Choices := New_List (New_Reference_To (RTE (RE_No_Rendezvous), Loc));
8415 if Else_Present then
8417 -- If no rendezvous is possible, the else part is executed
8419 Lab := Make_And_Declare_Label (0);
8420 Alt_Stats := New_List (
8421 Make_Goto_Statement (Loc,
8422 Name => New_Copy (Identifier (Lab))));
8424 Append (Lab, Trailing_List);
8425 Append_List (Else_Statements (N), Trailing_List);
8426 Append_To (Trailing_List,
8427 Make_Goto_Statement (Loc,
8428 Name => New_Copy (Identifier (End_Lab))));
8429 else
8430 Alt_Stats := New_List (
8431 Make_Goto_Statement (Loc,
8432 Name => New_Copy (Identifier (End_Lab))));
8433 end if;
8435 Append_To (Alt_List,
8436 Make_Case_Statement_Alternative (Loc,
8437 Discrete_Choices => Choices,
8438 Statements => Alt_Stats));
8440 -- We make use of the fact that Accept_Index is an integer type,
8441 -- and generate successive literals for entries for each accept.
8442 -- Only those for which there is a body or trailing statements are
8443 -- given a case entry.
8445 Alt := First (Select_Alternatives (N));
8446 Proc := First (Body_List);
8448 while Present (Alt) loop
8450 if Nkind (Alt) = N_Accept_Alternative then
8451 Process_Accept_Alternative (Alt, Index, Proc);
8452 Index := Index + 1;
8454 if Present
8455 (Handled_Statement_Sequence (Accept_Statement (Alt)))
8456 then
8457 Next (Proc);
8458 end if;
8460 elsif Nkind (Alt) = N_Delay_Alternative then
8461 Process_Delay_Alternative (Alt, Delay_Num);
8462 Delay_Num := Delay_Num + 1;
8463 end if;
8465 Next (Alt);
8466 end loop;
8468 -- An others choice is always added to the main case, as well
8469 -- as the delay case (to satisfy the compiler).
8471 Append_To (Alt_List,
8472 Make_Case_Statement_Alternative (Loc,
8473 Discrete_Choices =>
8474 New_List (Make_Others_Choice (Loc)),
8475 Statements =>
8476 New_List (Make_Goto_Statement (Loc,
8477 Name => New_Copy (Identifier (End_Lab))))));
8479 Accept_Case := New_List (
8480 Make_Case_Statement (Loc,
8481 Expression => New_Reference_To (Xnam, Loc),
8482 Alternatives => Alt_List));
8484 Append_List (Trailing_List, Accept_Case);
8485 Append (End_Lab, Accept_Case);
8486 Append_List (Body_List, Decls);
8488 -- Construct case statement for trailing statements of delay
8489 -- alternatives, if there are several of them.
8491 if Delay_Count > 1 then
8492 Append_To (Delay_Alt_List,
8493 Make_Case_Statement_Alternative (Loc,
8494 Discrete_Choices =>
8495 New_List (Make_Others_Choice (Loc)),
8496 Statements =>
8497 New_List (Make_Null_Statement (Loc))));
8499 Delay_Case := New_List (
8500 Make_Case_Statement (Loc,
8501 Expression => New_Reference_To (Delay_Index, Loc),
8502 Alternatives => Delay_Alt_List));
8503 else
8504 Delay_Case := Delay_Alt_List;
8505 end if;
8507 -- If there are no delay alternatives, we append the case statement
8508 -- to the statement list.
8510 if Delay_Count = 0 then
8511 Append_List (Accept_Case, Stats);
8513 -- Delay alternatives present
8515 else
8516 -- If delay alternatives are present we generate:
8518 -- find minimum delay.
8519 -- DX := minimum delay;
8520 -- M := <delay mode>;
8521 -- Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
8522 -- DX, MX, X);
8524 -- if X = No_Rendezvous then
8525 -- case statement for delay statements.
8526 -- else
8527 -- case statement for accept alternatives.
8528 -- end if;
8530 declare
8531 Cases : Node_Id;
8532 Stmt : Node_Id;
8533 Parms : List_Id;
8534 Parm : Node_Id;
8535 Conv : Node_Id;
8537 begin
8538 -- The type of the delay expression is known to be legal
8540 if Time_Type = Standard_Duration then
8541 Conv := New_Reference_To (Delay_Min, Loc);
8543 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
8544 Conv := Make_Function_Call (Loc,
8545 New_Reference_To (RTE (RO_CA_To_Duration), Loc),
8546 New_List (New_Reference_To (Delay_Min, Loc)));
8548 else
8549 pragma Assert
8550 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
8552 Conv := Make_Function_Call (Loc,
8553 New_Reference_To (RTE (RO_RT_To_Duration), Loc),
8554 New_List (New_Reference_To (Delay_Min, Loc)));
8555 end if;
8557 Stmt := Make_Assignment_Statement (Loc,
8558 Name => New_Reference_To (D, Loc),
8559 Expression => Conv);
8561 -- Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
8563 Parms := Parameter_Associations (Select_Call);
8564 Parm := First (Parms);
8566 while Present (Parm)
8567 and then Parm /= Select_Mode
8568 loop
8569 Next (Parm);
8570 end loop;
8572 pragma Assert (Present (Parm));
8573 Rewrite (Parm, New_Reference_To (RTE (RE_Delay_Mode), Loc));
8574 Analyze (Parm);
8576 -- Prepare two new parameters of Duration and Delay_Mode type
8577 -- which represent the value and the mode of the minimum delay.
8579 Next (Parm);
8580 Insert_After (Parm, New_Reference_To (M, Loc));
8581 Insert_After (Parm, New_Reference_To (D, Loc));
8583 -- Create a call to RTS
8585 Rewrite (Select_Call,
8586 Make_Procedure_Call_Statement (Loc,
8587 Name => New_Reference_To (RTE (RE_Timed_Selective_Wait), Loc),
8588 Parameter_Associations => Parms));
8590 -- This new call should follow the calculation of the
8591 -- minimum delay.
8593 Insert_List_Before (Select_Call, Delay_List);
8595 if Check_Guard then
8596 Stmt :=
8597 Make_Implicit_If_Statement (N,
8598 Condition => New_Reference_To (Guard_Open, Loc),
8599 Then_Statements =>
8600 New_List (New_Copy_Tree (Stmt),
8601 New_Copy_Tree (Select_Call)),
8602 Else_Statements => Accept_Or_Raise);
8603 Rewrite (Select_Call, Stmt);
8604 else
8605 Insert_Before (Select_Call, Stmt);
8606 end if;
8608 Cases :=
8609 Make_Implicit_If_Statement (N,
8610 Condition => Make_Op_Eq (Loc,
8611 Left_Opnd => New_Reference_To (Xnam, Loc),
8612 Right_Opnd =>
8613 New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
8615 Then_Statements => Delay_Case,
8616 Else_Statements => Accept_Case);
8618 Append (Cases, Stats);
8619 end;
8620 end if;
8622 -- Replace accept statement with appropriate block
8624 Block :=
8625 Make_Block_Statement (Loc,
8626 Declarations => Decls,
8627 Handled_Statement_Sequence =>
8628 Make_Handled_Sequence_Of_Statements (Loc,
8629 Statements => Stats));
8631 Rewrite (N, Block);
8632 Analyze (N);
8634 -- Note: have to worry more about abort deferral in above code ???
8636 -- Final step is to unstack the Accept_Address entries for all accept
8637 -- statements appearing in accept alternatives in the select statement
8639 Alt := First (Alts);
8640 while Present (Alt) loop
8641 if Nkind (Alt) = N_Accept_Alternative then
8642 Remove_Last_Elmt (Accept_Address
8643 (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
8644 end if;
8646 Next (Alt);
8647 end loop;
8648 end Expand_N_Selective_Accept;
8650 --------------------------------------
8651 -- Expand_N_Single_Task_Declaration --
8652 --------------------------------------
8654 -- Single task declarations should never be present after semantic
8655 -- analysis, since we expect them to be replaced by a declaration of
8656 -- an anonymous task type, followed by a declaration of the task
8657 -- object. We include this routine to make sure that is happening!
8659 procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
8660 begin
8661 raise Program_Error;
8662 end Expand_N_Single_Task_Declaration;
8664 ------------------------
8665 -- Expand_N_Task_Body --
8666 ------------------------
8668 -- Given a task body
8670 -- task body tname is
8671 -- <declarations>
8672 -- begin
8673 -- <statements>
8674 -- end x;
8676 -- This expansion routine converts it into a procedure and sets the
8677 -- elaboration flag for the procedure to true, to represent the fact
8678 -- that the task body is now elaborated:
8680 -- procedure tnameB (_Task : access tnameV) is
8681 -- discriminal : dtype renames _Task.discriminant;
8683 -- procedure _clean is
8684 -- begin
8685 -- Abort_Defer.all;
8686 -- Complete_Task;
8687 -- Abort_Undefer.all;
8688 -- return;
8689 -- end _clean;
8691 -- begin
8692 -- Abort_Undefer.all;
8693 -- <declarations>
8694 -- System.Task_Stages.Complete_Activation;
8695 -- <statements>
8696 -- at end
8697 -- _clean;
8698 -- end tnameB;
8700 -- tnameE := True;
8702 -- In addition, if the task body is an activator, then a call to
8703 -- activate tasks is added at the start of the statements, before
8704 -- the call to Complete_Activation, and if in addition the task is
8705 -- a master then it must be established as a master. These calls are
8706 -- inserted and analyzed in Expand_Cleanup_Actions, when the
8707 -- Handled_Sequence_Of_Statements is expanded.
8709 -- There is one discriminal declaration line generated for each
8710 -- discriminant that is present to provide an easy reference point
8711 -- for discriminant references inside the body (see Exp_Ch2.Expand_Name).
8713 -- Note on relationship to GNARLI definition. In the GNARLI definition,
8714 -- task body procedures have a profile (Arg : System.Address). That is
8715 -- needed because GNARLI has to use the same access-to-subprogram type
8716 -- for all task types. We depend here on knowing that in GNAT, passing
8717 -- an address argument by value is identical to passing a record value
8718 -- by access (in either case a single pointer is passed), so even though
8719 -- this procedure has the wrong profile. In fact it's all OK, since the
8720 -- callings sequence is identical.
8722 procedure Expand_N_Task_Body (N : Node_Id) is
8723 Loc : constant Source_Ptr := Sloc (N);
8724 Ttyp : constant Entity_Id := Corresponding_Spec (N);
8725 Call : Node_Id;
8726 New_N : Node_Id;
8728 begin
8729 -- Here we start the expansion by generating discriminal declarations
8731 Add_Discriminal_Declarations (Declarations (N), Ttyp, Name_uTask, Loc);
8733 -- Add a call to Abort_Undefer at the very beginning of the task
8734 -- body since this body is called with abort still deferred.
8736 if Abort_Allowed then
8737 Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
8738 Insert_Before
8739 (First (Statements (Handled_Statement_Sequence (N))), Call);
8740 Analyze (Call);
8741 end if;
8743 -- The statement part has already been protected with an at_end and
8744 -- cleanup actions. The call to Complete_Activation must be placed
8745 -- at the head of the sequence of statements of that block. The
8746 -- declarations have been merged in this sequence of statements but
8747 -- the first real statement is accessible from the First_Real_Statement
8748 -- field (which was set for exactly this purpose).
8750 if Restricted_Profile then
8751 Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
8752 else
8753 Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
8754 end if;
8756 Insert_Before
8757 (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
8758 Analyze (Call);
8760 New_N :=
8761 Make_Subprogram_Body (Loc,
8762 Specification => Build_Task_Proc_Specification (Ttyp),
8763 Declarations => Declarations (N),
8764 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
8766 -- If the task contains generic instantiations, cleanup actions
8767 -- are delayed until after instantiation. Transfer the activation
8768 -- chain to the subprogram, to insure that the activation call is
8769 -- properly generated. It the task body contains inner tasks, indicate
8770 -- that the subprogram is a task master.
8772 if Delay_Cleanups (Ttyp) then
8773 Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
8774 Set_Is_Task_Master (New_N, Is_Task_Master (N));
8775 end if;
8777 Rewrite (N, New_N);
8778 Analyze (N);
8780 -- Set elaboration flag immediately after task body. If the body
8781 -- is a subunit, the flag is set in the declarative part that
8782 -- contains the stub.
8784 if Nkind (Parent (N)) /= N_Subunit then
8785 Insert_After (N,
8786 Make_Assignment_Statement (Loc,
8787 Name =>
8788 Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
8789 Expression => New_Reference_To (Standard_True, Loc)));
8790 end if;
8792 -- Ada 2005 (AI-345): Construct the primitive entry wrapper bodies
8793 -- after the task body. At this point the entry specs have been
8794 -- created, frozen and included in the dispatch table for the task
8795 -- type.
8797 pragma Assert (Present (Corresponding_Record_Type (Ttyp)));
8799 if Ada_Version >= Ada_05
8800 and then Present (Task_Definition (Parent (Ttyp)))
8801 and then Present (Abstract_Interfaces
8802 (Corresponding_Record_Type (Ttyp)))
8803 then
8804 declare
8805 Current_Node : Node_Id;
8806 Vis_Decl : Node_Id :=
8807 First (Visible_Declarations (Task_Definition (Parent (Ttyp))));
8808 Wrap_Body : Node_Id;
8810 begin
8811 if Nkind (Parent (N)) = N_Subunit then
8812 Current_Node := Corresponding_Stub (Parent (N));
8813 else
8814 Current_Node := N;
8815 end if;
8817 -- Examine the visible declarations of the task type,
8818 -- looking for an entry declaration. We do not consider
8819 -- entry families since they can not have dispatching
8820 -- operations, thus they do not need entry wrappers.
8822 while Present (Vis_Decl) loop
8823 if Nkind (Vis_Decl) = N_Entry_Declaration
8824 and then Ekind (Defining_Identifier (Vis_Decl)) = E_Entry
8825 then
8827 -- Create the specification of the wrapper
8829 Wrap_Body :=
8830 Build_Wrapper_Body (Loc,
8831 Proc_Nam => Defining_Identifier (Vis_Decl),
8832 Obj_Typ => Corresponding_Record_Type (Ttyp),
8833 Formals => Parameter_Specifications (Vis_Decl));
8835 if Wrap_Body /= Empty then
8836 Insert_After (Current_Node, Wrap_Body);
8837 Current_Node := Wrap_Body;
8839 Analyze (Wrap_Body);
8840 end if;
8841 end if;
8843 Next (Vis_Decl);
8844 end loop;
8845 end;
8846 end if;
8847 end Expand_N_Task_Body;
8849 ------------------------------------
8850 -- Expand_N_Task_Type_Declaration --
8851 ------------------------------------
8853 -- We have several things to do. First we must create a Boolean flag used
8854 -- to mark if the body is elaborated yet. This variable gets set to True
8855 -- when the body of the task is elaborated (we can't rely on the normal
8856 -- ABE mechanism for the task body, since we need to pass an access to
8857 -- this elaboration boolean to the runtime routines).
8859 -- taskE : aliased Boolean := False;
8861 -- Next a variable is declared to hold the task stack size (either
8862 -- the default : Unspecified_Size, or a value that is set by a pragma
8863 -- Storage_Size). If the value of the pragma Storage_Size is static, then
8864 -- the variable is initialized with this value:
8866 -- taskZ : Size_Type := Unspecified_Size;
8867 -- or
8868 -- taskZ : Size_Type := Size_Type (size_expression);
8870 -- Next we create a corresponding record type declaration used to represent
8871 -- values of this task. The general form of this type declaration is
8873 -- type taskV (discriminants) is record
8874 -- _Task_Id : Task_Id;
8875 -- entry_family : array (bounds) of Void;
8876 -- _Priority : Integer := priority_expression;
8877 -- _Size : Size_Type := Size_Type (size_expression);
8878 -- _Task_Info : Task_Info_Type := task_info_expression;
8879 -- end record;
8881 -- The discriminants are present only if the corresponding task type has
8882 -- discriminants, and they exactly mirror the task type discriminants.
8884 -- The Id field is always present. It contains the Task_Id value, as
8885 -- set by the call to Create_Task. Note that although the task is
8886 -- limited, the task value record type is not limited, so there is no
8887 -- problem in passing this field as an out parameter to Create_Task.
8889 -- One entry_family component is present for each entry family in the
8890 -- task definition. The bounds correspond to the bounds of the entry
8891 -- family (which may depend on discriminants). The element type is
8892 -- void, since we only need the bounds information for determining
8893 -- the entry index. Note that the use of an anonymous array would
8894 -- normally be illegal in this context, but this is a parser check,
8895 -- and the semantics is quite prepared to handle such a case.
8897 -- The _Size field is present only if a Storage_Size pragma appears in
8898 -- the task definition. The expression captures the argument that was
8899 -- present in the pragma, and is used to override the task stack size
8900 -- otherwise associated with the task type.
8902 -- The _Priority field is present only if a Priority or Interrupt_Priority
8903 -- pragma appears in the task definition. The expression captures the
8904 -- argument that was present in the pragma, and is used to provide
8905 -- the Size parameter to the call to Create_Task.
8907 -- The _Task_Info field is present only if a Task_Info pragma appears in
8908 -- the task definition. The expression captures the argument that was
8909 -- present in the pragma, and is used to provide the Task_Image parameter
8910 -- to the call to Create_Task.
8912 -- When a task is declared, an instance of the task value record is
8913 -- created. The elaboration of this declaration creates the correct
8914 -- bounds for the entry families, and also evaluates the size, priority,
8915 -- and task_Info expressions if needed. The initialization routine for
8916 -- the task type itself then calls Create_Task with appropriate
8917 -- parameters to initialize the value of the Task_Id field.
8919 -- Note: the address of this record is passed as the "Discriminants"
8920 -- parameter for Create_Task. Since Create_Task merely passes this onto
8921 -- the body procedure, it does not matter that it does not quite match
8922 -- the GNARLI model of what is being passed (the record contains more
8923 -- than just the discriminants, but the discriminants can be found from
8924 -- the record value).
8926 -- The Entity_Id for this created record type is placed in the
8927 -- Corresponding_Record_Type field of the associated task type entity.
8929 -- Next we create a procedure specification for the task body procedure:
8931 -- procedure taskB (_Task : access taskV);
8933 -- Note that this must come after the record type declaration, since
8934 -- the spec refers to this type. It turns out that the initialization
8935 -- procedure for the value type references the task body spec, but that's
8936 -- fine, since it won't be generated till the freeze point for the type,
8937 -- which is certainly after the task body spec declaration.
8939 -- Finally, we set the task index value field of the entry attribute in
8940 -- the case of a simple entry.
8942 procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
8943 Loc : constant Source_Ptr := Sloc (N);
8944 Tasktyp : constant Entity_Id := Etype (Defining_Identifier (N));
8945 Tasknm : constant Name_Id := Chars (Tasktyp);
8946 Taskdef : constant Node_Id := Task_Definition (N);
8948 Proc_Spec : Node_Id;
8949 Rec_Decl : Node_Id;
8950 Rec_Ent : Entity_Id;
8951 Cdecls : List_Id;
8952 Elab_Decl : Node_Id;
8953 Size_Decl : Node_Id;
8954 Body_Decl : Node_Id;
8955 Task_Size : Node_Id;
8956 Ent_Stack : Entity_Id;
8957 Decl_Stack : Node_Id;
8959 begin
8960 -- If already expanded, nothing to do
8962 if Present (Corresponding_Record_Type (Tasktyp)) then
8963 return;
8964 end if;
8966 -- Here we will do the expansion
8968 Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
8970 -- Ada 2005 (AI-345): Propagate the attribute that contains the list
8971 -- of implemented interfaces.
8973 Set_Interface_List (Type_Definition (Rec_Decl), Interface_List (N));
8975 Rec_Ent := Defining_Identifier (Rec_Decl);
8976 Cdecls := Component_Items (Component_List
8977 (Type_Definition (Rec_Decl)));
8979 Qualify_Entity_Names (N);
8981 -- First create the elaboration variable
8983 Elab_Decl :=
8984 Make_Object_Declaration (Loc,
8985 Defining_Identifier =>
8986 Make_Defining_Identifier (Sloc (Tasktyp),
8987 Chars => New_External_Name (Tasknm, 'E')),
8988 Aliased_Present => True,
8989 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
8990 Expression => New_Reference_To (Standard_False, Loc));
8991 Insert_After (N, Elab_Decl);
8993 -- Next create the declaration of the size variable (tasknmZ)
8995 Set_Storage_Size_Variable (Tasktyp,
8996 Make_Defining_Identifier (Sloc (Tasktyp),
8997 Chars => New_External_Name (Tasknm, 'Z')));
8999 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) and then
9000 Is_Static_Expression (Expression (First (
9001 Pragma_Argument_Associations (Find_Task_Or_Protected_Pragma (
9002 Taskdef, Name_Storage_Size)))))
9003 then
9004 Size_Decl :=
9005 Make_Object_Declaration (Loc,
9006 Defining_Identifier => Storage_Size_Variable (Tasktyp),
9007 Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
9008 Expression =>
9009 Convert_To (RTE (RE_Size_Type),
9010 Relocate_Node (
9011 Expression (First (
9012 Pragma_Argument_Associations (
9013 Find_Task_Or_Protected_Pragma
9014 (Taskdef, Name_Storage_Size)))))));
9016 else
9017 Size_Decl :=
9018 Make_Object_Declaration (Loc,
9019 Defining_Identifier => Storage_Size_Variable (Tasktyp),
9020 Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
9021 Expression => New_Reference_To (RTE (RE_Unspecified_Size), Loc));
9022 end if;
9024 Insert_After (Elab_Decl, Size_Decl);
9026 -- Next build the rest of the corresponding record declaration.
9027 -- This is done last, since the corresponding record initialization
9028 -- procedure will reference the previously created entities.
9030 -- Fill in the component declarations -- first the _Task_Id field
9032 Append_To (Cdecls,
9033 Make_Component_Declaration (Loc,
9034 Defining_Identifier =>
9035 Make_Defining_Identifier (Loc, Name_uTask_Id),
9036 Component_Definition =>
9037 Make_Component_Definition (Loc,
9038 Aliased_Present => False,
9039 Subtype_Indication => New_Reference_To (RTE (RO_ST_Task_Id),
9040 Loc))));
9042 -- Declare static ATCB (that is, created by the expander) if we
9043 -- are using the Restricted run time.
9045 if Restricted_Profile then
9046 Append_To (Cdecls,
9047 Make_Component_Declaration (Loc,
9048 Defining_Identifier =>
9049 Make_Defining_Identifier (Loc, Name_uATCB),
9051 Component_Definition =>
9052 Make_Component_Definition (Loc,
9053 Aliased_Present => True,
9054 Subtype_Indication => Make_Subtype_Indication (Loc,
9055 Subtype_Mark => New_Occurrence_Of
9056 (RTE (RE_Ada_Task_Control_Block), Loc),
9058 Constraint =>
9059 Make_Index_Or_Discriminant_Constraint (Loc,
9060 Constraints =>
9061 New_List (Make_Integer_Literal (Loc, 0)))))));
9063 end if;
9065 -- Declare static stack (that is, created by the expander) if we
9066 -- are using the Restricted run time on a bare board configuration.
9068 if Restricted_Profile
9069 and then Preallocated_Stacks_On_Target
9070 then
9071 -- First we need to extract the appropriate stack size
9073 Ent_Stack := Make_Defining_Identifier (Loc, Name_uStack);
9075 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
9076 Task_Size := Relocate_Node (
9077 Expression (First (
9078 Pragma_Argument_Associations (
9079 Find_Task_Or_Protected_Pragma
9080 (Taskdef, Name_Storage_Size)))));
9081 else
9082 Task_Size :=
9083 New_Reference_To (RTE (RE_Default_Stack_Size), Loc);
9084 end if;
9086 Decl_Stack := Make_Component_Declaration (Loc,
9087 Defining_Identifier => Ent_Stack,
9089 Component_Definition =>
9090 Make_Component_Definition (Loc,
9091 Aliased_Present => True,
9092 Subtype_Indication => Make_Subtype_Indication (Loc,
9093 Subtype_Mark =>
9094 New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
9096 Constraint =>
9097 Make_Index_Or_Discriminant_Constraint (Loc,
9098 Constraints => New_List (Make_Range (Loc,
9099 Low_Bound => Make_Integer_Literal (Loc, 1),
9100 High_Bound => Convert_To (RTE (RE_Storage_Offset),
9101 Task_Size)))))));
9103 Append_To (Cdecls, Decl_Stack);
9105 -- The appropriate alignment for the stack is ensured by the
9106 -- run-time code in charge of task creation.
9108 end if;
9110 -- Add components for entry families
9112 Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
9114 -- Add the _Priority component if a Priority pragma is present
9116 if Present (Taskdef) and then Has_Priority_Pragma (Taskdef) then
9117 declare
9118 Prag : constant Node_Id :=
9119 Find_Task_Or_Protected_Pragma (Taskdef, Name_Priority);
9120 Expr : Node_Id;
9122 begin
9123 Expr := First (Pragma_Argument_Associations (Prag));
9125 if Nkind (Expr) = N_Pragma_Argument_Association then
9126 Expr := Expression (Expr);
9127 end if;
9129 Expr := New_Copy_Tree (Expr);
9131 -- Add conversion to proper type to do range check if required
9132 -- Note that for runtime units, we allow out of range interrupt
9133 -- priority values to be used in a priority pragma. This is for
9134 -- the benefit of some versions of System.Interrupts which use
9135 -- a special server task with maximum interrupt priority.
9137 if Chars (Prag) = Name_Priority
9138 and then not GNAT_Mode
9139 then
9140 Rewrite (Expr, Convert_To (RTE (RE_Priority), Expr));
9141 else
9142 Rewrite (Expr, Convert_To (RTE (RE_Any_Priority), Expr));
9143 end if;
9145 Append_To (Cdecls,
9146 Make_Component_Declaration (Loc,
9147 Defining_Identifier =>
9148 Make_Defining_Identifier (Loc, Name_uPriority),
9149 Component_Definition =>
9150 Make_Component_Definition (Loc,
9151 Aliased_Present => False,
9152 Subtype_Indication => New_Reference_To (Standard_Integer,
9153 Loc)),
9154 Expression => Expr));
9155 end;
9156 end if;
9158 -- Add the _Task_Size component if a Storage_Size pragma is present
9160 if Present (Taskdef)
9161 and then Has_Storage_Size_Pragma (Taskdef)
9162 then
9163 Append_To (Cdecls,
9164 Make_Component_Declaration (Loc,
9165 Defining_Identifier =>
9166 Make_Defining_Identifier (Loc, Name_uSize),
9168 Component_Definition =>
9169 Make_Component_Definition (Loc,
9170 Aliased_Present => False,
9171 Subtype_Indication => New_Reference_To (RTE (RE_Size_Type),
9172 Loc)),
9174 Expression =>
9175 Convert_To (RTE (RE_Size_Type),
9176 Relocate_Node (
9177 Expression (First (
9178 Pragma_Argument_Associations (
9179 Find_Task_Or_Protected_Pragma
9180 (Taskdef, Name_Storage_Size))))))));
9181 end if;
9183 -- Add the _Task_Info component if a Task_Info pragma is present
9185 if Present (Taskdef) and then Has_Task_Info_Pragma (Taskdef) then
9186 Append_To (Cdecls,
9187 Make_Component_Declaration (Loc,
9188 Defining_Identifier =>
9189 Make_Defining_Identifier (Loc, Name_uTask_Info),
9191 Component_Definition =>
9192 Make_Component_Definition (Loc,
9193 Aliased_Present => False,
9194 Subtype_Indication =>
9195 New_Reference_To (RTE (RE_Task_Info_Type), Loc)),
9197 Expression => New_Copy (
9198 Expression (First (
9199 Pragma_Argument_Associations (
9200 Find_Task_Or_Protected_Pragma
9201 (Taskdef, Name_Task_Info)))))));
9202 end if;
9204 Insert_After (Size_Decl, Rec_Decl);
9206 -- Analyze the record declaration immediately after construction,
9207 -- because the initialization procedure is needed for single task
9208 -- declarations before the next entity is analyzed.
9210 Analyze (Rec_Decl);
9212 -- Create the declaration of the task body procedure
9214 Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
9215 Body_Decl :=
9216 Make_Subprogram_Declaration (Loc,
9217 Specification => Proc_Spec);
9219 Insert_After (Rec_Decl, Body_Decl);
9221 -- The subprogram does not comes from source, so we have to indicate
9222 -- the need for debugging information explicitly.
9224 Set_Needs_Debug_Info
9225 (Defining_Entity (Proc_Spec), Comes_From_Source (Original_Node (N)));
9227 -- Ada 2005 (AI-345): Construct the primitive entry wrapper specs
9228 -- before the corresponding record has been frozen.
9230 if Ada_Version >= Ada_05
9231 and then Present (Taskdef)
9232 and then Present (Corresponding_Record_Type
9233 (Defining_Identifier (Parent (Taskdef))))
9234 and then Present (Abstract_Interfaces
9235 (Corresponding_Record_Type
9236 (Defining_Identifier (Parent (Taskdef)))))
9237 then
9238 declare
9239 Current_Node : Node_Id := Rec_Decl;
9240 Vis_Decl : Node_Id := First (Visible_Declarations (Taskdef));
9241 Wrap_Spec : Node_Id;
9242 New_N : Node_Id;
9244 begin
9245 -- Examine the visible declarations of the task type,
9246 -- looking for an entry declaration. We do not consider
9247 -- entry families since they can not have dispatching
9248 -- operations, thus they do not need entry wrappers.
9250 while Present (Vis_Decl) loop
9251 if Nkind (Vis_Decl) = N_Entry_Declaration
9252 and then Ekind (Defining_Identifier (Vis_Decl)) = E_Entry
9253 then
9254 Wrap_Spec :=
9255 Build_Wrapper_Spec (Loc,
9256 Proc_Nam => Defining_Identifier (Vis_Decl),
9257 Obj_Typ => Etype (Rec_Ent),
9258 Formals => Parameter_Specifications (Vis_Decl));
9260 if Wrap_Spec /= Empty then
9261 New_N :=
9262 Make_Subprogram_Declaration (Loc,
9263 Specification => Wrap_Spec);
9265 Insert_After (Current_Node, New_N);
9266 Current_Node := New_N;
9268 Analyze (New_N);
9269 end if;
9270 end if;
9272 Next (Vis_Decl);
9273 end loop;
9274 end;
9275 end if;
9277 -- Ada 2005 (AI-345): We must defer freezing to allow further
9278 -- declaration of primitive subprograms covering task interfaces
9280 if Ada_Version <= Ada_95 then
9282 -- Now we can freeze the corresponding record. This needs manually
9283 -- freezing, since it is really part of the task type, and the task
9284 -- type is frozen at this stage. We of course need the initialization
9285 -- procedure for this corresponding record type and we won't get it
9286 -- in time if we don't freeze now.
9288 declare
9289 L : constant List_Id := Freeze_Entity (Rec_Ent, Loc);
9291 begin
9292 if Is_Non_Empty_List (L) then
9293 Insert_List_After (Body_Decl, L);
9294 end if;
9295 end;
9296 end if;
9298 -- Complete the expansion of access types to the current task
9299 -- type, if any were declared.
9301 Expand_Previous_Access_Type (Tasktyp);
9302 end Expand_N_Task_Type_Declaration;
9304 -------------------------------
9305 -- Expand_N_Timed_Entry_Call --
9306 -------------------------------
9308 -- A timed entry call in normal case is not implemented using ATC
9309 -- mechanism anymore for efficiency reason.
9311 -- select
9312 -- T.E;
9313 -- S1;
9314 -- or
9315 -- Delay D;
9316 -- S2;
9317 -- end select;
9319 -- is expanded as follow:
9321 -- 1) When T.E is a task entry_call;
9323 -- declare
9324 -- B : Boolean;
9325 -- X : Task_Entry_Index := <entry index>;
9326 -- DX : Duration := To_Duration (D);
9327 -- M : Delay_Mode := <discriminant>;
9328 -- P : parms := (parm, parm, parm);
9330 -- begin
9331 -- Timed_Protected_Entry_Call (<acceptor-task>, X, P'Address,
9332 -- DX, M, B);
9333 -- if B then
9334 -- S1;
9335 -- else
9336 -- S2;
9337 -- end if;
9338 -- end;
9340 -- 2) When T.E is a protected entry_call;
9342 -- declare
9343 -- B : Boolean;
9344 -- X : Protected_Entry_Index := <entry index>;
9345 -- DX : Duration := To_Duration (D);
9346 -- M : Delay_Mode := <discriminant>;
9347 -- P : parms := (parm, parm, parm);
9349 -- begin
9350 -- Timed_Protected_Entry_Call (<object>'unchecked_access, X,
9351 -- P'Address, DX, M, B);
9352 -- if B then
9353 -- S1;
9354 -- else
9355 -- S2;
9356 -- end if;
9357 -- end;
9359 -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call;
9361 -- declare
9362 -- B : Boolean := False;
9363 -- C : Ada.Tags.Prim_Op_Kind;
9364 -- DX : Duration := To_Duration (D)
9365 -- M : Integer :=...;
9366 -- P : Parameters := (Param1 .. ParamN);
9367 -- S : constant Iteger := DT_Position (<dispatching-procedure>);
9369 -- begin
9370 -- disp_timed_select (<object>, S, P'Address, DX, M, C, B);
9372 -- if C = POK_Protected_Entry
9373 -- or else C = POK_Task_Entry
9374 -- then
9375 -- Param1 := P.Param1;
9376 -- ...
9377 -- ParamN := P.ParamN;
9378 -- end if;
9380 -- if B then
9381 -- if C = POK_Procedure
9382 -- or else C = POK_Protected_Procedure
9383 -- or else C = POK_Task_Procedure
9384 -- then
9385 -- T.E;
9386 -- end if;
9387 -- S1;
9388 -- else
9389 -- S2;
9390 -- end if;
9391 -- end;
9393 procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
9394 Loc : constant Source_Ptr := Sloc (N);
9396 E_Call : Node_Id :=
9397 Entry_Call_Statement (Entry_Call_Alternative (N));
9398 E_Stats : constant List_Id :=
9399 Statements (Entry_Call_Alternative (N));
9400 D_Stat : constant Node_Id :=
9401 Delay_Statement (Delay_Alternative (N));
9402 D_Stats : constant List_Id :=
9403 Statements (Delay_Alternative (N));
9405 Actuals : List_Id;
9406 Blk_Typ : Entity_Id;
9407 Call : Node_Id;
9408 Call_Ent : Entity_Id;
9409 Concval : Node_Id;
9410 D_Conv : Node_Id;
9411 D_Disc : Node_Id;
9412 D_Type : Entity_Id;
9413 Decls : List_Id;
9414 Dummy : Node_Id;
9415 Ename : Node_Id;
9416 Formals : List_Id;
9417 Index : Node_Id;
9418 N_Stats : List_Id;
9419 Obj : Entity_Id;
9420 Param : Node_Id;
9421 Params : List_Id;
9422 Stmt : Node_Id;
9423 Stmts : List_Id;
9425 B : Entity_Id; -- Call status flag
9426 C : Entity_Id; -- Call kind
9427 D : Entity_Id; -- Delay
9428 M : Entity_Id; -- Delay mode
9429 P : Node_Id; -- Parameter block
9430 S : Entity_Id; -- Primitive operation slot
9432 begin
9433 -- The arguments in the call may require dynamic allocation, and the
9434 -- call statement may have been transformed into a block. The block
9435 -- may contain additional declarations for internal entities, and the
9436 -- original call is found by sequential search.
9438 if Nkind (E_Call) = N_Block_Statement then
9439 E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
9440 while Nkind (E_Call) /= N_Procedure_Call_Statement
9441 and then Nkind (E_Call) /= N_Entry_Call_Statement
9442 loop
9443 Next (E_Call);
9444 end loop;
9445 end if;
9447 if Ada_Version >= Ada_05
9448 and then Nkind (E_Call) = N_Procedure_Call_Statement
9449 then
9450 Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
9452 Decls := New_List;
9453 Stmts := New_List;
9455 else
9456 -- Build an entry call using Simple_Entry_Call
9458 Extract_Entry (E_Call, Concval, Ename, Index);
9459 Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
9461 Decls := Declarations (E_Call);
9462 Stmts := Statements (Handled_Statement_Sequence (E_Call));
9464 if No (Decls) then
9465 Decls := New_List;
9466 end if;
9467 end if;
9469 -- Call status flag processing
9471 if Ada_Version >= Ada_05
9472 and then Nkind (E_Call) = N_Procedure_Call_Statement
9473 then
9474 -- Generate:
9475 -- B : Boolean := False;
9477 B := SEU.Build_B (Loc, Decls);
9479 else
9480 -- Generate:
9481 -- B : Boolean;
9483 B := Make_Defining_Identifier (Loc, Name_uB);
9485 Prepend_To (Decls,
9486 Make_Object_Declaration (Loc,
9487 Defining_Identifier =>
9489 Object_Definition =>
9490 New_Reference_To (Standard_Boolean, Loc)));
9491 end if;
9493 -- Call kind processing
9495 if Ada_Version >= Ada_05
9496 and then Nkind (E_Call) = N_Procedure_Call_Statement
9497 then
9498 -- Generate:
9499 -- C : Ada.Tags.Prim_Op_Kind;
9501 C := SEU.Build_C (Loc, Decls);
9502 end if;
9504 -- Duration and mode processing
9506 D_Type := Base_Type (Etype (Expression (D_Stat)));
9508 -- Use the type of the delay expression (Calendar or Real_Time)
9509 -- to generate the appropriate conversion.
9511 if Nkind (D_Stat) = N_Delay_Relative_Statement then
9512 D_Disc := Make_Integer_Literal (Loc, 0);
9513 D_Conv := Relocate_Node (Expression (D_Stat));
9515 elsif Is_RTE (D_Type, RO_CA_Time) then
9516 D_Disc := Make_Integer_Literal (Loc, 1);
9517 D_Conv := Make_Function_Call (Loc,
9518 New_Reference_To (RTE (RO_CA_To_Duration), Loc),
9519 New_List (New_Copy (Expression (D_Stat))));
9521 else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
9522 D_Disc := Make_Integer_Literal (Loc, 2);
9523 D_Conv := Make_Function_Call (Loc,
9524 New_Reference_To (RTE (RO_RT_To_Duration), Loc),
9525 New_List (New_Copy (Expression (D_Stat))));
9526 end if;
9528 D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
9530 -- Generate:
9531 -- D : Duration;
9533 Append_To (Decls,
9534 Make_Object_Declaration (Loc,
9535 Defining_Identifier =>
9537 Object_Definition =>
9538 New_Reference_To (Standard_Duration, Loc)));
9540 M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
9542 -- Generate:
9543 -- M : Integer := (0 | 1 | 2);
9545 Append_To (Decls,
9546 Make_Object_Declaration (Loc,
9547 Defining_Identifier =>
9549 Object_Definition =>
9550 New_Reference_To (Standard_Integer, Loc),
9551 Expression =>
9552 D_Disc));
9554 -- Do the assignement at this stage only because the evaluation of the
9555 -- expression must not occur before (see ACVC C97302A).
9557 Append_To (Stmts,
9558 Make_Assignment_Statement (Loc,
9559 Name =>
9560 New_Reference_To (D, Loc),
9561 Expression =>
9562 D_Conv));
9564 -- Parameter block processing
9566 -- Manually create the parameter block for dispatching calls. In the
9567 -- case of entries, the block has already been created during the call
9568 -- to Build_Simple_Entry_Call.
9570 if Ada_Version >= Ada_05
9571 and then Nkind (E_Call) = N_Procedure_Call_Statement
9572 then
9573 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
9574 P := Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals,
9575 Decls, Stmts);
9577 -- Dispatch table slot processing, generate:
9578 -- S : constant Integer :=
9579 -- DT_Prosition (<dispatching-procedure>)
9581 S := SEU.Build_S (Loc, Decls, Call_Ent);
9583 -- Generate:
9584 -- _dispatching_timed_select (Obj, S, P'address, D, M, C, B);
9586 -- where Obj is the controlling formal parameter, S is the dispatch
9587 -- table slot number of the dispatching operation, P is the wrapped
9588 -- parameter block, D is the duration, M is the duration mode, C is
9589 -- the call kind and B is the call status.
9591 Params := New_List;
9593 Append_To (Params, New_Copy_Tree (Obj));
9594 Append_To (Params, New_Reference_To (S, Loc));
9595 Append_To (Params, P);
9596 Append_To (Params, New_Reference_To (D, Loc));
9597 Append_To (Params, New_Reference_To (M, Loc));
9598 Append_To (Params, New_Reference_To (C, Loc));
9599 Append_To (Params, New_Reference_To (B, Loc));
9601 Append_To (Stmts,
9602 Make_Procedure_Call_Statement (Loc,
9603 Name =>
9604 Make_Identifier (Loc, Name_uDisp_Timed_Select),
9605 Parameter_Associations =>
9606 Params));
9608 -- Generate:
9609 -- if C = POK_Protected_Entry
9610 -- or else C = POK_Task_Entry
9611 -- then
9612 -- Param1 := P.Param1;
9613 -- ...
9614 -- ParamN := P.ParamN;
9615 -- end if;
9617 Append_To (Stmts,
9618 Make_If_Statement (Loc,
9620 Condition =>
9621 Make_Or_Else (Loc,
9622 Left_Opnd =>
9623 Make_Op_Eq (Loc,
9624 Left_Opnd =>
9625 New_Reference_To (C, Loc),
9626 Right_Opnd =>
9627 New_Reference_To (RTE (RE_POK_Protected_Entry), Loc)),
9628 Right_Opnd =>
9629 Make_Op_Eq (Loc,
9630 Left_Opnd =>
9631 New_Reference_To (C, Loc),
9632 Right_Opnd =>
9633 New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
9635 Then_Statements =>
9636 Parameter_Block_Unpack (Loc, Actuals, Formals)));
9638 -- Generate:
9639 -- if B then
9640 -- if C = POK_Procedure
9641 -- or else C = POK_Protected_Procedure
9642 -- or else C = POK_Task_Procedure
9643 -- then
9644 -- <dispatching-procedure-call>
9645 -- end if;
9646 -- <normal-statements>
9647 -- else
9648 -- <delay-statements>
9649 -- end if;
9651 N_Stats := New_Copy_List (E_Stats);
9653 Prepend_To (N_Stats,
9654 Make_If_Statement (Loc,
9656 Condition =>
9657 Make_Or_Else (Loc,
9658 Left_Opnd =>
9659 Make_Op_Eq (Loc,
9660 Left_Opnd =>
9661 New_Reference_To (C, Loc),
9662 Right_Opnd =>
9663 New_Reference_To (RTE (RE_POK_Procedure), Loc)),
9664 Right_Opnd =>
9665 Make_Or_Else (Loc,
9666 Left_Opnd =>
9667 Make_Op_Eq (Loc,
9668 Left_Opnd =>
9669 New_Reference_To (C, Loc),
9670 Right_Opnd =>
9671 New_Reference_To (RTE (
9672 RE_POK_Protected_Procedure), Loc)),
9673 Right_Opnd =>
9674 Make_Op_Eq (Loc,
9675 Left_Opnd =>
9676 New_Reference_To (C, Loc),
9677 Right_Opnd =>
9678 New_Reference_To (RTE (
9679 RE_POK_Task_Procedure), Loc)))),
9681 Then_Statements =>
9682 New_List (E_Call)));
9684 Append_To (Stmts,
9685 Make_If_Statement (Loc,
9686 Condition => New_Reference_To (B, Loc),
9687 Then_Statements => N_Stats,
9688 Else_Statements => D_Stats));
9689 else
9690 -- Skip assignments to temporaries created for in-out parameters.
9691 -- This makes unwarranted assumptions about the shape of the expanded
9692 -- tree for the call, and should be cleaned up ???
9694 Stmt := First (Stmts);
9695 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
9696 Next (Stmt);
9697 end loop;
9699 -- Do the assignement at this stage only because the evaluation
9700 -- of the expression must not occur before (see ACVC C97302A).
9702 Insert_Before (Stmt,
9703 Make_Assignment_Statement (Loc,
9704 Name => New_Reference_To (D, Loc),
9705 Expression => D_Conv));
9707 Call := Stmt;
9708 Params := Parameter_Associations (Call);
9710 -- For a protected type, we build a Timed_Protected_Entry_Call
9712 if Is_Protected_Type (Etype (Concval)) then
9714 -- Create a new call statement
9716 Param := First (Params);
9717 while Present (Param)
9718 and then not Is_RTE (Etype (Param), RE_Call_Modes)
9719 loop
9720 Next (Param);
9721 end loop;
9723 Dummy := Remove_Next (Next (Param));
9725 -- Remove garbage is following the Cancel_Param if present
9727 Dummy := Next (Param);
9729 -- Remove the mode of the Protected_Entry_Call call, then remove
9730 -- the Communication_Block of the Protected_Entry_Call call, and
9731 -- finally add Duration and a Delay_Mode parameter
9733 pragma Assert (Present (Param));
9734 Rewrite (Param, New_Reference_To (D, Loc));
9736 Rewrite (Dummy, New_Reference_To (M, Loc));
9738 -- Add a Boolean flag for successful entry call
9740 Append_To (Params, New_Reference_To (B, Loc));
9742 if Abort_Allowed
9743 or else Restriction_Active (No_Entry_Queue) = False
9744 or else Number_Entries (Etype (Concval)) > 1
9745 then
9746 Rewrite (Call,
9747 Make_Procedure_Call_Statement (Loc,
9748 Name =>
9749 New_Reference_To (RTE (
9750 RE_Timed_Protected_Entry_Call), Loc),
9751 Parameter_Associations => Params));
9752 else
9753 Param := First (Params);
9754 while Present (Param)
9755 and then not Is_RTE (Etype (Param), RE_Protected_Entry_Index)
9756 loop
9757 Next (Param);
9758 end loop;
9760 Remove (Param);
9762 Rewrite (Call,
9763 Make_Procedure_Call_Statement (Loc,
9764 Name => New_Reference_To (
9765 RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
9766 Parameter_Associations => Params));
9767 end if;
9769 -- For the task case, build a Timed_Task_Entry_Call
9771 else
9772 -- Create a new call statement
9774 Append_To (Params, New_Reference_To (D, Loc));
9775 Append_To (Params, New_Reference_To (M, Loc));
9776 Append_To (Params, New_Reference_To (B, Loc));
9778 Rewrite (Call,
9779 Make_Procedure_Call_Statement (Loc,
9780 Name =>
9781 New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc),
9782 Parameter_Associations => Params));
9783 end if;
9785 Append_To (Stmts,
9786 Make_Implicit_If_Statement (N,
9787 Condition => New_Reference_To (B, Loc),
9788 Then_Statements => E_Stats,
9789 Else_Statements => D_Stats));
9790 end if;
9792 Rewrite (N,
9793 Make_Block_Statement (Loc,
9794 Declarations => Decls,
9795 Handled_Statement_Sequence =>
9796 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
9798 Analyze (N);
9799 end Expand_N_Timed_Entry_Call;
9801 ----------------------------------------
9802 -- Expand_Protected_Body_Declarations --
9803 ----------------------------------------
9805 -- Part of the expansion of a protected body involves the creation of
9806 -- a declaration that can be referenced from the statement sequences of
9807 -- the entry bodies:
9809 -- A : Address;
9811 -- This declaration is inserted in the declarations of the service
9812 -- entries procedure for the protected body, and it is important that
9813 -- it be inserted before the statements of the entry body statement
9814 -- sequences are analyzed. Thus it would be too late to create this
9815 -- declaration in the Expand_N_Protected_Body routine, which is why
9816 -- there is a separate procedure to be called directly from Sem_Ch9.
9818 -- Ann is used to hold the address of the record containing the parameters
9819 -- (see Expand_N_Entry_Call for more details on how this record is built).
9820 -- References to the parameters do an unchecked conversion of this address
9821 -- to a pointer to the required record type, and then access the field that
9822 -- holds the value of the required parameter. The entity for the address
9823 -- variable is held as the top stack element (i.e. the last element) of the
9824 -- Accept_Address stack in the corresponding entry entity, and this element
9825 -- must be set in place before the statements are processed.
9827 -- No stack is needed for entry bodies, since they cannot be nested, but
9828 -- it is kept for consistency between protected and task entries. The
9829 -- stack will never contain more than one element. There is also only one
9830 -- such variable for a given protected body, but this is placed on the
9831 -- Accept_Address stack of all of the entries, again for consistency.
9833 -- To expand the requeue statement, a label is provided at the end of
9834 -- the loop in the entry service routine created by the expander (see
9835 -- Expand_N_Protected_Body for details), so that the statement can be
9836 -- skipped after the requeue is complete. This label is created during the
9837 -- expansion of the entry body, which will take place after the expansion
9838 -- of the requeue statements that it contains, so a placeholder defining
9839 -- identifier is associated with the task type here.
9841 -- Another label is provided following case statement created by the
9842 -- expander. This label is need for implementing return statement from
9843 -- entry body so that a return can be expanded as a goto to this label.
9844 -- This label is created during the expansion of the entry body, which
9845 -- will take place after the expansion of the return statements that it
9846 -- contains. Therefore, just like the label for expanding requeues, we
9847 -- need another placeholder for the label.
9849 procedure Expand_Protected_Body_Declarations
9850 (N : Node_Id;
9851 Spec_Id : Entity_Id)
9853 Op : Node_Id;
9855 begin
9856 if No_Run_Time_Mode then
9857 Error_Msg_CRT ("protected body", N);
9858 return;
9860 elsif Expander_Active then
9862 -- Associate privals with the first subprogram or entry
9863 -- body to be expanded. These are used to expand references
9864 -- to private data objects.
9866 Op := First_Protected_Operation (Declarations (N));
9868 if Present (Op) then
9869 Set_Discriminals (Parent (Spec_Id));
9870 Set_Privals (Parent (Spec_Id), Op, Sloc (N));
9871 end if;
9872 end if;
9873 end Expand_Protected_Body_Declarations;
9875 -------------------------
9876 -- External_Subprogram --
9877 -------------------------
9879 function External_Subprogram (E : Entity_Id) return Entity_Id is
9880 Subp : constant Entity_Id := Protected_Body_Subprogram (E);
9881 Decl : constant Node_Id := Unit_Declaration_Node (E);
9883 begin
9884 -- If the protected operation is defined in the visible part of the
9885 -- protected type, or if it is an interrupt handler, the internal and
9886 -- external subprograms follow each other on the entity chain. If the
9887 -- operation is defined in the private part of the type, there is no
9888 -- need for a separate locking version of the operation, and internal
9889 -- calls use the protected_body_subprogram directly.
9891 if List_Containing (Decl) = Visible_Declarations (Parent (Decl))
9892 or else Is_Interrupt_Handler (E)
9893 then
9894 return Next_Entity (Subp);
9895 else
9896 return (Subp);
9897 end if;
9898 end External_Subprogram;
9900 ------------------------------
9901 -- Extract_Dispatching_Call --
9902 ------------------------------
9904 procedure Extract_Dispatching_Call
9905 (N : Node_Id;
9906 Call_Ent : out Entity_Id;
9907 Object : out Entity_Id;
9908 Actuals : out List_Id;
9909 Formals : out List_Id)
9911 Call_Nam : Node_Id;
9913 begin
9914 pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
9916 if Present (Original_Node (N)) then
9917 Call_Nam := Name (Original_Node (N));
9918 else
9919 Call_Nam := Name (N);
9920 end if;
9922 -- Retrieve the name of the dispatching procedure. It contains the
9923 -- dispatch table slot number.
9925 loop
9926 case Nkind (Call_Nam) is
9927 when N_Identifier =>
9928 exit;
9930 when N_Selected_Component =>
9931 Call_Nam := Selector_Name (Call_Nam);
9933 when others =>
9934 raise Program_Error;
9936 end case;
9937 end loop;
9939 Actuals := Parameter_Associations (N);
9940 Call_Ent := Entity (Call_Nam);
9941 Formals := Parameter_Specifications (Parent (Call_Ent));
9942 Object := First (Actuals);
9944 if Present (Original_Node (Object)) then
9945 Object := Original_Node (Object);
9946 end if;
9947 end Extract_Dispatching_Call;
9949 -------------------
9950 -- Extract_Entry --
9951 -------------------
9953 procedure Extract_Entry
9954 (N : Node_Id;
9955 Concval : out Node_Id;
9956 Ename : out Node_Id;
9957 Index : out Node_Id)
9959 Nam : constant Node_Id := Name (N);
9961 begin
9962 -- For a simple entry, the name is a selected component, with the
9963 -- prefix being the task value, and the selector being the entry.
9965 if Nkind (Nam) = N_Selected_Component then
9966 Concval := Prefix (Nam);
9967 Ename := Selector_Name (Nam);
9968 Index := Empty;
9970 -- For a member of an entry family, the name is an indexed component
9971 -- where the prefix is a selected component, whose prefix in turn is
9972 -- the task value, and whose selector is the entry family. The single
9973 -- expression in the expressions list of the indexed component is the
9974 -- subscript for the family.
9976 else pragma Assert (Nkind (Nam) = N_Indexed_Component);
9977 Concval := Prefix (Prefix (Nam));
9978 Ename := Selector_Name (Prefix (Nam));
9979 Index := First (Expressions (Nam));
9980 end if;
9981 end Extract_Entry;
9983 -------------------
9984 -- Family_Offset --
9985 -------------------
9987 function Family_Offset
9988 (Loc : Source_Ptr;
9989 Hi : Node_Id;
9990 Lo : Node_Id;
9991 Ttyp : Entity_Id) return Node_Id
9993 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
9994 -- If one of the bounds is a reference to a discriminant, replace
9995 -- with corresponding discriminal of type. Within the body of a task
9996 -- retrieve the renamed discriminant by simple visibility, using its
9997 -- generated name. Within a protected object, find the original dis-
9998 -- criminant and replace it with the discriminal of the current prot-
9999 -- ected operation.
10001 ------------------------------
10002 -- Convert_Discriminant_Ref --
10003 ------------------------------
10005 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
10006 Loc : constant Source_Ptr := Sloc (Bound);
10007 B : Node_Id;
10008 D : Entity_Id;
10010 begin
10011 if Is_Entity_Name (Bound)
10012 and then Ekind (Entity (Bound)) = E_Discriminant
10013 then
10014 if Is_Task_Type (Ttyp)
10015 and then Has_Completion (Ttyp)
10016 then
10017 B := Make_Identifier (Loc, Chars (Entity (Bound)));
10018 Find_Direct_Name (B);
10020 elsif Is_Protected_Type (Ttyp) then
10021 D := First_Discriminant (Ttyp);
10023 while Chars (D) /= Chars (Entity (Bound)) loop
10024 Next_Discriminant (D);
10025 end loop;
10027 B := New_Reference_To (Discriminal (D), Loc);
10029 else
10030 B := New_Reference_To (Discriminal (Entity (Bound)), Loc);
10031 end if;
10033 elsif Nkind (Bound) = N_Attribute_Reference then
10034 return Bound;
10036 else
10037 B := New_Copy_Tree (Bound);
10038 end if;
10040 return
10041 Make_Attribute_Reference (Loc,
10042 Attribute_Name => Name_Pos,
10043 Prefix => New_Occurrence_Of (Etype (Bound), Loc),
10044 Expressions => New_List (B));
10045 end Convert_Discriminant_Ref;
10047 -- Start of processing for Family_Offset
10049 begin
10050 return
10051 Make_Op_Subtract (Loc,
10052 Left_Opnd => Convert_Discriminant_Ref (Hi),
10053 Right_Opnd => Convert_Discriminant_Ref (Lo));
10054 end Family_Offset;
10056 -----------------
10057 -- Family_Size --
10058 -----------------
10060 function Family_Size
10061 (Loc : Source_Ptr;
10062 Hi : Node_Id;
10063 Lo : Node_Id;
10064 Ttyp : Entity_Id) return Node_Id
10066 Ityp : Entity_Id;
10068 begin
10069 if Is_Task_Type (Ttyp) then
10070 Ityp := RTE (RE_Task_Entry_Index);
10071 else
10072 Ityp := RTE (RE_Protected_Entry_Index);
10073 end if;
10075 return
10076 Make_Attribute_Reference (Loc,
10077 Prefix => New_Reference_To (Ityp, Loc),
10078 Attribute_Name => Name_Max,
10079 Expressions => New_List (
10080 Make_Op_Add (Loc,
10081 Left_Opnd =>
10082 Family_Offset (Loc, Hi, Lo, Ttyp),
10083 Right_Opnd =>
10084 Make_Integer_Literal (Loc, 1)),
10085 Make_Integer_Literal (Loc, 0)));
10086 end Family_Size;
10088 -----------------------------------
10089 -- Find_Task_Or_Protected_Pragma --
10090 -----------------------------------
10092 function Find_Task_Or_Protected_Pragma
10093 (T : Node_Id;
10094 P : Name_Id) return Node_Id
10096 N : Node_Id;
10098 begin
10099 N := First (Visible_Declarations (T));
10101 while Present (N) loop
10102 if Nkind (N) = N_Pragma then
10103 if Chars (N) = P then
10104 return N;
10106 elsif P = Name_Priority
10107 and then Chars (N) = Name_Interrupt_Priority
10108 then
10109 return N;
10111 else
10112 Next (N);
10113 end if;
10115 else
10116 Next (N);
10117 end if;
10118 end loop;
10120 N := First (Private_Declarations (T));
10122 while Present (N) loop
10123 if Nkind (N) = N_Pragma then
10124 if Chars (N) = P then
10125 return N;
10127 elsif P = Name_Priority
10128 and then Chars (N) = Name_Interrupt_Priority
10129 then
10130 return N;
10132 else
10133 Next (N);
10134 end if;
10136 else
10137 Next (N);
10138 end if;
10139 end loop;
10141 raise Program_Error;
10142 end Find_Task_Or_Protected_Pragma;
10144 -------------------------------
10145 -- First_Protected_Operation --
10146 -------------------------------
10148 function First_Protected_Operation (D : List_Id) return Node_Id is
10149 First_Op : Node_Id;
10151 begin
10152 First_Op := First (D);
10153 while Present (First_Op)
10154 and then Nkind (First_Op) /= N_Subprogram_Body
10155 and then Nkind (First_Op) /= N_Entry_Body
10156 loop
10157 Next (First_Op);
10158 end loop;
10160 return First_Op;
10161 end First_Protected_Operation;
10163 --------------------------------
10164 -- Index_Constant_Declaration --
10165 --------------------------------
10167 function Index_Constant_Declaration
10168 (N : Node_Id;
10169 Index_Id : Entity_Id;
10170 Prot : Entity_Id) return List_Id
10172 Loc : constant Source_Ptr := Sloc (N);
10173 Decls : constant List_Id := New_List;
10174 Index_Con : constant Entity_Id := Entry_Index_Constant (Index_Id);
10175 Index_Typ : Entity_Id;
10177 Hi : Node_Id := Type_High_Bound (Etype (Index_Id));
10178 Lo : Node_Id := Type_Low_Bound (Etype (Index_Id));
10180 function Replace_Discriminant (Bound : Node_Id) return Node_Id;
10181 -- The bounds of the entry index may depend on discriminants, so
10182 -- each declaration of an entry_index_constant must have its own
10183 -- subtype declaration, using the local renaming of the object discri-
10184 -- minant.
10186 --------------------------
10187 -- Replace_Discriminant --
10188 --------------------------
10190 function Replace_Discriminant (Bound : Node_Id) return Node_Id is
10191 begin
10192 if Nkind (Bound) = N_Identifier
10193 and then Ekind (Entity (Bound)) = E_Constant
10194 and then Present (Discriminal_Link (Entity (Bound)))
10195 then
10196 return Make_Identifier (Loc, Chars (Entity (Bound)));
10197 else
10198 return Duplicate_Subexpr (Bound);
10199 end if;
10200 end Replace_Discriminant;
10202 -- Start of processing for Index_Constant_Declaration
10204 begin
10205 Set_Discriminal_Link (Index_Con, Index_Id);
10207 if Is_Entity_Name (
10208 Original_Node (Discrete_Subtype_Definition (Parent (Index_Id))))
10209 then
10210 -- Simple case: entry family is given by a subtype mark, and index
10211 -- constant has the same type, no replacement needed.
10213 Index_Typ := Etype (Index_Id);
10215 else
10216 Hi := Replace_Discriminant (Hi);
10217 Lo := Replace_Discriminant (Lo);
10219 Index_Typ := Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
10221 Append (
10222 Make_Subtype_Declaration (Loc,
10223 Defining_Identifier => Index_Typ,
10224 Subtype_Indication =>
10225 Make_Subtype_Indication (Loc,
10226 Subtype_Mark =>
10227 New_Occurrence_Of (Base_Type (Etype (Index_Id)), Loc),
10228 Constraint =>
10229 Make_Range_Constraint (Loc,
10230 Range_Expression => Make_Range (Loc, Lo, Hi)))),
10231 Decls);
10233 end if;
10235 Append (
10236 Make_Object_Declaration (Loc,
10237 Defining_Identifier => Index_Con,
10238 Constant_Present => True,
10239 Object_Definition => New_Occurrence_Of (Index_Typ, Loc),
10241 Expression =>
10242 Make_Attribute_Reference (Loc,
10243 Prefix => New_Reference_To (Index_Typ, Loc),
10244 Attribute_Name => Name_Val,
10246 Expressions => New_List (
10248 Make_Op_Add (Loc,
10249 Left_Opnd =>
10250 Make_Op_Subtract (Loc,
10251 Left_Opnd => Make_Identifier (Loc, Name_uE),
10252 Right_Opnd =>
10253 Entry_Index_Expression (Loc,
10254 Defining_Identifier (N), Empty, Prot)),
10256 Right_Opnd =>
10257 Make_Attribute_Reference (Loc,
10258 Prefix => New_Reference_To (Index_Typ, Loc),
10259 Attribute_Name => Name_Pos,
10260 Expressions => New_List (
10261 Make_Attribute_Reference (Loc,
10262 Prefix => New_Reference_To (Index_Typ, Loc),
10263 Attribute_Name => Name_First))))))),
10264 Decls);
10266 return Decls;
10267 end Index_Constant_Declaration;
10269 --------------------------------
10270 -- Make_Initialize_Protection --
10271 --------------------------------
10273 function Make_Initialize_Protection
10274 (Protect_Rec : Entity_Id) return List_Id
10276 Loc : constant Source_Ptr := Sloc (Protect_Rec);
10277 P_Arr : Entity_Id;
10278 Pdef : Node_Id;
10279 Pdec : Node_Id;
10280 Ptyp : constant Node_Id :=
10281 Corresponding_Concurrent_Type (Protect_Rec);
10282 Args : List_Id;
10283 L : constant List_Id := New_List;
10284 Has_Entry : constant Boolean := Has_Entries (Ptyp);
10285 Restricted : constant Boolean := Restricted_Profile;
10287 begin
10288 -- We may need two calls to properly initialize the object, one
10289 -- to Initialize_Protection, and possibly one to Install_Handlers
10290 -- if we have a pragma Attach_Handler.
10292 -- Get protected declaration. In the case of a task type declaration,
10293 -- this is simply the parent of the protected type entity.
10294 -- In the single protected object
10295 -- declaration, this parent will be the implicit type, and we can find
10296 -- the corresponding single protected object declaration by
10297 -- searching forward in the declaration list in the tree.
10298 -- ??? I am not sure that the test for N_Single_Protected_Declaration
10299 -- is needed here. Nodes of this type should have been removed
10300 -- during semantic analysis.
10302 Pdec := Parent (Ptyp);
10304 while Nkind (Pdec) /= N_Protected_Type_Declaration
10305 and then Nkind (Pdec) /= N_Single_Protected_Declaration
10306 loop
10307 Next (Pdec);
10308 end loop;
10310 -- Now we can find the object definition from this declaration
10312 Pdef := Protected_Definition (Pdec);
10314 -- Build the parameter list for the call. Note that _Init is the name
10315 -- of the formal for the object to be initialized, which is the task
10316 -- value record itself.
10318 Args := New_List;
10320 -- Object parameter. This is a pointer to the object of type
10321 -- Protection used by the GNARL to control the protected object.
10323 Append_To (Args,
10324 Make_Attribute_Reference (Loc,
10325 Prefix =>
10326 Make_Selected_Component (Loc,
10327 Prefix => Make_Identifier (Loc, Name_uInit),
10328 Selector_Name => Make_Identifier (Loc, Name_uObject)),
10329 Attribute_Name => Name_Unchecked_Access));
10331 -- Priority parameter. Set to Unspecified_Priority unless there is a
10332 -- priority pragma, in which case we take the value from the pragma,
10333 -- or there is an interrupt pragma and no priority pragma, and we
10334 -- set the ceiling to Interrupt_Priority'Last, an implementation-
10335 -- defined value, see D.3(10).
10337 if Present (Pdef)
10338 and then Has_Priority_Pragma (Pdef)
10339 then
10340 Append_To (Args,
10341 Duplicate_Subexpr_No_Checks
10342 (Expression
10343 (First
10344 (Pragma_Argument_Associations
10345 (Find_Task_Or_Protected_Pragma (Pdef, Name_Priority))))));
10347 elsif Has_Interrupt_Handler (Ptyp)
10348 or else Has_Attach_Handler (Ptyp)
10349 then
10350 -- When no priority is specified but an xx_Handler pragma is,
10351 -- we default to System.Interrupts.Default_Interrupt_Priority,
10352 -- see D.3(10).
10354 Append_To (Args,
10355 New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
10357 else
10358 Append_To (Args,
10359 New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
10360 end if;
10362 if Has_Entry
10363 or else Has_Interrupt_Handler (Ptyp)
10364 or else Has_Attach_Handler (Ptyp)
10365 or else (Ada_Version >= Ada_05
10366 and then Present (Interface_List (Parent (Ptyp))))
10367 then
10368 -- Compiler_Info parameter. This parameter allows entry body
10369 -- procedures and barrier functions to be called from the runtime.
10370 -- It is a pointer to the record generated by the compiler to
10371 -- represent the protected object.
10373 if Has_Entry or else not Restricted then
10374 Append_To (Args,
10375 Make_Attribute_Reference (Loc,
10376 Prefix => Make_Identifier (Loc, Name_uInit),
10377 Attribute_Name => Name_Address));
10378 end if;
10380 if Has_Entry then
10381 -- Entry_Bodies parameter. This is a pointer to an array of
10382 -- pointers to the entry body procedures and barrier functions
10383 -- of the object. If the protected type has no entries this
10384 -- object will not exist; in this case, pass a null.
10386 P_Arr := Entry_Bodies_Array (Ptyp);
10388 Append_To (Args,
10389 Make_Attribute_Reference (Loc,
10390 Prefix => New_Reference_To (P_Arr, Loc),
10391 Attribute_Name => Name_Unrestricted_Access));
10393 if Abort_Allowed
10394 or else Restriction_Active (No_Entry_Queue) = False
10395 or else Number_Entries (Ptyp) > 1
10396 then
10397 -- Find index mapping function (clumsy but ok for now)
10399 while Ekind (P_Arr) /= E_Function loop
10400 Next_Entity (P_Arr);
10401 end loop;
10403 Append_To (Args,
10404 Make_Attribute_Reference (Loc,
10405 Prefix =>
10406 New_Reference_To (P_Arr, Loc),
10407 Attribute_Name => Name_Unrestricted_Access));
10408 end if;
10410 elsif not Restricted then
10411 Append_To (Args, Make_Null (Loc));
10412 Append_To (Args, Make_Null (Loc));
10413 end if;
10415 if Abort_Allowed
10416 or else Restriction_Active (No_Entry_Queue) = False
10417 or else Number_Entries (Ptyp) > 1
10418 then
10419 Append_To (L,
10420 Make_Procedure_Call_Statement (Loc,
10421 Name => New_Reference_To (
10422 RTE (RE_Initialize_Protection_Entries), Loc),
10423 Parameter_Associations => Args));
10425 elsif not Has_Entry and then Restricted then
10426 Append_To (L,
10427 Make_Procedure_Call_Statement (Loc,
10428 Name => New_Reference_To (
10429 RTE (RE_Initialize_Protection), Loc),
10430 Parameter_Associations => Args));
10432 else
10433 Append_To (L,
10434 Make_Procedure_Call_Statement (Loc,
10435 Name => New_Reference_To (
10436 RTE (RE_Initialize_Protection_Entry), Loc),
10437 Parameter_Associations => Args));
10438 end if;
10440 else
10441 Append_To (L,
10442 Make_Procedure_Call_Statement (Loc,
10443 Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
10444 Parameter_Associations => Args));
10445 end if;
10447 if Has_Attach_Handler (Ptyp) then
10449 -- We have a list of N Attach_Handler (ProcI, ExprI),
10450 -- and we have to make the following call:
10451 -- Install_Handlers (_object,
10452 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
10453 -- or, in the case of Ravenscar:
10454 -- Install_Handlers
10455 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
10457 declare
10458 Args : constant List_Id := New_List;
10459 Table : constant List_Id := New_List;
10460 Ritem : Node_Id := First_Rep_Item (Ptyp);
10462 begin
10463 if not Restricted then
10464 -- Appends the _object argument
10466 Append_To (Args,
10467 Make_Attribute_Reference (Loc,
10468 Prefix =>
10469 Make_Selected_Component (Loc,
10470 Prefix => Make_Identifier (Loc, Name_uInit),
10471 Selector_Name => Make_Identifier (Loc, Name_uObject)),
10472 Attribute_Name => Name_Unchecked_Access));
10473 end if;
10475 -- Build the Attach_Handler table argument
10477 while Present (Ritem) loop
10478 if Nkind (Ritem) = N_Pragma
10479 and then Chars (Ritem) = Name_Attach_Handler
10480 then
10481 declare
10482 Handler : constant Node_Id :=
10483 First (Pragma_Argument_Associations (Ritem));
10485 Interrupt : constant Node_Id := Next (Handler);
10486 Expr : constant Node_Id := Expression (Interrupt);
10488 begin
10489 Append_To (Table,
10490 Make_Aggregate (Loc, Expressions => New_List (
10491 Unchecked_Convert_To
10492 (RTE (RE_System_Interrupt_Id), Expr),
10493 Make_Attribute_Reference (Loc,
10494 Prefix => Make_Selected_Component (Loc,
10495 Make_Identifier (Loc, Name_uInit),
10496 Duplicate_Subexpr_No_Checks
10497 (Expression (Handler))),
10498 Attribute_Name => Name_Access))));
10499 end;
10500 end if;
10502 Next_Rep_Item (Ritem);
10503 end loop;
10505 -- Append the table argument we just built
10507 Append_To (Args, Make_Aggregate (Loc, Table));
10509 -- Append the Install_Handler call to the statements
10511 Append_To (L,
10512 Make_Procedure_Call_Statement (Loc,
10513 Name => New_Reference_To (RTE (RE_Install_Handlers), Loc),
10514 Parameter_Associations => Args));
10515 end;
10516 end if;
10518 return L;
10519 end Make_Initialize_Protection;
10521 ---------------------------
10522 -- Make_Task_Create_Call --
10523 ---------------------------
10525 function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
10526 Loc : constant Source_Ptr := Sloc (Task_Rec);
10527 Name : Node_Id;
10528 Tdef : Node_Id;
10529 Tdec : Node_Id;
10530 Ttyp : Node_Id;
10531 Tnam : Name_Id;
10532 Args : List_Id;
10533 Ecount : Node_Id;
10535 begin
10536 Ttyp := Corresponding_Concurrent_Type (Task_Rec);
10537 Tnam := Chars (Ttyp);
10539 -- Get task declaration. In the case of a task type declaration, this
10540 -- is simply the parent of the task type entity. In the single task
10541 -- declaration, this parent will be the implicit type, and we can find
10542 -- the corresponding single task declaration by searching forward in
10543 -- the declaration list in the tree.
10544 -- ??? I am not sure that the test for N_Single_Task_Declaration
10545 -- is needed here. Nodes of this type should have been removed
10546 -- during semantic analysis.
10548 Tdec := Parent (Ttyp);
10550 while Nkind (Tdec) /= N_Task_Type_Declaration
10551 and then Nkind (Tdec) /= N_Single_Task_Declaration
10552 loop
10553 Next (Tdec);
10554 end loop;
10556 -- Now we can find the task definition from this declaration
10558 Tdef := Task_Definition (Tdec);
10560 -- Build the parameter list for the call. Note that _Init is the name
10561 -- of the formal for the object to be initialized, which is the task
10562 -- value record itself.
10564 Args := New_List;
10566 -- Priority parameter. Set to Unspecified_Priority unless there is a
10567 -- priority pragma, in which case we take the value from the pragma.
10569 if Present (Tdef) and then Has_Priority_Pragma (Tdef) then
10570 Append_To (Args,
10571 Make_Selected_Component (Loc,
10572 Prefix => Make_Identifier (Loc, Name_uInit),
10573 Selector_Name => Make_Identifier (Loc, Name_uPriority)));
10574 else
10575 Append_To (Args,
10576 New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
10577 end if;
10579 -- Optional Stack parameter
10581 if Restricted_Profile then
10583 -- If the stack has been preallocated by the expander then
10584 -- pass its address. Otherwise, pass a null address.
10586 if Preallocated_Stacks_On_Target then
10587 Append_To (Args,
10588 Make_Attribute_Reference (Loc,
10589 Prefix => Make_Selected_Component (Loc,
10590 Prefix => Make_Identifier (Loc, Name_uInit),
10591 Selector_Name =>
10592 Make_Identifier (Loc, Name_uStack)),
10593 Attribute_Name => Name_Address));
10595 else
10596 Append_To (Args,
10597 New_Reference_To (RTE (RE_Null_Address), Loc));
10598 end if;
10599 end if;
10601 -- Size parameter. If no Storage_Size pragma is present, then
10602 -- the size is taken from the taskZ variable for the type, which
10603 -- is either Unspecified_Size, or has been reset by the use of
10604 -- a Storage_Size attribute definition clause. If a pragma is
10605 -- present, then the size is taken from the _Size field of the
10606 -- task value record, which was set from the pragma value.
10608 if Present (Tdef)
10609 and then Has_Storage_Size_Pragma (Tdef)
10610 then
10611 Append_To (Args,
10612 Make_Selected_Component (Loc,
10613 Prefix => Make_Identifier (Loc, Name_uInit),
10614 Selector_Name => Make_Identifier (Loc, Name_uSize)));
10616 else
10617 Append_To (Args,
10618 New_Reference_To (Storage_Size_Variable (Ttyp), Loc));
10619 end if;
10621 -- Task_Info parameter. Set to Unspecified_Task_Info unless there is a
10622 -- Task_Info pragma, in which case we take the value from the pragma.
10624 if Present (Tdef)
10625 and then Has_Task_Info_Pragma (Tdef)
10626 then
10627 Append_To (Args,
10628 Make_Selected_Component (Loc,
10629 Prefix => Make_Identifier (Loc, Name_uInit),
10630 Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
10632 else
10633 Append_To (Args,
10634 New_Reference_To (RTE (RE_Unspecified_Task_Info), Loc));
10635 end if;
10637 if not Restricted_Profile then
10639 -- Number of entries. This is an expression of the form:
10641 -- n + _Init.a'Length + _Init.a'B'Length + ...
10643 -- where a,b... are the entry family names for the task definition
10645 Ecount := Build_Entry_Count_Expression (
10646 Ttyp,
10647 Component_Items (Component_List (
10648 Type_Definition (Parent (
10649 Corresponding_Record_Type (Ttyp))))),
10650 Loc);
10651 Append_To (Args, Ecount);
10653 -- Master parameter. This is a reference to the _Master parameter of
10654 -- the initialization procedure, except in the case of the pragma
10655 -- Restrictions (No_Task_Hierarchy) where the value is fixed to 3.
10656 -- See comments in System.Tasking.Initialization.Init_RTS for the
10657 -- value 3.
10659 if Restriction_Active (No_Task_Hierarchy) = False then
10660 Append_To (Args, Make_Identifier (Loc, Name_uMaster));
10661 else
10662 Append_To (Args, Make_Integer_Literal (Loc, 3));
10663 end if;
10664 end if;
10666 -- State parameter. This is a pointer to the task body procedure. The
10667 -- required value is obtained by taking the address of the task body
10668 -- procedure and converting it (with an unchecked conversion) to the
10669 -- type required by the task kernel. For further details, see the
10670 -- description of Expand_Task_Body
10672 Append_To (Args,
10673 Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
10674 Make_Attribute_Reference (Loc,
10675 Prefix =>
10676 New_Occurrence_Of (Get_Task_Body_Procedure (Ttyp), Loc),
10677 Attribute_Name => Name_Address)));
10679 -- Discriminants parameter. This is just the address of the task
10680 -- value record itself (which contains the discriminant values
10682 Append_To (Args,
10683 Make_Attribute_Reference (Loc,
10684 Prefix => Make_Identifier (Loc, Name_uInit),
10685 Attribute_Name => Name_Address));
10687 -- Elaborated parameter. This is an access to the elaboration Boolean
10689 Append_To (Args,
10690 Make_Attribute_Reference (Loc,
10691 Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
10692 Attribute_Name => Name_Unchecked_Access));
10694 -- Chain parameter. This is a reference to the _Chain parameter of
10695 -- the initialization procedure.
10697 Append_To (Args, Make_Identifier (Loc, Name_uChain));
10699 -- Task name parameter. Take this from the _Task_Id parameter to the
10700 -- init call unless there is a Task_Name pragma, in which case we take
10701 -- the value from the pragma.
10703 if Present (Tdef)
10704 and then Has_Task_Name_Pragma (Tdef)
10705 then
10706 Append_To (Args,
10707 New_Copy (
10708 Expression (First (
10709 Pragma_Argument_Associations (
10710 Find_Task_Or_Protected_Pragma
10711 (Tdef, Name_Task_Name))))));
10713 else
10714 Append_To (Args, Make_Identifier (Loc, Name_uTask_Name));
10715 end if;
10717 -- Created_Task parameter. This is the _Task_Id field of the task
10718 -- record value
10720 Append_To (Args,
10721 Make_Selected_Component (Loc,
10722 Prefix => Make_Identifier (Loc, Name_uInit),
10723 Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
10725 if Restricted_Profile then
10726 Name := New_Reference_To (RTE (RE_Create_Restricted_Task), Loc);
10727 else
10728 Name := New_Reference_To (RTE (RE_Create_Task), Loc);
10729 end if;
10731 return Make_Procedure_Call_Statement (Loc,
10732 Name => Name, Parameter_Associations => Args);
10733 end Make_Task_Create_Call;
10735 ------------------------------
10736 -- Next_Protected_Operation --
10737 ------------------------------
10739 function Next_Protected_Operation (N : Node_Id) return Node_Id is
10740 Next_Op : Node_Id;
10742 begin
10743 Next_Op := Next (N);
10745 while Present (Next_Op)
10746 and then Nkind (Next_Op) /= N_Subprogram_Body
10747 and then Nkind (Next_Op) /= N_Entry_Body
10748 loop
10749 Next (Next_Op);
10750 end loop;
10752 return Next_Op;
10753 end Next_Protected_Operation;
10755 --------------------------
10756 -- Parameter_Block_Pack --
10757 --------------------------
10759 function Parameter_Block_Pack
10760 (Loc : Source_Ptr;
10761 Blk_Typ : Entity_Id;
10762 Actuals : List_Id;
10763 Formals : List_Id;
10764 Decls : List_Id;
10765 Stmts : List_Id) return Node_Id
10767 Actual : Entity_Id;
10768 Blk_Nam : Node_Id;
10769 Formal : Entity_Id;
10770 Params : List_Id;
10771 Temp_Asn : Node_Id;
10772 Temp_Nam : Node_Id;
10774 begin
10775 Actual := First (Actuals);
10776 Formal := Defining_Identifier (First (Formals));
10777 Params := New_List;
10779 while Present (Actual) loop
10780 if Is_By_Copy_Type (Etype (Actual)) then
10781 -- Generate:
10782 -- Jnn : aliased <formal-type>
10784 Temp_Nam :=
10785 Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
10787 Append_To (Decls,
10788 Make_Object_Declaration (Loc,
10789 Aliased_Present =>
10790 True,
10791 Defining_Identifier =>
10792 Temp_Nam,
10793 Object_Definition =>
10794 New_Reference_To (Etype (Formal), Loc)));
10796 if Ekind (Formal) /= E_Out_Parameter then
10798 -- Generate:
10799 -- Jnn := <actual>
10801 Temp_Asn :=
10802 New_Reference_To (Temp_Nam, Loc);
10804 Set_Assignment_OK (Temp_Asn);
10806 Append_To (Stmts,
10807 Make_Assignment_Statement (Loc,
10808 Name =>
10809 Temp_Asn,
10810 Expression =>
10811 New_Copy_Tree (Actual)));
10812 end if;
10814 -- Generate:
10815 -- Jnn'unchecked_access
10817 Append_To (Params,
10818 Make_Attribute_Reference (Loc,
10819 Attribute_Name =>
10820 Name_Unchecked_Access,
10821 Prefix =>
10822 New_Reference_To (Temp_Nam, Loc)));
10823 else
10824 Append_To (Params,
10825 Make_Reference (Loc, New_Copy_Tree (Actual)));
10826 end if;
10828 Next_Actual (Actual);
10829 Next_Formal_With_Extras (Formal);
10830 end loop;
10832 -- Generate:
10833 -- P : Ann := (
10834 -- J1'unchecked_access;
10835 -- <actual2>'reference;
10836 -- ...);
10838 Blk_Nam := Make_Defining_Identifier (Loc, Name_uP);
10840 Append_To (Decls,
10841 Make_Object_Declaration (Loc,
10842 Defining_Identifier =>
10843 Blk_Nam,
10844 Object_Definition =>
10845 New_Reference_To (Blk_Typ, Loc),
10846 Expression =>
10847 Make_Aggregate (Loc, Params)));
10849 -- Return:
10850 -- P'address
10852 return
10853 Make_Attribute_Reference (Loc,
10854 Attribute_Name =>
10855 Name_Address,
10856 Prefix =>
10857 New_Reference_To (Blk_Nam, Loc));
10858 end Parameter_Block_Pack;
10860 ----------------------------
10861 -- Parameter_Block_Unpack --
10862 ----------------------------
10864 function Parameter_Block_Unpack
10865 (Loc : Source_Ptr;
10866 Actuals : List_Id;
10867 Formals : List_Id) return List_Id
10869 Actual : Entity_Id;
10870 Asnmt : Node_Id;
10871 Formal : Entity_Id;
10872 Result : constant List_Id := New_List;
10874 At_Least_One_Asnmt : Boolean := False;
10876 begin
10877 Actual := First (Actuals);
10878 Formal := Defining_Identifier (First (Formals));
10880 while Present (Actual) loop
10881 if Is_By_Copy_Type (Etype (Actual))
10882 and then Ekind (Formal) /= E_In_Parameter
10883 then
10884 At_Least_One_Asnmt := True;
10886 -- Generate:
10887 -- <actual> := P.<formal>;
10889 Asnmt :=
10890 Make_Assignment_Statement (Loc,
10891 Name =>
10892 New_Copy (Actual),
10893 Expression =>
10894 Make_Explicit_Dereference (Loc,
10895 Make_Selected_Component (Loc,
10896 Prefix =>
10897 Make_Identifier (Loc, Name_uP),
10898 Selector_Name =>
10899 Make_Identifier (Loc, Chars (Formal)))));
10901 Set_Assignment_OK (Name (Asnmt));
10903 Append_To (Result, Asnmt);
10904 end if;
10906 Next_Actual (Actual);
10907 Next_Formal_With_Extras (Formal);
10908 end loop;
10910 if At_Least_One_Asnmt then
10911 return Result;
10912 end if;
10914 return New_List (Make_Null_Statement (Loc));
10915 end Parameter_Block_Unpack;
10917 ----------------------
10918 -- Set_Discriminals --
10919 ----------------------
10921 procedure Set_Discriminals (Dec : Node_Id) is
10922 D : Entity_Id;
10923 Pdef : Entity_Id;
10924 D_Minal : Entity_Id;
10926 begin
10927 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
10928 Pdef := Defining_Identifier (Dec);
10930 if Has_Discriminants (Pdef) then
10931 D := First_Discriminant (Pdef);
10932 while Present (D) loop
10933 D_Minal :=
10934 Make_Defining_Identifier (Sloc (D),
10935 Chars => New_External_Name (Chars (D), 'D'));
10937 Set_Ekind (D_Minal, E_Constant);
10938 Set_Etype (D_Minal, Etype (D));
10939 Set_Scope (D_Minal, Pdef);
10940 Set_Discriminal (D, D_Minal);
10941 Set_Discriminal_Link (D_Minal, D);
10943 Next_Discriminant (D);
10944 end loop;
10945 end if;
10946 end Set_Discriminals;
10948 -----------------
10949 -- Set_Privals --
10950 -----------------
10952 procedure Set_Privals
10953 (Dec : Node_Id;
10954 Op : Node_Id;
10955 Loc : Source_Ptr)
10957 P_Decl : Node_Id;
10958 P_Id : Entity_Id;
10959 Priv : Entity_Id;
10960 Def : Node_Id;
10961 Body_Ent : Entity_Id;
10962 Prec_Decl : constant Node_Id :=
10963 Parent (Corresponding_Record_Type
10964 (Defining_Identifier (Dec)));
10965 Prec_Def : constant Entity_Id := Type_Definition (Prec_Decl);
10966 Obj_Decl : Node_Id;
10967 P_Subtype : Entity_Id;
10968 Assoc_L : constant Elist_Id := New_Elmt_List;
10969 Op_Id : Entity_Id;
10971 begin
10972 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
10973 pragma Assert
10974 (Nkind (Op) = N_Subprogram_Body or else Nkind (Op) = N_Entry_Body);
10976 Def := Protected_Definition (Dec);
10978 if Present (Private_Declarations (Def)) then
10980 P_Decl := First (Private_Declarations (Def));
10982 while Present (P_Decl) loop
10983 if Nkind (P_Decl) = N_Component_Declaration then
10984 P_Id := Defining_Identifier (P_Decl);
10985 Priv :=
10986 Make_Defining_Identifier (Loc,
10987 New_External_Name (Chars (P_Id), 'P'));
10989 Set_Ekind (Priv, E_Variable);
10990 Set_Etype (Priv, Etype (P_Id));
10991 Set_Scope (Priv, Scope (P_Id));
10992 Set_Esize (Priv, Esize (Etype (P_Id)));
10993 Set_Alignment (Priv, Alignment (Etype (P_Id)));
10995 -- If the type of the component is an itype, we must create a
10996 -- new itype for the corresponding prival in each protected
10997 -- operation, to avoid scoping problems. We create new itypes
10998 -- by copying the tree for the component definition.
11000 if Is_Itype (Etype (P_Id)) then
11001 Append_Elmt (P_Id, Assoc_L);
11002 Append_Elmt (Priv, Assoc_L);
11004 if Nkind (Op) = N_Entry_Body then
11005 Op_Id := Defining_Identifier (Op);
11006 else
11007 Op_Id := Defining_Unit_Name (Specification (Op));
11008 end if;
11010 Discard_Node
11011 (New_Copy_Tree (P_Decl, Assoc_L, New_Scope => Op_Id));
11012 end if;
11014 Set_Protected_Operation (P_Id, Op);
11015 Set_Prival (P_Id, Priv);
11016 end if;
11018 Next (P_Decl);
11019 end loop;
11020 end if;
11022 -- There is one more implicit private decl: the object itself. "prival"
11023 -- for this is attached to the protected body defining identifier.
11025 Body_Ent := Corresponding_Body (Dec);
11027 Priv :=
11028 Make_Defining_Identifier (Sloc (Body_Ent),
11029 Chars => New_External_Name (Chars (Body_Ent), 'R'));
11031 -- Set the Etype to the implicit subtype of Protection created when
11032 -- the protected type declaration was expanded. This node will not
11033 -- be analyzed until it is used as the defining identifier for the
11034 -- renaming declaration in the protected operation body, and it will
11035 -- be needed in the references expanded before that body is expanded.
11036 -- Since the Protection field is aliased, set Is_Aliased as well.
11038 Obj_Decl := First (Component_Items (Component_List (Prec_Def)));
11039 while Chars (Defining_Identifier (Obj_Decl)) /= Name_uObject loop
11040 Next (Obj_Decl);
11041 end loop;
11043 P_Subtype := Etype (Defining_Identifier (Obj_Decl));
11044 Set_Ekind (Priv, E_Variable);
11045 Set_Etype (Priv, P_Subtype);
11046 Set_Is_Aliased (Priv);
11047 Set_Object_Ref (Body_Ent, Priv);
11048 end Set_Privals;
11050 ----------------------------
11051 -- Update_Prival_Subtypes --
11052 ----------------------------
11054 procedure Update_Prival_Subtypes (N : Node_Id) is
11056 function Process (N : Node_Id) return Traverse_Result;
11057 -- Update the etype of occurrences of privals whose etype does not
11058 -- match the current Etype of the prival entity itself.
11060 procedure Update_Array_Bounds (E : Entity_Id);
11061 -- Itypes generated for array expressions may depend on the
11062 -- determinants of the protected object, and need to be processed
11063 -- separately because they are not attached to the tree.
11065 procedure Update_Index_Types (N : Node_Id);
11066 -- Similarly, update the types of expressions in indexed components
11067 -- which may depend on other discriminants.
11069 -------------
11070 -- Process --
11071 -------------
11073 function Process (N : Node_Id) return Traverse_Result is
11074 begin
11075 if Is_Entity_Name (N) then
11076 declare
11077 E : constant Entity_Id := Entity (N);
11079 begin
11080 if Present (E)
11081 and then (Ekind (E) = E_Constant
11082 or else Ekind (E) = E_Variable)
11083 and then Nkind (Parent (E)) = N_Object_Renaming_Declaration
11084 and then not Is_Scalar_Type (Etype (E))
11085 and then Etype (N) /= Etype (E)
11086 then
11087 Set_Etype (N, Etype (Entity (Original_Node (N))));
11088 Update_Index_Types (N);
11090 elsif Present (E)
11091 and then Ekind (E) = E_Constant
11092 and then Present (Discriminal_Link (E))
11093 then
11094 Set_Etype (N, Etype (E));
11095 end if;
11096 end;
11098 return OK;
11100 elsif Nkind (N) = N_Defining_Identifier
11101 or else Nkind (N) = N_Defining_Operator_Symbol
11102 or else Nkind (N) = N_Defining_Character_Literal
11103 then
11104 return Skip;
11106 elsif Nkind (N) = N_String_Literal then
11108 -- Array type, but bounds are constant
11110 return OK;
11112 elsif Nkind (N) = N_Object_Declaration
11113 and then Is_Itype (Etype (Defining_Identifier (N)))
11114 and then Is_Array_Type (Etype (Defining_Identifier (N)))
11115 then
11116 Update_Array_Bounds (Etype (Defining_Identifier (N)));
11117 return OK;
11119 -- For array components of discriminated records, use the base type
11120 -- directly, because it may depend indirectly on the discriminants of
11121 -- the protected type.
11123 -- Cleaner would be a systematic mechanism to compute actual subtypes
11124 -- of private components???
11126 elsif Nkind (N) in N_Has_Etype
11127 and then Present (Etype (N))
11128 and then Is_Array_Type (Etype (N))
11129 and then Nkind (N) = N_Selected_Component
11130 and then Has_Discriminants (Etype (Prefix (N)))
11131 then
11132 Set_Etype (N, Base_Type (Etype (N)));
11133 Update_Index_Types (N);
11134 return OK;
11136 else
11137 if Nkind (N) in N_Has_Etype
11138 and then Present (Etype (N))
11139 and then Is_Itype (Etype (N)) then
11141 if Is_Array_Type (Etype (N)) then
11142 Update_Array_Bounds (Etype (N));
11144 elsif Is_Scalar_Type (Etype (N)) then
11145 Update_Prival_Subtypes (Type_Low_Bound (Etype (N)));
11146 Update_Prival_Subtypes (Type_High_Bound (Etype (N)));
11147 end if;
11148 end if;
11150 return OK;
11151 end if;
11152 end Process;
11154 -------------------------
11155 -- Update_Array_Bounds --
11156 -------------------------
11158 procedure Update_Array_Bounds (E : Entity_Id) is
11159 Ind : Node_Id;
11160 begin
11161 Ind := First_Index (E);
11162 while Present (Ind) loop
11163 Update_Prival_Subtypes (Type_Low_Bound (Etype (Ind)));
11164 Update_Prival_Subtypes (Type_High_Bound (Etype (Ind)));
11165 Next_Index (Ind);
11166 end loop;
11167 end Update_Array_Bounds;
11169 ------------------------
11170 -- Update_Index_Types --
11171 ------------------------
11173 procedure Update_Index_Types (N : Node_Id) is
11174 Indx1 : Node_Id;
11175 I_Typ : Node_Id;
11177 begin
11178 -- If the prefix has an actual subtype that is different from the
11179 -- nominal one, update the types of the indices, so that the proper
11180 -- constraints are applied. Do not apply this transformation to a
11181 -- packed array, where the index type is computed for a byte array
11182 -- and is different from the source index.
11184 if Nkind (Parent (N)) = N_Indexed_Component
11185 and then
11186 not Is_Bit_Packed_Array (Etype (Prefix (Parent (N))))
11187 then
11188 Indx1 := First (Expressions (Parent (N)));
11189 I_Typ := First_Index (Etype (N));
11191 while Present (Indx1) and then Present (I_Typ) loop
11193 if not Is_Entity_Name (Indx1) then
11194 Set_Etype (Indx1, Base_Type (Etype (I_Typ)));
11195 end if;
11197 Next (Indx1);
11198 Next_Index (I_Typ);
11199 end loop;
11200 end if;
11201 end Update_Index_Types;
11203 procedure Traverse is new Traverse_Proc;
11205 -- Start of processing for Update_Prival_Subtypes
11207 begin
11208 Traverse (N);
11209 end Update_Prival_Subtypes;
11211 end Exp_Ch9;