]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/exp_ch9.adb
825bf206639423e83a87fcb16ad1cb8681137e38
[thirdparty/gcc.git] / gcc / ada / exp_ch9.adb
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-2021, 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 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Atree; use Atree;
27 with Aspects; use Aspects;
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_Ch6; use Exp_Ch6;
34 with Exp_Ch11; use Exp_Ch11;
35 with Exp_Dbug; use Exp_Dbug;
36 with Exp_Sel; use Exp_Sel;
37 with Exp_Smem; use Exp_Smem;
38 with Exp_Tss; use Exp_Tss;
39 with Exp_Util; use Exp_Util;
40 with Freeze; use Freeze;
41 with Hostparm;
42 with Itypes; use Itypes;
43 with Namet; use Namet;
44 with Nlists; use Nlists;
45 with Nmake; use Nmake;
46 with Opt; use Opt;
47 with Restrict; use Restrict;
48 with Rident; use Rident;
49 with Rtsfind; use Rtsfind;
50 with Sem; use Sem;
51 with Sem_Aux; use Sem_Aux;
52 with Sem_Ch5; use Sem_Ch5;
53 with Sem_Ch6; use Sem_Ch6;
54 with Sem_Ch8; use Sem_Ch8;
55 with Sem_Ch9; use Sem_Ch9;
56 with Sem_Ch11; use Sem_Ch11;
57 with Sem_Ch13; use Sem_Ch13;
58 with Sem_Elab; use Sem_Elab;
59 with Sem_Eval; use Sem_Eval;
60 with Sem_Res; use Sem_Res;
61 with Sem_Util; use Sem_Util;
62 with Sinfo; use Sinfo;
63 with Snames; use Snames;
64 with Stand; use Stand;
65 with Targparm; use Targparm;
66 with Tbuild; use Tbuild;
67 with Uintp; use Uintp;
68 with Validsw; use Validsw;
69
70 package body Exp_Ch9 is
71
72 -- The following constant establishes the upper bound for the index of
73 -- an entry family. It is used to limit the allocated size of protected
74 -- types with defaulted discriminant of an integer type, when the bound
75 -- of some entry family depends on a discriminant. The limitation to entry
76 -- families of 128K should be reasonable in all cases, and is a documented
77 -- implementation restriction.
78
79 Entry_Family_Bound : constant Pos := 2**16;
80
81 -----------------------
82 -- Local Subprograms --
83 -----------------------
84
85 function Actual_Index_Expression
86 (Sloc : Source_Ptr;
87 Ent : Entity_Id;
88 Index : Node_Id;
89 Tsk : Entity_Id) return Node_Id;
90 -- Compute the index position for an entry call. Tsk is the target task. If
91 -- the bounds of some entry family depend on discriminants, the expression
92 -- computed by this function uses the discriminants of the target task.
93
94 procedure Add_Object_Pointer
95 (Loc : Source_Ptr;
96 Conc_Typ : Entity_Id;
97 Decls : List_Id);
98 -- Prepend an object pointer declaration to the declaration list Decls.
99 -- This object pointer is initialized to a type conversion of the System.
100 -- Address pointer passed to entry barrier functions and entry body
101 -- procedures.
102
103 procedure Add_Formal_Renamings
104 (Spec : Node_Id;
105 Decls : List_Id;
106 Ent : Entity_Id;
107 Loc : Source_Ptr);
108 -- Create renaming declarations for the formals, inside the procedure that
109 -- implements an entry body. The renamings make the original names of the
110 -- formals accessible to gdb, and serve no other purpose.
111 -- Spec is the specification of the procedure being built.
112 -- Decls is the list of declarations to be enhanced.
113 -- Ent is the entity for the original entry body.
114
115 function Build_Accept_Body (Astat : Node_Id) return Node_Id;
116 -- Transform accept statement into a block with added exception handler.
117 -- Used both for simple accept statements and for accept alternatives in
118 -- select statements. Astat is the accept statement.
119
120 function Build_Barrier_Function
121 (N : Node_Id;
122 Ent : Entity_Id;
123 Pid : Entity_Id) return Node_Id;
124 -- Build the function body returning the value of the barrier expression
125 -- for the specified entry body.
126
127 function Build_Barrier_Function_Specification
128 (Loc : Source_Ptr;
129 Def_Id : Entity_Id) return Node_Id;
130 -- Build a specification for a function implementing the protected entry
131 -- barrier of the specified entry body.
132
133 procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id);
134 -- Build the body of a wrapper procedure for an entry or entry family that
135 -- has contract cases, preconditions, or postconditions. The body gathers
136 -- the executable contract items and expands them in the usual way, and
137 -- performs the entry call itself. This way preconditions are evaluated
138 -- before the call is queued. E is the entry in question, and Decl is the
139 -- enclosing synchronized type declaration at whose freeze point the
140 -- generated body is analyzed.
141
142 function Build_Corresponding_Record
143 (N : Node_Id;
144 Ctyp : Node_Id;
145 Loc : Source_Ptr) return Node_Id;
146 -- Common to tasks and protected types. Copy discriminant specifications,
147 -- build record declaration. N is the type declaration, Ctyp is the
148 -- concurrent entity (task type or protected type).
149
150 function Build_Dispatching_Tag_Check
151 (K : Entity_Id;
152 N : Node_Id) return Node_Id;
153 -- Utility to create the tree to check whether the dispatching call in
154 -- a timed entry call, a conditional entry call, or an asynchronous
155 -- transfer of control is a call to a primitive of a non-synchronized type.
156 -- K is the temporary that holds the tagged kind of the target object, and
157 -- N is the enclosing construct.
158
159 function Build_Entry_Count_Expression
160 (Concurrent_Type : Node_Id;
161 Component_List : List_Id;
162 Loc : Source_Ptr) return Node_Id;
163 -- Compute number of entries for concurrent object. This is a count of
164 -- simple entries, followed by an expression that computes the length
165 -- of the range of each entry family. A single array with that size is
166 -- allocated for each concurrent object of the type.
167
168 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
169 -- Build the function that translates the entry index in the call
170 -- (which depends on the size of entry families) into an index into the
171 -- Entry_Bodies_Array, to determine the body and barrier function used
172 -- in a protected entry call. A pointer to this function appears in every
173 -- protected object.
174
175 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
176 -- Build subprogram declaration for previous one
177
178 function Build_Lock_Free_Protected_Subprogram_Body
179 (N : Node_Id;
180 Prot_Typ : Node_Id;
181 Unprot_Spec : Node_Id) return Node_Id;
182 -- N denotes a subprogram body of protected type Prot_Typ. Unprot_Spec is
183 -- the subprogram specification of the unprotected version of N. Transform
184 -- N such that it invokes the unprotected version of the body.
185
186 function Build_Lock_Free_Unprotected_Subprogram_Body
187 (N : Node_Id;
188 Prot_Typ : Node_Id) return Node_Id;
189 -- N denotes a subprogram body of protected type Prot_Typ. Build a version
190 -- of N where the original statements of N are synchronized through atomic
191 -- actions such as compare and exchange. Prior to invoking this routine, it
192 -- has been established that N can be implemented in a lock-free fashion.
193
194 function Build_Parameter_Block
195 (Loc : Source_Ptr;
196 Actuals : List_Id;
197 Formals : List_Id;
198 Decls : List_Id) return Entity_Id;
199 -- Generate an access type for each actual parameter in the list Actuals.
200 -- Create an encapsulating record that contains all the actuals and return
201 -- its type. Generate:
202 -- type Ann1 is access all <actual1-type>
203 -- ...
204 -- type AnnN is access all <actualN-type>
205 -- type Pnn is record
206 -- <formal1> : Ann1;
207 -- ...
208 -- <formalN> : AnnN;
209 -- end record;
210
211 function Build_Protected_Entry
212 (N : Node_Id;
213 Ent : Entity_Id;
214 Pid : Node_Id) return Node_Id;
215 -- Build the procedure implementing the statement sequence of the specified
216 -- entry body.
217
218 function Build_Protected_Entry_Specification
219 (Loc : Source_Ptr;
220 Def_Id : Entity_Id;
221 Ent_Id : Entity_Id) return Node_Id;
222 -- Build a specification for the procedure implementing the statements of
223 -- the specified entry body. Add attributes associating it with the entry
224 -- defining identifier Ent_Id.
225
226 function Build_Protected_Spec
227 (N : Node_Id;
228 Obj_Type : Entity_Id;
229 Ident : Entity_Id;
230 Unprotected : Boolean := False) return List_Id;
231 -- Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
232 -- Subprogram_Type. Builds signature of protected subprogram, adding the
233 -- formal that corresponds to the object itself. For an access to protected
234 -- subprogram, there is no object type to specify, so the parameter has
235 -- type Address and mode In. An indirect call through such a pointer will
236 -- convert the address to a reference to the actual object. The object is
237 -- a limited record and therefore a by_reference type.
238
239 function Build_Protected_Subprogram_Body
240 (N : Node_Id;
241 Pid : Node_Id;
242 N_Op_Spec : Node_Id) return Node_Id;
243 -- This function is used to construct the protected version of a protected
244 -- subprogram. Its statement sequence first defers abort, then locks the
245 -- associated protected object, and then enters a block that contains a
246 -- call to the unprotected version of the subprogram (for details, see
247 -- Build_Unprotected_Subprogram_Body). This block statement requires a
248 -- cleanup handler that unlocks the object in all cases. For details,
249 -- see Exp_Ch7.Expand_Cleanup_Actions.
250
251 function Build_Renamed_Formal_Declaration
252 (New_F : Entity_Id;
253 Formal : Entity_Id;
254 Comp : Entity_Id;
255 Renamed_Formal : Node_Id) return Node_Id;
256 -- Create a renaming declaration for a formal, within a protected entry
257 -- body or an accept body. The renamed object is a component of the
258 -- parameter block that is a parameter in the entry call.
259 --
260 -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
261 -- does not dereference the corresponding component to prevent an illegal
262 -- use of the incomplete type (AI05-0151).
263
264 function Build_Selected_Name
265 (Prefix : Entity_Id;
266 Selector : Entity_Id;
267 Append_Char : Character := ' ') return Name_Id;
268 -- Build a name in the form of Prefix__Selector, with an optional character
269 -- appended. This is used for internal subprograms generated for operations
270 -- of protected types, including barrier functions. For the subprograms
271 -- generated for entry bodies and entry barriers, the generated name
272 -- includes a sequence number that makes names unique in the presence of
273 -- entry overloading. This is necessary because entry body procedures and
274 -- barrier functions all have the same signature.
275
276 procedure Build_Simple_Entry_Call
277 (N : Node_Id;
278 Concval : Node_Id;
279 Ename : Node_Id;
280 Index : Node_Id);
281 -- Some comments here would be useful ???
282
283 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
284 -- This routine constructs a specification for the procedure that we will
285 -- build for the task body for task type T. The spec has the form:
286 --
287 -- procedure tnameB (_Task : access tnameV);
288 --
289 -- where name is the character name taken from the task type entity that
290 -- is passed as the argument to the procedure, and tnameV is the task
291 -- value type that is associated with the task type.
292
293 function Build_Unprotected_Subprogram_Body
294 (N : Node_Id;
295 Pid : Node_Id) return Node_Id;
296 -- This routine constructs the unprotected version of a protected
297 -- subprogram body, which contains all of the code in the original,
298 -- unexpanded body. This is the version of the protected subprogram that is
299 -- called from all protected operations on the same object, including the
300 -- protected version of the same subprogram.
301
302 procedure Build_Wrapper_Bodies
303 (Loc : Source_Ptr;
304 Typ : Entity_Id;
305 N : Node_Id);
306 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
307 -- record of a concurrent type. N is the insertion node where all bodies
308 -- will be placed. This routine builds the bodies of the subprograms which
309 -- serve as an indirection mechanism to overriding primitives of concurrent
310 -- types, entries and protected procedures. Any new body is analyzed.
311
312 procedure Build_Wrapper_Specs
313 (Loc : Source_Ptr;
314 Typ : Entity_Id;
315 N : in out Node_Id);
316 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
317 -- record of a concurrent type. N is the insertion node where all specs
318 -- will be placed. This routine builds the specs of the subprograms which
319 -- serve as an indirection mechanism to overriding primitives of concurrent
320 -- types, entries and protected procedures. Any new spec is analyzed.
321
322 procedure Collect_Entry_Families
323 (Loc : Source_Ptr;
324 Cdecls : List_Id;
325 Current_Node : in out Node_Id;
326 Conctyp : Entity_Id);
327 -- For each entry family in a concurrent type, create an anonymous array
328 -- type of the right size, and add a component to the corresponding_record.
329
330 function Concurrent_Object
331 (Spec_Id : Entity_Id;
332 Conc_Typ : Entity_Id) return Entity_Id;
333 -- Given a subprogram entity Spec_Id and concurrent type Conc_Typ, return
334 -- the entity associated with the concurrent object in the Protected_Body_
335 -- Subprogram or the Task_Body_Procedure of Spec_Id. The returned entity
336 -- denotes formal parameter _O, _object or _task.
337
338 function Copy_Result_Type (Res : Node_Id) return Node_Id;
339 -- Copy the result type of a function specification, when building the
340 -- internal operation corresponding to a protected function, or when
341 -- expanding an access to protected function. If the result is an anonymous
342 -- access to subprogram itself, we need to create a new signature with the
343 -- same parameter names and the same resolved types, but with new entities
344 -- for the formals.
345
346 function Create_Secondary_Stack_For_Task (T : Node_Id) return Boolean;
347 -- Return whether a secondary stack for the task T should be created by the
348 -- expander. The secondary stack for a task will be created by the expander
349 -- if the size of the stack has been specified by the Secondary_Stack_Size
350 -- representation aspect and either the No_Implicit_Heap_Allocations or
351 -- No_Implicit_Task_Allocations restrictions are in effect and the
352 -- No_Secondary_Stack restriction is not.
353
354 procedure Debug_Private_Data_Declarations (Decls : List_Id);
355 -- Decls is a list which may contain the declarations created by Install_
356 -- Private_Data_Declarations. All generated entities are marked as needing
357 -- debug info and debug nodes are manually generation where necessary. This
358 -- step of the expansion must to be done after private data has been moved
359 -- to its final resting scope to ensure proper visibility of debug objects.
360
361 procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id);
362 -- If control flow optimizations are suppressed, and Alt is an accept,
363 -- delay, or entry call alternative with no trailing statements, insert
364 -- a null trailing statement with the given Loc (which is the sloc of
365 -- the accept, delay, or entry call statement). There might not be any
366 -- generated code for the accept, delay, or entry call itself (the effect
367 -- of these statements is part of the general processing done for the
368 -- enclosing selective accept, timed entry call, or asynchronous select),
369 -- and the null statement is there to carry the sloc of that statement to
370 -- the back-end for trace-based coverage analysis purposes.
371
372 procedure Extract_Dispatching_Call
373 (N : Node_Id;
374 Call_Ent : out Entity_Id;
375 Object : out Entity_Id;
376 Actuals : out List_Id;
377 Formals : out List_Id);
378 -- Given a dispatching call, extract the entity of the name of the call,
379 -- its actual dispatching object, its actual parameters and the formal
380 -- parameters of the overridden interface-level version. If the type of
381 -- the dispatching object is an access type then an explicit dereference
382 -- is returned in Object.
383
384 procedure Extract_Entry
385 (N : Node_Id;
386 Concval : out Node_Id;
387 Ename : out Node_Id;
388 Index : out Node_Id);
389 -- Given an entry call, returns the associated concurrent object, the entry
390 -- name, and the entry family index.
391
392 function Family_Offset
393 (Loc : Source_Ptr;
394 Hi : Node_Id;
395 Lo : Node_Id;
396 Ttyp : Entity_Id;
397 Cap : Boolean) return Node_Id;
398 -- Compute (Hi - Lo) for two entry family indexes. Hi is the index in an
399 -- accept statement, or the upper bound in the discrete subtype of an entry
400 -- declaration. Lo is the corresponding lower bound. Ttyp is the concurrent
401 -- type of the entry. If Cap is true, the result is capped according to
402 -- Entry_Family_Bound.
403
404 function Family_Size
405 (Loc : Source_Ptr;
406 Hi : Node_Id;
407 Lo : Node_Id;
408 Ttyp : Entity_Id;
409 Cap : Boolean) return Node_Id;
410 -- Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in a
411 -- family, and handle properly the superflat case. This is equivalent to
412 -- the use of 'Length on the index type, but must use Family_Offset to
413 -- handle properly the case of bounds that depend on discriminants. If
414 -- Cap is true, the result is capped according to Entry_Family_Bound.
415
416 procedure Find_Enclosing_Context
417 (N : Node_Id;
418 Context : out Node_Id;
419 Context_Id : out Entity_Id;
420 Context_Decls : out List_Id);
421 -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
422 -- Build_Master_Entity. Given an arbitrary node in the tree, find the
423 -- nearest enclosing body, block, package, or return statement and return
424 -- its constituents. Context is the enclosing construct, Context_Id is
425 -- the scope of Context_Id and Context_Decls is the declarative list of
426 -- Context.
427
428 function Index_Object (Spec_Id : Entity_Id) return Entity_Id;
429 -- Given a subprogram identifier, return the entity which is associated
430 -- with the protection entry index in the Protected_Body_Subprogram or
431 -- the Task_Body_Procedure of Spec_Id. The returned entity denotes formal
432 -- parameter _E.
433
434 function Is_Potentially_Large_Family
435 (Base_Index : Entity_Id;
436 Conctyp : Entity_Id;
437 Lo : Node_Id;
438 Hi : Node_Id) return Boolean;
439 -- Determine whether an entry family is potentially large because one of
440 -- its bounds denotes a discrminant.
441
442 function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean;
443 -- Determine whether Id is a function or a procedure and is marked as a
444 -- private primitive.
445
446 function Null_Statements (Stats : List_Id) return Boolean;
447 -- Used to check DO-END sequence. Checks for equivalent of DO NULL; END.
448 -- Allows labels, and pragma Warnings/Unreferenced in the sequence as well
449 -- to still count as null. Returns True for a null sequence. The argument
450 -- is the list of statements from the DO-END sequence.
451
452 function Parameter_Block_Pack
453 (Loc : Source_Ptr;
454 Blk_Typ : Entity_Id;
455 Actuals : List_Id;
456 Formals : List_Id;
457 Decls : List_Id;
458 Stmts : List_Id) return Entity_Id;
459 -- Set the components of the generated parameter block with the values
460 -- of the actual parameters. Generate aliased temporaries to capture the
461 -- values for types that are passed by copy. Otherwise generate a reference
462 -- to the actual's value. Return the address of the aggregate block.
463 -- Generate:
464 -- Jnn1 : alias <formal-type1>;
465 -- Jnn1 := <actual1>;
466 -- ...
467 -- P : Blk_Typ := (
468 -- Jnn1'unchecked_access;
469 -- <actual2>'reference;
470 -- ...);
471
472 function Parameter_Block_Unpack
473 (Loc : Source_Ptr;
474 P : Entity_Id;
475 Actuals : List_Id;
476 Formals : List_Id) return List_Id;
477 -- Retrieve the values of the components from the parameter block and
478 -- assign then to the original actual parameters. Generate:
479 -- <actual1> := P.<formal1>;
480 -- ...
481 -- <actualN> := P.<formalN>;
482
483 procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id);
484 -- Reset the scope of declarations and blocks at the top level of Bod to
485 -- be E. Bod is either a block or a subprogram body. Used after expanding
486 -- various kinds of entry bodies into their corresponding constructs. This
487 -- is needed during unnesting to determine whether a body generated for an
488 -- entry or an accept alternative includes uplevel references.
489
490 function Trivial_Accept_OK return Boolean;
491 -- If there is no DO-END block for an accept, or if the DO-END block has
492 -- only null statements, then it is possible to do the Rendezvous with much
493 -- less overhead using the Accept_Trivial routine in the run-time library.
494 -- However, this is not always a valid optimization. Whether it is valid or
495 -- not depends on the Task_Dispatching_Policy. The issue is whether a full
496 -- rescheduling action is required or not. In FIFO_Within_Priorities, such
497 -- a rescheduling is required, so this optimization is not allowed. This
498 -- function returns True if the optimization is permitted.
499
500 -----------------------------
501 -- Actual_Index_Expression --
502 -----------------------------
503
504 function Actual_Index_Expression
505 (Sloc : Source_Ptr;
506 Ent : Entity_Id;
507 Index : Node_Id;
508 Tsk : Entity_Id) return Node_Id
509 is
510 Ttyp : constant Entity_Id := Etype (Tsk);
511 Expr : Node_Id;
512 Num : Node_Id;
513 Lo : Node_Id;
514 Hi : Node_Id;
515 Prev : Entity_Id;
516 S : Node_Id;
517
518 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
519 -- Compute difference between bounds of entry family
520
521 --------------------------
522 -- Actual_Family_Offset --
523 --------------------------
524
525 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
526
527 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
528 -- Replace a reference to a discriminant with a selected component
529 -- denoting the discriminant of the target task.
530
531 -----------------------------
532 -- Actual_Discriminant_Ref --
533 -----------------------------
534
535 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
536 Typ : constant Entity_Id := Etype (Bound);
537 B : Node_Id;
538
539 begin
540 if not Is_Entity_Name (Bound)
541 or else Ekind (Entity (Bound)) /= E_Discriminant
542 then
543 if Nkind (Bound) = N_Attribute_Reference then
544 return Bound;
545 else
546 B := New_Copy_Tree (Bound);
547 end if;
548
549 else
550 B :=
551 Make_Selected_Component (Sloc,
552 Prefix => New_Copy_Tree (Tsk),
553 Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
554
555 Analyze_And_Resolve (B, Typ);
556 end if;
557
558 return
559 Make_Attribute_Reference (Sloc,
560 Attribute_Name => Name_Pos,
561 Prefix => New_Occurrence_Of (Etype (Bound), Sloc),
562 Expressions => New_List (B));
563 end Actual_Discriminant_Ref;
564
565 -- Start of processing for Actual_Family_Offset
566
567 begin
568 return
569 Make_Op_Subtract (Sloc,
570 Left_Opnd => Actual_Discriminant_Ref (Hi),
571 Right_Opnd => Actual_Discriminant_Ref (Lo));
572 end Actual_Family_Offset;
573
574 -- Start of processing for Actual_Index_Expression
575
576 begin
577 -- The queues of entries and entry families appear in textual order in
578 -- the associated record. The entry index is computed as the sum of the
579 -- number of queues for all entries that precede the designated one, to
580 -- which is added the index expression, if this expression denotes a
581 -- member of a family.
582
583 -- The following is a place holder for the count of simple entries
584
585 Num := Make_Integer_Literal (Sloc, 1);
586
587 -- We construct an expression which is a series of addition operations.
588 -- See comments in Entry_Index_Expression, which is identical in
589 -- structure.
590
591 if Present (Index) then
592 S := Entry_Index_Type (Ent);
593
594 -- First make sure the index is in range if requested. The index type
595 -- has been directly set on the prefix, see Resolve_Entry.
596
597 if Do_Range_Check (Index) then
598 Generate_Range_Check
599 (Index, Etype (Prefix (Parent (Index))), CE_Range_Check_Failed);
600 end if;
601
602 Expr :=
603 Make_Op_Add (Sloc,
604 Left_Opnd => Num,
605 Right_Opnd =>
606 Actual_Family_Offset (
607 Make_Attribute_Reference (Sloc,
608 Attribute_Name => Name_Pos,
609 Prefix => New_Occurrence_Of (Base_Type (S), Sloc),
610 Expressions => New_List (Relocate_Node (Index))),
611 Type_Low_Bound (S)));
612 else
613 Expr := Num;
614 end if;
615
616 -- Now add lengths of preceding entries and entry families
617
618 Prev := First_Entity (Ttyp);
619 while Chars (Prev) /= Chars (Ent)
620 or else (Ekind (Prev) /= Ekind (Ent))
621 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
622 loop
623 if Ekind (Prev) = E_Entry then
624 Set_Intval (Num, Intval (Num) + 1);
625
626 elsif Ekind (Prev) = E_Entry_Family then
627 S := Entry_Index_Type (Prev);
628
629 -- The need for the following full view retrieval stems from this
630 -- complex case of nested generics and tasking:
631
632 -- generic
633 -- type Formal_Index is range <>;
634 -- ...
635 -- package Outer is
636 -- type Index is private;
637 -- generic
638 -- ...
639 -- package Inner is
640 -- procedure P;
641 -- end Inner;
642 -- private
643 -- type Index is new Formal_Index range 1 .. 10;
644 -- end Outer;
645
646 -- package body Outer is
647 -- task type T is
648 -- entry Fam (Index); -- (2)
649 -- entry E;
650 -- end T;
651 -- package body Inner is -- (3)
652 -- procedure P is
653 -- begin
654 -- T.E; -- (1)
655 -- end P;
656 -- end Inner;
657 -- ...
658
659 -- We are currently building the index expression for the entry
660 -- call "T.E" (1). Part of the expansion must mention the range
661 -- of the discrete type "Index" (2) of entry family "Fam".
662
663 -- However only the private view of type "Index" is available to
664 -- the inner generic (3) because there was no prior mention of
665 -- the type inside "Inner". This visibility requirement is
666 -- implicit and cannot be detected during the construction of
667 -- the generic trees and needs special handling.
668
669 if In_Instance_Body
670 and then Is_Private_Type (S)
671 and then Present (Full_View (S))
672 then
673 S := Full_View (S);
674 end if;
675
676 Lo := Type_Low_Bound (S);
677 Hi := Type_High_Bound (S);
678
679 Expr :=
680 Make_Op_Add (Sloc,
681 Left_Opnd => Expr,
682 Right_Opnd =>
683 Make_Op_Add (Sloc,
684 Left_Opnd => Actual_Family_Offset (Hi, Lo),
685 Right_Opnd => Make_Integer_Literal (Sloc, 1)));
686
687 -- Other components are anonymous types to be ignored
688
689 else
690 null;
691 end if;
692
693 Next_Entity (Prev);
694 end loop;
695
696 return Expr;
697 end Actual_Index_Expression;
698
699 --------------------------
700 -- Add_Formal_Renamings --
701 --------------------------
702
703 procedure Add_Formal_Renamings
704 (Spec : Node_Id;
705 Decls : List_Id;
706 Ent : Entity_Id;
707 Loc : Source_Ptr)
708 is
709 Ptr : constant Entity_Id :=
710 Defining_Identifier
711 (Next (First (Parameter_Specifications (Spec))));
712 -- The name of the formal that holds the address of the parameter block
713 -- for the call.
714
715 Comp : Entity_Id;
716 Decl : Node_Id;
717 Formal : Entity_Id;
718 New_F : Entity_Id;
719 Renamed_Formal : Node_Id;
720
721 begin
722 Formal := First_Formal (Ent);
723 while Present (Formal) loop
724 Comp := Entry_Component (Formal);
725 New_F :=
726 Make_Defining_Identifier (Sloc (Formal),
727 Chars => Chars (Formal));
728 Set_Etype (New_F, Etype (Formal));
729 Set_Scope (New_F, Ent);
730
731 -- Now we set debug info needed on New_F even though it does not come
732 -- from source, so that the debugger will get the right information
733 -- for these generated names.
734
735 Set_Debug_Info_Needed (New_F);
736
737 if Ekind (Formal) = E_In_Parameter then
738 Set_Ekind (New_F, E_Constant);
739 else
740 Set_Ekind (New_F, E_Variable);
741 Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
742 end if;
743
744 Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
745
746 Renamed_Formal :=
747 Make_Selected_Component (Loc,
748 Prefix =>
749 Make_Explicit_Dereference (Loc,
750 Unchecked_Convert_To (Entry_Parameters_Type (Ent),
751 Make_Identifier (Loc, Chars (Ptr)))),
752 Selector_Name => New_Occurrence_Of (Comp, Loc));
753
754 Decl :=
755 Build_Renamed_Formal_Declaration
756 (New_F, Formal, Comp, Renamed_Formal);
757
758 Append (Decl, Decls);
759 Set_Renamed_Object (Formal, New_F);
760 Next_Formal (Formal);
761 end loop;
762 end Add_Formal_Renamings;
763
764 ------------------------
765 -- Add_Object_Pointer --
766 ------------------------
767
768 procedure Add_Object_Pointer
769 (Loc : Source_Ptr;
770 Conc_Typ : Entity_Id;
771 Decls : List_Id)
772 is
773 Rec_Typ : constant Entity_Id := Corresponding_Record_Type (Conc_Typ);
774 Decl : Node_Id;
775 Obj_Ptr : Node_Id;
776
777 begin
778 -- Create the renaming declaration for the Protection object of a
779 -- protected type. _Object is used by Complete_Entry_Body.
780 -- ??? An attempt to make this a renaming was unsuccessful.
781
782 -- Build the entity for the access type
783
784 Obj_Ptr :=
785 Make_Defining_Identifier (Loc,
786 New_External_Name (Chars (Rec_Typ), 'P'));
787
788 -- Generate:
789 -- _object : poVP := poVP!O;
790
791 Decl :=
792 Make_Object_Declaration (Loc,
793 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uObject),
794 Object_Definition => New_Occurrence_Of (Obj_Ptr, Loc),
795 Expression =>
796 Unchecked_Convert_To (Obj_Ptr, Make_Identifier (Loc, Name_uO)));
797 Set_Debug_Info_Needed (Defining_Identifier (Decl));
798 Prepend_To (Decls, Decl);
799
800 -- Generate:
801 -- type poVP is access poV;
802
803 Decl :=
804 Make_Full_Type_Declaration (Loc,
805 Defining_Identifier =>
806 Obj_Ptr,
807 Type_Definition =>
808 Make_Access_To_Object_Definition (Loc,
809 Subtype_Indication =>
810 New_Occurrence_Of (Rec_Typ, Loc)));
811 Set_Debug_Info_Needed (Defining_Identifier (Decl));
812 Prepend_To (Decls, Decl);
813 end Add_Object_Pointer;
814
815 -----------------------
816 -- Build_Accept_Body --
817 -----------------------
818
819 function Build_Accept_Body (Astat : Node_Id) return Node_Id is
820 Loc : constant Source_Ptr := Sloc (Astat);
821 Stats : constant Node_Id := Handled_Statement_Sequence (Astat);
822 New_S : Node_Id;
823 Hand : Node_Id;
824 Call : Node_Id;
825 Ohandle : Node_Id;
826
827 begin
828 -- At the end of the statement sequence, Complete_Rendezvous is called.
829 -- A label skipping the Complete_Rendezvous, and all other accept
830 -- processing, has already been added for the expansion of requeue
831 -- statements. The Sloc is copied from the last statement since it
832 -- is really part of this last statement.
833
834 Call :=
835 Build_Runtime_Call
836 (Sloc (Last (Statements (Stats))), RE_Complete_Rendezvous);
837 Insert_Before (Last (Statements (Stats)), Call);
838 Analyze (Call);
839
840 -- Ada 2020 (AI12-0279)
841
842 if Has_Yield_Aspect (Entity (Entry_Direct_Name (Astat)))
843 and then RTE_Available (RE_Yield)
844 then
845 Insert_Action_After (Call,
846 Make_Procedure_Call_Statement (Loc,
847 New_Occurrence_Of (RTE (RE_Yield), Loc)));
848 end if;
849
850 -- If exception handlers are present, then append Complete_Rendezvous
851 -- calls to the handlers, and construct the required outer block. As
852 -- above, the Sloc is copied from the last statement in the sequence.
853
854 if Present (Exception_Handlers (Stats)) then
855 Hand := First (Exception_Handlers (Stats));
856 while Present (Hand) loop
857 Call :=
858 Build_Runtime_Call
859 (Sloc (Last (Statements (Hand))), RE_Complete_Rendezvous);
860 Append (Call, Statements (Hand));
861 Analyze (Call);
862
863 -- Ada 2020 (AI12-0279)
864
865 if Has_Yield_Aspect (Entity (Entry_Direct_Name (Astat)))
866 and then RTE_Available (RE_Yield)
867 then
868 Insert_Action_After (Call,
869 Make_Procedure_Call_Statement (Loc,
870 New_Occurrence_Of (RTE (RE_Yield), Loc)));
871 end if;
872
873 Next (Hand);
874 end loop;
875
876 New_S :=
877 Make_Handled_Sequence_Of_Statements (Loc,
878 Statements => New_List (
879 Make_Block_Statement (Loc,
880 Handled_Statement_Sequence => Stats)));
881
882 else
883 New_S := Stats;
884 end if;
885
886 -- At this stage we know that the new statement sequence does
887 -- not have an exception handler part, so we supply one to call
888 -- Exceptional_Complete_Rendezvous. This handler is
889
890 -- when all others =>
891 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
892
893 -- We handle Abort_Signal to make sure that we properly catch the abort
894 -- case and wake up the caller.
895
896 Call :=
897 Make_Procedure_Call_Statement (Sloc (Stats),
898 Name => New_Occurrence_Of (
899 RTE (RE_Exceptional_Complete_Rendezvous), Sloc (Stats)),
900 Parameter_Associations => New_List (
901 Make_Function_Call (Sloc (Stats),
902 Name =>
903 New_Occurrence_Of
904 (RTE (RE_Get_GNAT_Exception), Sloc (Stats)))));
905
906 Ohandle := Make_Others_Choice (Loc);
907 Set_All_Others (Ohandle);
908
909 Set_Exception_Handlers (New_S,
910 New_List (
911 Make_Implicit_Exception_Handler (Loc,
912 Exception_Choices => New_List (Ohandle),
913
914 Statements => New_List (Call))));
915
916 -- Ada 2020 (AI12-0279)
917
918 if Has_Yield_Aspect (Entity (Entry_Direct_Name (Astat)))
919 and then RTE_Available (RE_Yield)
920 then
921 Insert_Action_After (Call,
922 Make_Procedure_Call_Statement (Loc,
923 New_Occurrence_Of (RTE (RE_Yield), Loc)));
924 end if;
925
926 Set_Parent (New_S, Astat); -- temp parent for Analyze call
927 Analyze_Exception_Handlers (Exception_Handlers (New_S));
928 Expand_Exception_Handlers (New_S);
929
930 -- Exceptional_Complete_Rendezvous must be called with abort still
931 -- deferred, which is the case for a "when all others" handler.
932
933 return New_S;
934 end Build_Accept_Body;
935
936 -----------------------------------
937 -- Build_Activation_Chain_Entity --
938 -----------------------------------
939
940 procedure Build_Activation_Chain_Entity (N : Node_Id) is
941 function Has_Activation_Chain (Stmt : Node_Id) return Boolean;
942 -- Determine whether an extended return statement has activation chain
943
944 --------------------------
945 -- Has_Activation_Chain --
946 --------------------------
947
948 function Has_Activation_Chain (Stmt : Node_Id) return Boolean is
949 Decl : Node_Id;
950
951 begin
952 Decl := First (Return_Object_Declarations (Stmt));
953 while Present (Decl) loop
954 if Nkind (Decl) = N_Object_Declaration
955 and then Chars (Defining_Identifier (Decl)) = Name_uChain
956 then
957 return True;
958 end if;
959
960 Next (Decl);
961 end loop;
962
963 return False;
964 end Has_Activation_Chain;
965
966 -- Local variables
967
968 Context : Node_Id;
969 Context_Id : Entity_Id;
970 Decls : List_Id;
971
972 -- Start of processing for Build_Activation_Chain_Entity
973
974 begin
975 -- No action needed if the run-time has no tasking support
976
977 if Global_No_Tasking then
978 return;
979 end if;
980
981 -- Activation chain is never used for sequential elaboration policy, see
982 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
983
984 if Partition_Elaboration_Policy = 'S' then
985 return;
986 end if;
987
988 Find_Enclosing_Context (N, Context, Context_Id, Decls);
989
990 -- If activation chain entity has not been declared already, create one
991
992 if Nkind (Context) = N_Extended_Return_Statement
993 or else No (Activation_Chain_Entity (Context))
994 then
995 -- Since extended return statements do not store the entity of the
996 -- chain, examine the return object declarations to avoid creating
997 -- a duplicate.
998
999 if Nkind (Context) = N_Extended_Return_Statement
1000 and then Has_Activation_Chain (Context)
1001 then
1002 return;
1003 end if;
1004
1005 declare
1006 Loc : constant Source_Ptr := Sloc (Context);
1007 Chain : Entity_Id;
1008 Decl : Node_Id;
1009
1010 begin
1011 Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
1012
1013 -- Note: An extended return statement is not really a task
1014 -- activator, but it does have an activation chain on which to
1015 -- store the tasks temporarily. On successful return, the tasks
1016 -- on this chain are moved to the chain passed in by the caller.
1017 -- We do not build an Activation_Chain_Entity for an extended
1018 -- return statement, because we do not want to build a call to
1019 -- Activate_Tasks. Task activation is the responsibility of the
1020 -- caller.
1021
1022 if Nkind (Context) /= N_Extended_Return_Statement then
1023 Set_Activation_Chain_Entity (Context, Chain);
1024 end if;
1025
1026 Decl :=
1027 Make_Object_Declaration (Loc,
1028 Defining_Identifier => Chain,
1029 Aliased_Present => True,
1030 Object_Definition =>
1031 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc));
1032
1033 Prepend_To (Decls, Decl);
1034
1035 -- Ensure that _chain appears in the proper scope of the context
1036
1037 if Context_Id /= Current_Scope then
1038 Push_Scope (Context_Id);
1039 Analyze (Decl);
1040 Pop_Scope;
1041 else
1042 Analyze (Decl);
1043 end if;
1044 end;
1045 end if;
1046 end Build_Activation_Chain_Entity;
1047
1048 ----------------------------
1049 -- Build_Barrier_Function --
1050 ----------------------------
1051
1052 function Build_Barrier_Function
1053 (N : Node_Id;
1054 Ent : Entity_Id;
1055 Pid : Entity_Id) return Node_Id
1056 is
1057 Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
1058 Cond : constant Node_Id := Condition (Ent_Formals);
1059 Loc : constant Source_Ptr := Sloc (Cond);
1060 Func_Id : constant Entity_Id := Barrier_Function (Ent);
1061 Op_Decls : constant List_Id := New_List;
1062 Stmt : Node_Id;
1063 Func_Body : Node_Id;
1064
1065 begin
1066 -- Add a declaration for the Protection object, renaming declarations
1067 -- for the discriminals and privals and finally a declaration for the
1068 -- entry family index (if applicable).
1069
1070 Install_Private_Data_Declarations (Sloc (N),
1071 Spec_Id => Func_Id,
1072 Conc_Typ => Pid,
1073 Body_Nod => N,
1074 Decls => Op_Decls,
1075 Barrier => True,
1076 Family => Ekind (Ent) = E_Entry_Family);
1077
1078 -- If compiling with -fpreserve-control-flow, make sure we insert an
1079 -- IF statement so that the back-end knows to generate a conditional
1080 -- branch instruction, even if the condition is just the name of a
1081 -- boolean object. Note that Expand_N_If_Statement knows to preserve
1082 -- such redundant IF statements under -fpreserve-control-flow
1083 -- (whether coming from this routine, or directly from source).
1084
1085 if Opt.Suppress_Control_Flow_Optimizations then
1086 Stmt :=
1087 Make_Implicit_If_Statement (Cond,
1088 Condition => Cond,
1089 Then_Statements => New_List (
1090 Make_Simple_Return_Statement (Loc,
1091 New_Occurrence_Of (Standard_True, Loc))),
1092
1093 Else_Statements => New_List (
1094 Make_Simple_Return_Statement (Loc,
1095 New_Occurrence_Of (Standard_False, Loc))));
1096
1097 else
1098 Stmt := Make_Simple_Return_Statement (Loc, Cond);
1099 end if;
1100
1101 -- Note: the condition in the barrier function needs to be properly
1102 -- processed for the C/Fortran boolean possibility, but this happens
1103 -- automatically since the return statement does this normalization.
1104
1105 Func_Body :=
1106 Make_Subprogram_Body (Loc,
1107 Specification =>
1108 Build_Barrier_Function_Specification (Loc,
1109 Make_Defining_Identifier (Loc, Chars (Func_Id))),
1110 Declarations => Op_Decls,
1111 Handled_Statement_Sequence =>
1112 Make_Handled_Sequence_Of_Statements (Loc,
1113 Statements => New_List (Stmt)));
1114 Set_Is_Entry_Barrier_Function (Func_Body);
1115
1116 return Func_Body;
1117 end Build_Barrier_Function;
1118
1119 ------------------------------------------
1120 -- Build_Barrier_Function_Specification --
1121 ------------------------------------------
1122
1123 function Build_Barrier_Function_Specification
1124 (Loc : Source_Ptr;
1125 Def_Id : Entity_Id) return Node_Id
1126 is
1127 begin
1128 Set_Debug_Info_Needed (Def_Id);
1129
1130 return
1131 Make_Function_Specification (Loc,
1132 Defining_Unit_Name => Def_Id,
1133 Parameter_Specifications => New_List (
1134 Make_Parameter_Specification (Loc,
1135 Defining_Identifier =>
1136 Make_Defining_Identifier (Loc, Name_uO),
1137 Parameter_Type =>
1138 New_Occurrence_Of (RTE (RE_Address), Loc)),
1139
1140 Make_Parameter_Specification (Loc,
1141 Defining_Identifier =>
1142 Make_Defining_Identifier (Loc, Name_uE),
1143 Parameter_Type =>
1144 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
1145
1146 Result_Definition =>
1147 New_Occurrence_Of (Standard_Boolean, Loc));
1148 end Build_Barrier_Function_Specification;
1149
1150 --------------------------
1151 -- Build_Call_With_Task --
1152 --------------------------
1153
1154 function Build_Call_With_Task
1155 (N : Node_Id;
1156 E : Entity_Id) return Node_Id
1157 is
1158 Loc : constant Source_Ptr := Sloc (N);
1159 begin
1160 return
1161 Make_Function_Call (Loc,
1162 Name => New_Occurrence_Of (E, Loc),
1163 Parameter_Associations => New_List (Concurrent_Ref (N)));
1164 end Build_Call_With_Task;
1165
1166 -----------------------------
1167 -- Build_Class_Wide_Master --
1168 -----------------------------
1169
1170 procedure Build_Class_Wide_Master (Typ : Entity_Id) is
1171 Loc : constant Source_Ptr := Sloc (Typ);
1172 Master_Decl : Node_Id;
1173 Master_Id : Entity_Id;
1174 Master_Scope : Entity_Id;
1175 Name_Id : Node_Id;
1176 Related_Node : Node_Id;
1177 Ren_Decl : Node_Id;
1178
1179 begin
1180 -- No action needed if the run-time has no tasking support
1181
1182 if Global_No_Tasking then
1183 return;
1184 end if;
1185
1186 -- Find the declaration that created the access type, which is either a
1187 -- type declaration, or an object declaration with an access definition,
1188 -- in which case the type is anonymous.
1189
1190 if Is_Itype (Typ) then
1191 Related_Node := Associated_Node_For_Itype (Typ);
1192 else
1193 Related_Node := Parent (Typ);
1194 end if;
1195
1196 Master_Scope := Find_Master_Scope (Typ);
1197
1198 -- Nothing to do if the master scope already contains a _master entity.
1199 -- The only exception to this is the following scenario:
1200
1201 -- Source_Scope
1202 -- Transient_Scope_1
1203 -- _master
1204
1205 -- Transient_Scope_2
1206 -- use of master
1207
1208 -- In this case the source scope is marked as having the master entity
1209 -- even though the actual declaration appears inside an inner scope. If
1210 -- the second transient scope requires a _master, it cannot use the one
1211 -- already declared because the entity is not visible.
1212
1213 Name_Id := Make_Identifier (Loc, Name_uMaster);
1214 Master_Decl := Empty;
1215
1216 if not Has_Master_Entity (Master_Scope)
1217 or else No (Current_Entity_In_Scope (Name_Id))
1218 then
1219 declare
1220 Ins_Nod : Node_Id;
1221
1222 begin
1223 Set_Has_Master_Entity (Master_Scope);
1224 Master_Decl := Build_Master_Declaration (Loc);
1225
1226 -- Ensure that the master declaration is placed before its use
1227
1228 Ins_Nod := Find_Hook_Context (Related_Node);
1229 while not Is_List_Member (Ins_Nod) loop
1230 Ins_Nod := Parent (Ins_Nod);
1231 end loop;
1232
1233 Insert_Before (First (List_Containing (Ins_Nod)), Master_Decl);
1234 Analyze (Master_Decl);
1235
1236 -- Mark the containing scope as a task master. Masters associated
1237 -- with return statements are already marked at this stage (see
1238 -- Analyze_Subprogram_Body).
1239
1240 if Ekind (Current_Scope) /= E_Return_Statement then
1241 declare
1242 Par : Node_Id := Related_Node;
1243
1244 begin
1245 while Nkind (Par) /= N_Compilation_Unit loop
1246 Par := Parent (Par);
1247
1248 -- If we fall off the top, we are at the outer level,
1249 -- and the environment task is our effective master,
1250 -- so nothing to mark.
1251
1252 if Nkind (Par) in
1253 N_Block_Statement | N_Subprogram_Body | N_Task_Body
1254 then
1255 Set_Is_Task_Master (Par);
1256 exit;
1257 end if;
1258 end loop;
1259 end;
1260 end if;
1261 end;
1262 end if;
1263
1264 Master_Id :=
1265 Make_Defining_Identifier (Loc, New_External_Name (Chars (Typ), 'M'));
1266
1267 -- Generate:
1268 -- typeMnn renames _master;
1269
1270 Ren_Decl :=
1271 Make_Object_Renaming_Declaration (Loc,
1272 Defining_Identifier => Master_Id,
1273 Subtype_Mark => New_Occurrence_Of (Standard_Integer, Loc),
1274 Name => Name_Id);
1275
1276 -- If the master is declared locally, add the renaming declaration
1277 -- immediately after it, to prevent access-before-elaboration in the
1278 -- back-end.
1279
1280 if Present (Master_Decl) then
1281 Insert_After (Master_Decl, Ren_Decl);
1282 Analyze (Ren_Decl);
1283
1284 else
1285 Insert_Action (Related_Node, Ren_Decl);
1286 end if;
1287
1288 Set_Master_Id (Typ, Master_Id);
1289 end Build_Class_Wide_Master;
1290
1291 ----------------------------
1292 -- Build_Contract_Wrapper --
1293 ----------------------------
1294
1295 procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id) is
1296 Conc_Typ : constant Entity_Id := Scope (E);
1297 Loc : constant Source_Ptr := Sloc (E);
1298
1299 procedure Add_Discriminant_Renamings
1300 (Obj_Id : Entity_Id;
1301 Decls : List_Id);
1302 -- Add renaming declarations for all discriminants of concurrent type
1303 -- Conc_Typ. Obj_Id is the entity of the wrapper formal parameter which
1304 -- represents the concurrent object.
1305
1306 procedure Add_Matching_Formals
1307 (Formals : List_Id;
1308 Actuals : in out List_Id);
1309 -- Add formal parameters that match those of entry E to list Formals.
1310 -- The routine also adds matching actuals for the new formals to list
1311 -- Actuals.
1312
1313 procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id);
1314 -- Relocate pragma Prag to list To. The routine creates a new list if
1315 -- To does not exist.
1316
1317 --------------------------------
1318 -- Add_Discriminant_Renamings --
1319 --------------------------------
1320
1321 procedure Add_Discriminant_Renamings
1322 (Obj_Id : Entity_Id;
1323 Decls : List_Id)
1324 is
1325 Discr : Entity_Id;
1326
1327 begin
1328 -- Inspect the discriminants of the concurrent type and generate a
1329 -- renaming for each one.
1330
1331 if Has_Discriminants (Conc_Typ) then
1332 Discr := First_Discriminant (Conc_Typ);
1333 while Present (Discr) loop
1334 Prepend_To (Decls,
1335 Make_Object_Renaming_Declaration (Loc,
1336 Defining_Identifier =>
1337 Make_Defining_Identifier (Loc, Chars (Discr)),
1338 Subtype_Mark =>
1339 New_Occurrence_Of (Etype (Discr), Loc),
1340 Name =>
1341 Make_Selected_Component (Loc,
1342 Prefix => New_Occurrence_Of (Obj_Id, Loc),
1343 Selector_Name =>
1344 Make_Identifier (Loc, Chars (Discr)))));
1345
1346 Next_Discriminant (Discr);
1347 end loop;
1348 end if;
1349 end Add_Discriminant_Renamings;
1350
1351 --------------------------
1352 -- Add_Matching_Formals --
1353 --------------------------
1354
1355 procedure Add_Matching_Formals
1356 (Formals : List_Id;
1357 Actuals : in out List_Id)
1358 is
1359 Formal : Entity_Id;
1360 New_Formal : Entity_Id;
1361
1362 begin
1363 -- Inspect the formal parameters of the entry and generate a new
1364 -- matching formal with the same name for the wrapper. A reference
1365 -- to the new formal becomes an actual in the entry call.
1366
1367 Formal := First_Formal (E);
1368 while Present (Formal) loop
1369 New_Formal := Make_Defining_Identifier (Loc, Chars (Formal));
1370 Append_To (Formals,
1371 Make_Parameter_Specification (Loc,
1372 Defining_Identifier => New_Formal,
1373 In_Present => In_Present (Parent (Formal)),
1374 Out_Present => Out_Present (Parent (Formal)),
1375 Parameter_Type =>
1376 New_Occurrence_Of (Etype (Formal), Loc)));
1377
1378 if No (Actuals) then
1379 Actuals := New_List;
1380 end if;
1381
1382 Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
1383 Next_Formal (Formal);
1384 end loop;
1385 end Add_Matching_Formals;
1386
1387 ---------------------
1388 -- Transfer_Pragma --
1389 ---------------------
1390
1391 procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id) is
1392 New_Prag : Node_Id;
1393
1394 begin
1395 if No (To) then
1396 To := New_List;
1397 end if;
1398
1399 New_Prag := Relocate_Node (Prag);
1400
1401 Set_Analyzed (New_Prag, False);
1402 Append (New_Prag, To);
1403 end Transfer_Pragma;
1404
1405 -- Local variables
1406
1407 Items : constant Node_Id := Contract (E);
1408 Actuals : List_Id := No_List;
1409 Call : Node_Id;
1410 Call_Nam : Node_Id;
1411 Decls : List_Id := No_List;
1412 Formals : List_Id;
1413 Has_Pragma : Boolean := False;
1414 Index_Id : Entity_Id;
1415 Obj_Id : Entity_Id;
1416 Prag : Node_Id;
1417 Wrapper_Id : Entity_Id;
1418
1419 -- Start of processing for Build_Contract_Wrapper
1420
1421 begin
1422 -- This routine generates a specialized wrapper for a protected or task
1423 -- entry [family] which implements precondition/postcondition semantics.
1424 -- Preconditions and case guards of contract cases are checked before
1425 -- the protected action or rendezvous takes place. Postconditions and
1426 -- consequences of contract cases are checked after the protected action
1427 -- or rendezvous takes place. The structure of the generated wrapper is
1428 -- as follows:
1429
1430 -- procedure Wrapper
1431 -- (Obj_Id : Conc_Typ; -- concurrent object
1432 -- [Index : Index_Typ;] -- index of entry family
1433 -- [Formal_1 : ...; -- parameters of original entry
1434 -- Formal_N : ...])
1435 -- is
1436 -- [Discr_1 : ... renames Obj_Id.Discr_1; -- discriminant
1437 -- Discr_N : ... renames Obj_Id.Discr_N;] -- renamings
1438
1439 -- <precondition checks>
1440 -- <case guard checks>
1441
1442 -- procedure _Postconditions is
1443 -- begin
1444 -- <postcondition checks>
1445 -- <consequence checks>
1446 -- end _Postconditions;
1447
1448 -- begin
1449 -- Entry_Call (Obj_Id, [Index,] [Formal_1, Formal_N]);
1450 -- _Postconditions;
1451 -- end Wrapper;
1452
1453 -- Create the wrapper only when the entry has at least one executable
1454 -- contract item such as contract cases, precondition or postcondition.
1455
1456 if Present (Items) then
1457
1458 -- Inspect the list of pre/postconditions and transfer all available
1459 -- pragmas to the declarative list of the wrapper.
1460
1461 Prag := Pre_Post_Conditions (Items);
1462 while Present (Prag) loop
1463 if Pragma_Name_Unmapped (Prag) in Name_Postcondition
1464 | Name_Precondition
1465 and then Is_Checked (Prag)
1466 then
1467 Has_Pragma := True;
1468 Transfer_Pragma (Prag, To => Decls);
1469 end if;
1470
1471 Prag := Next_Pragma (Prag);
1472 end loop;
1473
1474 -- Inspect the list of test/contract cases and transfer only contract
1475 -- cases pragmas to the declarative part of the wrapper.
1476
1477 Prag := Contract_Test_Cases (Items);
1478 while Present (Prag) loop
1479 if Pragma_Name (Prag) = Name_Contract_Cases
1480 and then Is_Checked (Prag)
1481 then
1482 Has_Pragma := True;
1483 Transfer_Pragma (Prag, To => Decls);
1484 end if;
1485
1486 Prag := Next_Pragma (Prag);
1487 end loop;
1488 end if;
1489
1490 -- The entry lacks executable contract items and a wrapper is not needed
1491
1492 if not Has_Pragma then
1493 return;
1494 end if;
1495
1496 -- Create the profile of the wrapper. The first formal parameter is the
1497 -- concurrent object.
1498
1499 Obj_Id :=
1500 Make_Defining_Identifier (Loc,
1501 Chars => New_External_Name (Chars (Conc_Typ), 'A'));
1502
1503 Formals := New_List (
1504 Make_Parameter_Specification (Loc,
1505 Defining_Identifier => Obj_Id,
1506 Out_Present => True,
1507 In_Present => True,
1508 Parameter_Type => New_Occurrence_Of (Conc_Typ, Loc)));
1509
1510 -- Construct the call to the original entry. The call will be gradually
1511 -- augmented with an optional entry index and extra parameters.
1512
1513 Call_Nam :=
1514 Make_Selected_Component (Loc,
1515 Prefix => New_Occurrence_Of (Obj_Id, Loc),
1516 Selector_Name => New_Occurrence_Of (E, Loc));
1517
1518 -- When creating a wrapper for an entry family, the second formal is the
1519 -- entry index.
1520
1521 if Ekind (E) = E_Entry_Family then
1522 Index_Id := Make_Defining_Identifier (Loc, Name_I);
1523
1524 Append_To (Formals,
1525 Make_Parameter_Specification (Loc,
1526 Defining_Identifier => Index_Id,
1527 Parameter_Type =>
1528 New_Occurrence_Of (Entry_Index_Type (E), Loc)));
1529
1530 -- The call to the original entry becomes an indexed component to
1531 -- accommodate the entry index.
1532
1533 Call_Nam :=
1534 Make_Indexed_Component (Loc,
1535 Prefix => Call_Nam,
1536 Expressions => New_List (New_Occurrence_Of (Index_Id, Loc)));
1537 end if;
1538
1539 -- Add formal parameters to match those of the entry and build actuals
1540 -- for the entry call.
1541
1542 Add_Matching_Formals (Formals, Actuals);
1543
1544 Call :=
1545 Make_Procedure_Call_Statement (Loc,
1546 Name => Call_Nam,
1547 Parameter_Associations => Actuals);
1548
1549 -- Add renaming declarations for the discriminants of the enclosing type
1550 -- as the various contract items may reference them.
1551
1552 Add_Discriminant_Renamings (Obj_Id, Decls);
1553
1554 Wrapper_Id :=
1555 Make_Defining_Identifier (Loc, New_External_Name (Chars (E), 'E'));
1556 Set_Contract_Wrapper (E, Wrapper_Id);
1557 Set_Is_Entry_Wrapper (Wrapper_Id);
1558
1559 -- The wrapper body is analyzed when the enclosing type is frozen
1560
1561 Append_Freeze_Action (Defining_Entity (Decl),
1562 Make_Subprogram_Body (Loc,
1563 Specification =>
1564 Make_Procedure_Specification (Loc,
1565 Defining_Unit_Name => Wrapper_Id,
1566 Parameter_Specifications => Formals),
1567 Declarations => Decls,
1568 Handled_Statement_Sequence =>
1569 Make_Handled_Sequence_Of_Statements (Loc,
1570 Statements => New_List (Call))));
1571 end Build_Contract_Wrapper;
1572
1573 --------------------------------
1574 -- Build_Corresponding_Record --
1575 --------------------------------
1576
1577 function Build_Corresponding_Record
1578 (N : Node_Id;
1579 Ctyp : Entity_Id;
1580 Loc : Source_Ptr) return Node_Id
1581 is
1582 Rec_Ent : constant Entity_Id :=
1583 Make_Defining_Identifier
1584 (Loc, New_External_Name (Chars (Ctyp), 'V'));
1585 Disc : Entity_Id;
1586 Dlist : List_Id;
1587 New_Disc : Entity_Id;
1588 Cdecls : List_Id;
1589
1590 begin
1591 Set_Corresponding_Record_Type (Ctyp, Rec_Ent);
1592 Set_Ekind (Rec_Ent, E_Record_Type);
1593 Set_Has_Delayed_Freeze (Rec_Ent, Has_Delayed_Freeze (Ctyp));
1594 Set_Is_Concurrent_Record_Type (Rec_Ent, True);
1595 Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
1596 Set_Stored_Constraint (Rec_Ent, No_Elist);
1597 Cdecls := New_List;
1598
1599 -- Use discriminals to create list of discriminants for record, and
1600 -- create new discriminals for use in default expressions, etc. It is
1601 -- worth noting that a task discriminant gives rise to 5 entities;
1602
1603 -- a) The original discriminant.
1604 -- b) The discriminal for use in the task.
1605 -- c) The discriminant of the corresponding record.
1606 -- d) The discriminal for the init proc of the corresponding record.
1607 -- e) The local variable that renames the discriminant in the procedure
1608 -- for the task body.
1609
1610 -- In fact the discriminals b) are used in the renaming declarations
1611 -- for e). See details in einfo (Handling of Discriminants).
1612
1613 if Present (Discriminant_Specifications (N)) then
1614 Dlist := New_List;
1615 Disc := First_Discriminant (Ctyp);
1616
1617 while Present (Disc) loop
1618 New_Disc := CR_Discriminant (Disc);
1619
1620 Append_To (Dlist,
1621 Make_Discriminant_Specification (Loc,
1622 Defining_Identifier => New_Disc,
1623 Discriminant_Type =>
1624 New_Occurrence_Of (Etype (Disc), Loc),
1625 Expression =>
1626 New_Copy (Discriminant_Default_Value (Disc))));
1627
1628 Next_Discriminant (Disc);
1629 end loop;
1630
1631 else
1632 Dlist := No_List;
1633 end if;
1634
1635 -- Now we can construct the record type declaration. Note that this
1636 -- record is "limited tagged". It is "limited" to reflect the underlying
1637 -- limitedness of the task or protected object that it represents, and
1638 -- ensuring for example that it is properly passed by reference. It is
1639 -- "tagged" to give support to dispatching calls through interfaces. We
1640 -- propagate here the list of interfaces covered by the concurrent type
1641 -- (Ada 2005: AI-345).
1642
1643 return
1644 Make_Full_Type_Declaration (Loc,
1645 Defining_Identifier => Rec_Ent,
1646 Discriminant_Specifications => Dlist,
1647 Type_Definition =>
1648 Make_Record_Definition (Loc,
1649 Component_List =>
1650 Make_Component_List (Loc, Component_Items => Cdecls),
1651 Tagged_Present =>
1652 Ada_Version >= Ada_2005 and then Is_Tagged_Type (Ctyp),
1653 Interface_List => Interface_List (N),
1654 Limited_Present => True));
1655 end Build_Corresponding_Record;
1656
1657 ---------------------------------
1658 -- Build_Dispatching_Tag_Check --
1659 ---------------------------------
1660
1661 function Build_Dispatching_Tag_Check
1662 (K : Entity_Id;
1663 N : Node_Id) return Node_Id
1664 is
1665 Loc : constant Source_Ptr := Sloc (N);
1666
1667 begin
1668 return
1669 Make_Op_Or (Loc,
1670 Make_Op_Eq (Loc,
1671 Left_Opnd =>
1672 New_Occurrence_Of (K, Loc),
1673 Right_Opnd =>
1674 New_Occurrence_Of (RTE (RE_TK_Limited_Tagged), Loc)),
1675
1676 Make_Op_Eq (Loc,
1677 Left_Opnd =>
1678 New_Occurrence_Of (K, Loc),
1679 Right_Opnd =>
1680 New_Occurrence_Of (RTE (RE_TK_Tagged), Loc)));
1681 end Build_Dispatching_Tag_Check;
1682
1683 ----------------------------------
1684 -- Build_Entry_Count_Expression --
1685 ----------------------------------
1686
1687 function Build_Entry_Count_Expression
1688 (Concurrent_Type : Node_Id;
1689 Component_List : List_Id;
1690 Loc : Source_Ptr) return Node_Id
1691 is
1692 Eindx : Nat;
1693 Ent : Entity_Id;
1694 Ecount : Node_Id;
1695 Comp : Node_Id;
1696 Lo : Node_Id;
1697 Hi : Node_Id;
1698 Typ : Entity_Id;
1699 Large : Boolean;
1700
1701 begin
1702 -- Count number of non-family entries
1703
1704 Eindx := 0;
1705 Ent := First_Entity (Concurrent_Type);
1706 while Present (Ent) loop
1707 if Ekind (Ent) = E_Entry then
1708 Eindx := Eindx + 1;
1709 end if;
1710
1711 Next_Entity (Ent);
1712 end loop;
1713
1714 Ecount := Make_Integer_Literal (Loc, Eindx);
1715
1716 -- Loop through entry families building the addition nodes
1717
1718 Ent := First_Entity (Concurrent_Type);
1719 Comp := First (Component_List);
1720 while Present (Ent) loop
1721 if Ekind (Ent) = E_Entry_Family then
1722 while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
1723 Next (Comp);
1724 end loop;
1725
1726 Typ := Entry_Index_Type (Ent);
1727 Hi := Type_High_Bound (Typ);
1728 Lo := Type_Low_Bound (Typ);
1729 Large := Is_Potentially_Large_Family
1730 (Base_Type (Typ), Concurrent_Type, Lo, Hi);
1731 Ecount :=
1732 Make_Op_Add (Loc,
1733 Left_Opnd => Ecount,
1734 Right_Opnd =>
1735 Family_Size (Loc, Hi, Lo, Concurrent_Type, Large));
1736 end if;
1737
1738 Next_Entity (Ent);
1739 end loop;
1740
1741 return Ecount;
1742 end Build_Entry_Count_Expression;
1743
1744 ------------------------------
1745 -- Build_Master_Declaration --
1746 ------------------------------
1747
1748 function Build_Master_Declaration (Loc : Source_Ptr) return Node_Id is
1749 Master_Decl : Node_Id;
1750
1751 begin
1752 -- Generate a dummy master if tasks or tasking hierarchies are
1753 -- prohibited.
1754
1755 -- _Master : constant Master_Id := 3;
1756
1757 if not Tasking_Allowed
1758 or else Restrictions.Set (No_Task_Hierarchy)
1759 or else not RTE_Available (RE_Current_Master)
1760 then
1761 declare
1762 Expr : Node_Id;
1763
1764 begin
1765 -- RE_Library_Task_Level is not always available in configurable
1766 -- RunTime
1767
1768 if not RTE_Available (RE_Library_Task_Level) then
1769 Expr := Make_Integer_Literal (Loc, Uint_3);
1770 else
1771 Expr := New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc);
1772 end if;
1773
1774 Master_Decl :=
1775 Make_Object_Declaration (Loc,
1776 Defining_Identifier =>
1777 Make_Defining_Identifier (Loc, Name_uMaster),
1778 Constant_Present => True,
1779 Object_Definition =>
1780 New_Occurrence_Of (Standard_Integer, Loc),
1781 Expression => Expr);
1782 end;
1783
1784 -- Generate:
1785 -- _master : constant Integer := Current_Master.all;
1786
1787 else
1788 Master_Decl :=
1789 Make_Object_Declaration (Loc,
1790 Defining_Identifier =>
1791 Make_Defining_Identifier (Loc, Name_uMaster),
1792 Constant_Present => True,
1793 Object_Definition =>
1794 New_Occurrence_Of (Standard_Integer, Loc),
1795 Expression =>
1796 Make_Explicit_Dereference (Loc,
1797 New_Occurrence_Of (RTE (RE_Current_Master), Loc)));
1798 end if;
1799
1800 return Master_Decl;
1801 end Build_Master_Declaration;
1802
1803 ---------------------------
1804 -- Build_Parameter_Block --
1805 ---------------------------
1806
1807 function Build_Parameter_Block
1808 (Loc : Source_Ptr;
1809 Actuals : List_Id;
1810 Formals : List_Id;
1811 Decls : List_Id) return Entity_Id
1812 is
1813 Actual : Entity_Id;
1814 Comp_Nam : Node_Id;
1815 Comps : List_Id;
1816 Formal : Entity_Id;
1817 Has_Comp : Boolean := False;
1818 Rec_Nam : Node_Id;
1819
1820 begin
1821 Actual := First (Actuals);
1822 Comps := New_List;
1823 Formal := Defining_Identifier (First (Formals));
1824
1825 while Present (Actual) loop
1826 if not Is_Controlling_Actual (Actual) then
1827
1828 -- Generate:
1829 -- type Ann is access all <actual-type>
1830
1831 Comp_Nam := Make_Temporary (Loc, 'A');
1832 Set_Is_Param_Block_Component_Type (Comp_Nam);
1833
1834 Append_To (Decls,
1835 Make_Full_Type_Declaration (Loc,
1836 Defining_Identifier => Comp_Nam,
1837 Type_Definition =>
1838 Make_Access_To_Object_Definition (Loc,
1839 All_Present => True,
1840 Constant_Present => Ekind (Formal) = E_In_Parameter,
1841 Subtype_Indication =>
1842 New_Occurrence_Of (Etype (Actual), Loc))));
1843
1844 -- Generate:
1845 -- Param : Ann;
1846
1847 Append_To (Comps,
1848 Make_Component_Declaration (Loc,
1849 Defining_Identifier =>
1850 Make_Defining_Identifier (Loc, Chars (Formal)),
1851 Component_Definition =>
1852 Make_Component_Definition (Loc,
1853 Aliased_Present =>
1854 False,
1855 Subtype_Indication =>
1856 New_Occurrence_Of (Comp_Nam, Loc))));
1857
1858 Has_Comp := True;
1859 end if;
1860
1861 Next_Actual (Actual);
1862 Next_Formal_With_Extras (Formal);
1863 end loop;
1864
1865 Rec_Nam := Make_Temporary (Loc, 'P');
1866
1867 if Has_Comp then
1868
1869 -- Generate:
1870 -- type Pnn is record
1871 -- Param1 : Ann1;
1872 -- ...
1873 -- ParamN : AnnN;
1874
1875 -- where Pnn is a parameter wrapping record, Param1 .. ParamN are
1876 -- the original parameter names and Ann1 .. AnnN are the access to
1877 -- actual types.
1878
1879 Append_To (Decls,
1880 Make_Full_Type_Declaration (Loc,
1881 Defining_Identifier =>
1882 Rec_Nam,
1883 Type_Definition =>
1884 Make_Record_Definition (Loc,
1885 Component_List =>
1886 Make_Component_List (Loc, Comps))));
1887 else
1888 -- Generate:
1889 -- type Pnn is null record;
1890
1891 Append_To (Decls,
1892 Make_Full_Type_Declaration (Loc,
1893 Defining_Identifier =>
1894 Rec_Nam,
1895 Type_Definition =>
1896 Make_Record_Definition (Loc,
1897 Null_Present => True,
1898 Component_List => Empty)));
1899 end if;
1900
1901 return Rec_Nam;
1902 end Build_Parameter_Block;
1903
1904 --------------------------------------
1905 -- Build_Renamed_Formal_Declaration --
1906 --------------------------------------
1907
1908 function Build_Renamed_Formal_Declaration
1909 (New_F : Entity_Id;
1910 Formal : Entity_Id;
1911 Comp : Entity_Id;
1912 Renamed_Formal : Node_Id) return Node_Id
1913 is
1914 Loc : constant Source_Ptr := Sloc (New_F);
1915 Decl : Node_Id;
1916
1917 begin
1918 -- If the formal is a tagged incomplete type, it is already passed
1919 -- by reference, so it is sufficient to rename the pointer component
1920 -- that corresponds to the actual. Otherwise we need to dereference
1921 -- the pointer component to obtain the actual.
1922
1923 if Is_Incomplete_Type (Etype (Formal))
1924 and then Is_Tagged_Type (Etype (Formal))
1925 then
1926 Decl :=
1927 Make_Object_Renaming_Declaration (Loc,
1928 Defining_Identifier => New_F,
1929 Subtype_Mark => New_Occurrence_Of (Etype (Comp), Loc),
1930 Name => Renamed_Formal);
1931
1932 else
1933 Decl :=
1934 Make_Object_Renaming_Declaration (Loc,
1935 Defining_Identifier => New_F,
1936 Subtype_Mark => New_Occurrence_Of (Etype (Formal), Loc),
1937 Name =>
1938 Make_Explicit_Dereference (Loc, Renamed_Formal));
1939 end if;
1940
1941 return Decl;
1942 end Build_Renamed_Formal_Declaration;
1943
1944 --------------------------
1945 -- Build_Wrapper_Bodies --
1946 --------------------------
1947
1948 procedure Build_Wrapper_Bodies
1949 (Loc : Source_Ptr;
1950 Typ : Entity_Id;
1951 N : Node_Id)
1952 is
1953 Rec_Typ : Entity_Id;
1954
1955 function Build_Wrapper_Body
1956 (Loc : Source_Ptr;
1957 Subp_Id : Entity_Id;
1958 Obj_Typ : Entity_Id;
1959 Formals : List_Id) return Node_Id;
1960 -- Ada 2005 (AI-345): Build the body that wraps a primitive operation
1961 -- associated with a protected or task type. Subp_Id is the subprogram
1962 -- name which will be wrapped. Obj_Typ is the type of the new formal
1963 -- parameter which handles dispatching and object notation. Formals are
1964 -- the original formals of Subp_Id which will be explicitly replicated.
1965
1966 ------------------------
1967 -- Build_Wrapper_Body --
1968 ------------------------
1969
1970 function Build_Wrapper_Body
1971 (Loc : Source_Ptr;
1972 Subp_Id : Entity_Id;
1973 Obj_Typ : Entity_Id;
1974 Formals : List_Id) return Node_Id
1975 is
1976 Body_Spec : Node_Id;
1977
1978 begin
1979 Body_Spec := Build_Wrapper_Spec (Subp_Id, Obj_Typ, Formals);
1980
1981 -- The subprogram is not overriding or is not a primitive declared
1982 -- between two views.
1983
1984 if No (Body_Spec) then
1985 return Empty;
1986 end if;
1987
1988 declare
1989 Actuals : List_Id := No_List;
1990 Conv_Id : Node_Id;
1991 First_Form : Node_Id;
1992 Formal : Node_Id;
1993 Nam : Node_Id;
1994
1995 begin
1996 -- Map formals to actuals. Use the list built for the wrapper
1997 -- spec, skipping the object notation parameter.
1998
1999 First_Form := First (Parameter_Specifications (Body_Spec));
2000
2001 Formal := First_Form;
2002 Next (Formal);
2003
2004 if Present (Formal) then
2005 Actuals := New_List;
2006 while Present (Formal) loop
2007 Append_To (Actuals,
2008 Make_Identifier (Loc,
2009 Chars => Chars (Defining_Identifier (Formal))));
2010 Next (Formal);
2011 end loop;
2012 end if;
2013
2014 -- Special processing for primitives declared between a private
2015 -- type and its completion: the wrapper needs a properly typed
2016 -- parameter if the wrapped operation has a controlling first
2017 -- parameter. Note that this might not be the case for a function
2018 -- with a controlling result.
2019
2020 if Is_Private_Primitive_Subprogram (Subp_Id) then
2021 if No (Actuals) then
2022 Actuals := New_List;
2023 end if;
2024
2025 if Is_Controlling_Formal (First_Formal (Subp_Id)) then
2026 Prepend_To (Actuals,
2027 Unchecked_Convert_To
2028 (Corresponding_Concurrent_Type (Obj_Typ),
2029 Make_Identifier (Loc, Name_uO)));
2030
2031 else
2032 Prepend_To (Actuals,
2033 Make_Identifier (Loc,
2034 Chars => Chars (Defining_Identifier (First_Form))));
2035 end if;
2036
2037 Nam := New_Occurrence_Of (Subp_Id, Loc);
2038 else
2039 -- An access-to-variable object parameter requires an explicit
2040 -- dereference in the unchecked conversion. This case occurs
2041 -- when a protected entry wrapper must override an interface
2042 -- level procedure with interface access as first parameter.
2043
2044 -- O.all.Subp_Id (Formal_1, ..., Formal_N)
2045
2046 if Nkind (Parameter_Type (First_Form)) =
2047 N_Access_Definition
2048 then
2049 Conv_Id :=
2050 Make_Explicit_Dereference (Loc,
2051 Prefix => Make_Identifier (Loc, Name_uO));
2052 else
2053 Conv_Id := Make_Identifier (Loc, Name_uO);
2054 end if;
2055
2056 Nam :=
2057 Make_Selected_Component (Loc,
2058 Prefix =>
2059 Unchecked_Convert_To
2060 (Corresponding_Concurrent_Type (Obj_Typ), Conv_Id),
2061 Selector_Name => New_Occurrence_Of (Subp_Id, Loc));
2062 end if;
2063
2064 -- Create the subprogram body. For a function, the call to the
2065 -- actual subprogram has to be converted to the corresponding
2066 -- record if it is a controlling result.
2067
2068 if Ekind (Subp_Id) = E_Function then
2069 declare
2070 Res : Node_Id;
2071
2072 begin
2073 Res :=
2074 Make_Function_Call (Loc,
2075 Name => Nam,
2076 Parameter_Associations => Actuals);
2077
2078 if Has_Controlling_Result (Subp_Id) then
2079 Res :=
2080 Unchecked_Convert_To
2081 (Corresponding_Record_Type (Etype (Subp_Id)), Res);
2082 end if;
2083
2084 return
2085 Make_Subprogram_Body (Loc,
2086 Specification => Body_Spec,
2087 Declarations => Empty_List,
2088 Handled_Statement_Sequence =>
2089 Make_Handled_Sequence_Of_Statements (Loc,
2090 Statements => New_List (
2091 Make_Simple_Return_Statement (Loc, Res))));
2092 end;
2093
2094 else
2095 return
2096 Make_Subprogram_Body (Loc,
2097 Specification => Body_Spec,
2098 Declarations => Empty_List,
2099 Handled_Statement_Sequence =>
2100 Make_Handled_Sequence_Of_Statements (Loc,
2101 Statements => New_List (
2102 Make_Procedure_Call_Statement (Loc,
2103 Name => Nam,
2104 Parameter_Associations => Actuals))));
2105 end if;
2106 end;
2107 end Build_Wrapper_Body;
2108
2109 -- Start of processing for Build_Wrapper_Bodies
2110
2111 begin
2112 if Is_Concurrent_Type (Typ) then
2113 Rec_Typ := Corresponding_Record_Type (Typ);
2114 else
2115 Rec_Typ := Typ;
2116 end if;
2117
2118 -- Generate wrapper bodies for a concurrent type which implements an
2119 -- interface.
2120
2121 if Present (Interfaces (Rec_Typ)) then
2122 declare
2123 Insert_Nod : Node_Id;
2124 Prim : Entity_Id;
2125 Prim_Elmt : Elmt_Id;
2126 Prim_Decl : Node_Id;
2127 Subp : Entity_Id;
2128 Wrap_Body : Node_Id;
2129 Wrap_Id : Entity_Id;
2130
2131 begin
2132 Insert_Nod := N;
2133
2134 -- Examine all primitive operations of the corresponding record
2135 -- type, looking for wrapper specs. Generate bodies in order to
2136 -- complete them.
2137
2138 Prim_Elmt := First_Elmt (Primitive_Operations (Rec_Typ));
2139 while Present (Prim_Elmt) loop
2140 Prim := Node (Prim_Elmt);
2141
2142 if (Ekind (Prim) = E_Function
2143 or else Ekind (Prim) = E_Procedure)
2144 and then Is_Primitive_Wrapper (Prim)
2145 then
2146 Subp := Wrapped_Entity (Prim);
2147 Prim_Decl := Parent (Parent (Prim));
2148
2149 Wrap_Body :=
2150 Build_Wrapper_Body (Loc,
2151 Subp_Id => Subp,
2152 Obj_Typ => Rec_Typ,
2153 Formals => Parameter_Specifications (Parent (Subp)));
2154 Wrap_Id := Defining_Unit_Name (Specification (Wrap_Body));
2155
2156 Set_Corresponding_Spec (Wrap_Body, Prim);
2157 Set_Corresponding_Body (Prim_Decl, Wrap_Id);
2158
2159 Insert_After (Insert_Nod, Wrap_Body);
2160 Insert_Nod := Wrap_Body;
2161
2162 Analyze (Wrap_Body);
2163 end if;
2164
2165 Next_Elmt (Prim_Elmt);
2166 end loop;
2167 end;
2168 end if;
2169 end Build_Wrapper_Bodies;
2170
2171 ------------------------
2172 -- Build_Wrapper_Spec --
2173 ------------------------
2174
2175 function Build_Wrapper_Spec
2176 (Subp_Id : Entity_Id;
2177 Obj_Typ : Entity_Id;
2178 Formals : List_Id) return Node_Id
2179 is
2180 function Overriding_Possible
2181 (Iface_Op : Entity_Id;
2182 Wrapper : Entity_Id) return Boolean;
2183 -- Determine whether a primitive operation can be overridden by Wrapper.
2184 -- Iface_Op is the candidate primitive operation of an interface type,
2185 -- Wrapper is the generated entry wrapper.
2186
2187 function Replicate_Formals
2188 (Loc : Source_Ptr;
2189 Formals : List_Id) return List_Id;
2190 -- An explicit parameter replication is required due to the Is_Entry_
2191 -- Formal flag being set for all the formals of an entry. The explicit
2192 -- replication removes the flag that would otherwise cause a different
2193 -- path of analysis.
2194
2195 -------------------------
2196 -- Overriding_Possible --
2197 -------------------------
2198
2199 function Overriding_Possible
2200 (Iface_Op : Entity_Id;
2201 Wrapper : Entity_Id) return Boolean
2202 is
2203 Iface_Op_Spec : constant Node_Id := Parent (Iface_Op);
2204 Wrapper_Spec : constant Node_Id := Parent (Wrapper);
2205
2206 function Type_Conformant_Parameters
2207 (Iface_Op_Params : List_Id;
2208 Wrapper_Params : List_Id) return Boolean;
2209 -- Determine whether the parameters of the generated entry wrapper
2210 -- and those of a primitive operation are type conformant. During
2211 -- this check, the first parameter of the primitive operation is
2212 -- skipped if it is a controlling argument: protected functions
2213 -- may have a controlling result.
2214
2215 --------------------------------
2216 -- Type_Conformant_Parameters --
2217 --------------------------------
2218
2219 function Type_Conformant_Parameters
2220 (Iface_Op_Params : List_Id;
2221 Wrapper_Params : List_Id) return Boolean
2222 is
2223 Iface_Op_Param : Node_Id;
2224 Iface_Op_Typ : Entity_Id;
2225 Wrapper_Param : Node_Id;
2226 Wrapper_Typ : Entity_Id;
2227
2228 begin
2229 -- Skip the first (controlling) parameter of primitive operation
2230
2231 Iface_Op_Param := First (Iface_Op_Params);
2232
2233 if Present (First_Formal (Iface_Op))
2234 and then Is_Controlling_Formal (First_Formal (Iface_Op))
2235 then
2236 Next (Iface_Op_Param);
2237 end if;
2238
2239 Wrapper_Param := First (Wrapper_Params);
2240 while Present (Iface_Op_Param)
2241 and then Present (Wrapper_Param)
2242 loop
2243 Iface_Op_Typ := Find_Parameter_Type (Iface_Op_Param);
2244 Wrapper_Typ := Find_Parameter_Type (Wrapper_Param);
2245
2246 -- The two parameters must be mode conformant
2247
2248 if not Conforming_Types
2249 (Iface_Op_Typ, Wrapper_Typ, Mode_Conformant)
2250 then
2251 return False;
2252 end if;
2253
2254 Next (Iface_Op_Param);
2255 Next (Wrapper_Param);
2256 end loop;
2257
2258 -- One of the lists is longer than the other
2259
2260 if Present (Iface_Op_Param) or else Present (Wrapper_Param) then
2261 return False;
2262 end if;
2263
2264 return True;
2265 end Type_Conformant_Parameters;
2266
2267 -- Start of processing for Overriding_Possible
2268
2269 begin
2270 if Chars (Iface_Op) /= Chars (Wrapper) then
2271 return False;
2272 end if;
2273
2274 -- If an inherited subprogram is implemented by a protected procedure
2275 -- or an entry, then the first parameter of the inherited subprogram
2276 -- must be of mode OUT or IN OUT, or access-to-variable parameter.
2277
2278 if Ekind (Iface_Op) = E_Procedure
2279 and then Present (Parameter_Specifications (Iface_Op_Spec))
2280 then
2281 declare
2282 Obj_Param : constant Node_Id :=
2283 First (Parameter_Specifications (Iface_Op_Spec));
2284 begin
2285 if not Out_Present (Obj_Param)
2286 and then Nkind (Parameter_Type (Obj_Param)) /=
2287 N_Access_Definition
2288 then
2289 return False;
2290 end if;
2291 end;
2292 end if;
2293
2294 return
2295 Type_Conformant_Parameters
2296 (Parameter_Specifications (Iface_Op_Spec),
2297 Parameter_Specifications (Wrapper_Spec));
2298 end Overriding_Possible;
2299
2300 -----------------------
2301 -- Replicate_Formals --
2302 -----------------------
2303
2304 function Replicate_Formals
2305 (Loc : Source_Ptr;
2306 Formals : List_Id) return List_Id
2307 is
2308 New_Formals : constant List_Id := New_List;
2309 Formal : Node_Id;
2310 Param_Type : Node_Id;
2311
2312 begin
2313 Formal := First (Formals);
2314
2315 -- Skip the object parameter when dealing with primitives declared
2316 -- between two views.
2317
2318 if Is_Private_Primitive_Subprogram (Subp_Id)
2319 and then not Has_Controlling_Result (Subp_Id)
2320 then
2321 Next (Formal);
2322 end if;
2323
2324 while Present (Formal) loop
2325
2326 -- Create an explicit copy of the entry parameter
2327
2328 -- When creating the wrapper subprogram for a primitive operation
2329 -- of a protected interface we must construct an equivalent
2330 -- signature to that of the overriding operation. For regular
2331 -- parameters we can just use the type of the formal, but for
2332 -- access to subprogram parameters we need to reanalyze the
2333 -- parameter type to create local entities for the signature of
2334 -- the subprogram type. Using the entities of the overriding
2335 -- subprogram will result in out-of-scope errors in the back-end.
2336
2337 if Nkind (Parameter_Type (Formal)) = N_Access_Definition then
2338 Param_Type := Copy_Separate_Tree (Parameter_Type (Formal));
2339 else
2340 Param_Type :=
2341 New_Occurrence_Of (Etype (Parameter_Type (Formal)), Loc);
2342 end if;
2343
2344 Append_To (New_Formals,
2345 Make_Parameter_Specification (Loc,
2346 Defining_Identifier =>
2347 Make_Defining_Identifier (Loc,
2348 Chars => Chars (Defining_Identifier (Formal))),
2349 In_Present => In_Present (Formal),
2350 Out_Present => Out_Present (Formal),
2351 Null_Exclusion_Present => Null_Exclusion_Present (Formal),
2352 Parameter_Type => Param_Type));
2353
2354 Next (Formal);
2355 end loop;
2356
2357 return New_Formals;
2358 end Replicate_Formals;
2359
2360 -- Local variables
2361
2362 Loc : constant Source_Ptr := Sloc (Subp_Id);
2363 First_Param : Node_Id := Empty;
2364 Iface : Entity_Id;
2365 Iface_Elmt : Elmt_Id;
2366 Iface_Op : Entity_Id;
2367 Iface_Op_Elmt : Elmt_Id;
2368 Overridden_Subp : Entity_Id;
2369
2370 -- Start of processing for Build_Wrapper_Spec
2371
2372 begin
2373 -- No point in building wrappers for untagged concurrent types
2374
2375 pragma Assert (Is_Tagged_Type (Obj_Typ));
2376
2377 -- Check if this subprogram has a profile that matches some interface
2378 -- primitive.
2379
2380 Check_Synchronized_Overriding (Subp_Id, Overridden_Subp);
2381
2382 if Present (Overridden_Subp) then
2383 First_Param :=
2384 First (Parameter_Specifications (Parent (Overridden_Subp)));
2385
2386 -- An entry or a protected procedure can override a routine where the
2387 -- controlling formal is either IN OUT, OUT or is of access-to-variable
2388 -- type. Since the wrapper must have the exact same signature as that of
2389 -- the overridden subprogram, we try to find the overriding candidate
2390 -- and use its controlling formal.
2391
2392 -- Check every implemented interface
2393
2394 elsif Present (Interfaces (Obj_Typ)) then
2395 Iface_Elmt := First_Elmt (Interfaces (Obj_Typ));
2396 Search : while Present (Iface_Elmt) loop
2397 Iface := Node (Iface_Elmt);
2398
2399 -- Check every interface primitive
2400
2401 if Present (Primitive_Operations (Iface)) then
2402 Iface_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
2403 while Present (Iface_Op_Elmt) loop
2404 Iface_Op := Node (Iface_Op_Elmt);
2405
2406 -- Ignore predefined primitives
2407
2408 if not Is_Predefined_Dispatching_Operation (Iface_Op) then
2409 Iface_Op := Ultimate_Alias (Iface_Op);
2410
2411 -- The current primitive operation can be overridden by
2412 -- the generated entry wrapper.
2413
2414 if Overriding_Possible (Iface_Op, Subp_Id) then
2415 First_Param :=
2416 First (Parameter_Specifications (Parent (Iface_Op)));
2417
2418 exit Search;
2419 end if;
2420 end if;
2421
2422 Next_Elmt (Iface_Op_Elmt);
2423 end loop;
2424 end if;
2425
2426 Next_Elmt (Iface_Elmt);
2427 end loop Search;
2428 end if;
2429
2430 -- Do not generate the wrapper if no interface primitive is covered by
2431 -- the subprogram and it is not a primitive declared between two views
2432 -- (see Process_Full_View).
2433
2434 if No (First_Param)
2435 and then not Is_Private_Primitive_Subprogram (Subp_Id)
2436 then
2437 return Empty;
2438 end if;
2439
2440 declare
2441 Wrapper_Id : constant Entity_Id :=
2442 Make_Defining_Identifier (Loc, Chars (Subp_Id));
2443 New_Formals : List_Id;
2444 Obj_Param : Node_Id;
2445 Obj_Param_Typ : Entity_Id;
2446
2447 begin
2448 -- Minimum decoration is needed to catch the entity in
2449 -- Sem_Ch6.Override_Dispatching_Operation.
2450
2451 if Ekind (Subp_Id) = E_Function then
2452 Set_Ekind (Wrapper_Id, E_Function);
2453 else
2454 Set_Ekind (Wrapper_Id, E_Procedure);
2455 end if;
2456
2457 Set_Is_Primitive_Wrapper (Wrapper_Id);
2458 Set_Wrapped_Entity (Wrapper_Id, Subp_Id);
2459 Set_Is_Private_Primitive (Wrapper_Id,
2460 Is_Private_Primitive_Subprogram (Subp_Id));
2461
2462 -- Process the formals
2463
2464 New_Formals := Replicate_Formals (Loc, Formals);
2465
2466 -- A function with a controlling result and no first controlling
2467 -- formal needs no additional parameter.
2468
2469 if Has_Controlling_Result (Subp_Id)
2470 and then
2471 (No (First_Formal (Subp_Id))
2472 or else not Is_Controlling_Formal (First_Formal (Subp_Id)))
2473 then
2474 null;
2475
2476 -- Routine Subp_Id has been found to override an interface primitive.
2477 -- If the interface operation has an access parameter, create a copy
2478 -- of it, with the same null exclusion indicator if present.
2479
2480 elsif Present (First_Param) then
2481 if Nkind (Parameter_Type (First_Param)) = N_Access_Definition then
2482 Obj_Param_Typ :=
2483 Make_Access_Definition (Loc,
2484 Subtype_Mark =>
2485 New_Occurrence_Of (Obj_Typ, Loc),
2486 Null_Exclusion_Present =>
2487 Null_Exclusion_Present (Parameter_Type (First_Param)),
2488 Constant_Present =>
2489 Constant_Present (Parameter_Type (First_Param)));
2490 else
2491 Obj_Param_Typ := New_Occurrence_Of (Obj_Typ, Loc);
2492 end if;
2493
2494 Obj_Param :=
2495 Make_Parameter_Specification (Loc,
2496 Defining_Identifier =>
2497 Make_Defining_Identifier (Loc,
2498 Chars => Name_uO),
2499 In_Present => In_Present (First_Param),
2500 Out_Present => Out_Present (First_Param),
2501 Parameter_Type => Obj_Param_Typ);
2502
2503 Prepend_To (New_Formals, Obj_Param);
2504
2505 -- If we are dealing with a primitive declared between two views,
2506 -- implemented by a synchronized operation, we need to create
2507 -- a default parameter. The mode of the parameter must match that
2508 -- of the primitive operation.
2509
2510 else
2511 pragma Assert (Is_Private_Primitive_Subprogram (Subp_Id));
2512
2513 Obj_Param :=
2514 Make_Parameter_Specification (Loc,
2515 Defining_Identifier =>
2516 Make_Defining_Identifier (Loc, Name_uO),
2517 In_Present =>
2518 In_Present (Parent (First_Entity (Subp_Id))),
2519 Out_Present => Ekind (Subp_Id) /= E_Function,
2520 Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
2521
2522 Prepend_To (New_Formals, Obj_Param);
2523 end if;
2524
2525 -- Build the final spec. If it is a function with a controlling
2526 -- result, it is a primitive operation of the corresponding
2527 -- record type, so mark the spec accordingly.
2528
2529 if Ekind (Subp_Id) = E_Function then
2530 declare
2531 Res_Def : Node_Id;
2532
2533 begin
2534 if Has_Controlling_Result (Subp_Id) then
2535 Res_Def :=
2536 New_Occurrence_Of
2537 (Corresponding_Record_Type (Etype (Subp_Id)), Loc);
2538 else
2539 Res_Def := New_Copy (Result_Definition (Parent (Subp_Id)));
2540 end if;
2541
2542 return
2543 Make_Function_Specification (Loc,
2544 Defining_Unit_Name => Wrapper_Id,
2545 Parameter_Specifications => New_Formals,
2546 Result_Definition => Res_Def);
2547 end;
2548 else
2549 return
2550 Make_Procedure_Specification (Loc,
2551 Defining_Unit_Name => Wrapper_Id,
2552 Parameter_Specifications => New_Formals);
2553 end if;
2554 end;
2555 end Build_Wrapper_Spec;
2556
2557 -------------------------
2558 -- Build_Wrapper_Specs --
2559 -------------------------
2560
2561 procedure Build_Wrapper_Specs
2562 (Loc : Source_Ptr;
2563 Typ : Entity_Id;
2564 N : in out Node_Id)
2565 is
2566 Def : Node_Id;
2567 Rec_Typ : Entity_Id;
2568 procedure Scan_Declarations (L : List_Id);
2569 -- Common processing for visible and private declarations
2570 -- of a protected type.
2571
2572 procedure Scan_Declarations (L : List_Id) is
2573 Decl : Node_Id;
2574 Wrap_Decl : Node_Id;
2575 Wrap_Spec : Node_Id;
2576
2577 begin
2578 if No (L) then
2579 return;
2580 end if;
2581
2582 Decl := First (L);
2583 while Present (Decl) loop
2584 Wrap_Spec := Empty;
2585
2586 if Nkind (Decl) = N_Entry_Declaration
2587 and then Ekind (Defining_Identifier (Decl)) = E_Entry
2588 then
2589 Wrap_Spec :=
2590 Build_Wrapper_Spec
2591 (Subp_Id => Defining_Identifier (Decl),
2592 Obj_Typ => Rec_Typ,
2593 Formals => Parameter_Specifications (Decl));
2594
2595 elsif Nkind (Decl) = N_Subprogram_Declaration then
2596 Wrap_Spec :=
2597 Build_Wrapper_Spec
2598 (Subp_Id => Defining_Unit_Name (Specification (Decl)),
2599 Obj_Typ => Rec_Typ,
2600 Formals =>
2601 Parameter_Specifications (Specification (Decl)));
2602 end if;
2603
2604 if Present (Wrap_Spec) then
2605 Wrap_Decl :=
2606 Make_Subprogram_Declaration (Loc,
2607 Specification => Wrap_Spec);
2608
2609 Insert_After (N, Wrap_Decl);
2610 N := Wrap_Decl;
2611
2612 Analyze (Wrap_Decl);
2613 end if;
2614
2615 Next (Decl);
2616 end loop;
2617 end Scan_Declarations;
2618
2619 -- start of processing for Build_Wrapper_Specs
2620
2621 begin
2622 if Is_Protected_Type (Typ) then
2623 Def := Protected_Definition (Parent (Typ));
2624 else pragma Assert (Is_Task_Type (Typ));
2625 Def := Task_Definition (Parent (Typ));
2626 end if;
2627
2628 Rec_Typ := Corresponding_Record_Type (Typ);
2629
2630 -- Generate wrapper specs for a concurrent type which implements an
2631 -- interface. Operations in both the visible and private parts may
2632 -- implement progenitor operations.
2633
2634 if Present (Interfaces (Rec_Typ)) and then Present (Def) then
2635 Scan_Declarations (Visible_Declarations (Def));
2636 Scan_Declarations (Private_Declarations (Def));
2637 end if;
2638 end Build_Wrapper_Specs;
2639
2640 ---------------------------
2641 -- Build_Find_Body_Index --
2642 ---------------------------
2643
2644 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id is
2645 Loc : constant Source_Ptr := Sloc (Typ);
2646 Ent : Entity_Id;
2647 E_Typ : Entity_Id;
2648 Has_F : Boolean := False;
2649 Index : Nat;
2650 If_St : Node_Id := Empty;
2651 Lo : Node_Id;
2652 Hi : Node_Id;
2653 Decls : List_Id := New_List;
2654 Ret : Node_Id := Empty;
2655 Spec : Node_Id;
2656 Siz : Node_Id := Empty;
2657
2658 procedure Add_If_Clause (Expr : Node_Id);
2659 -- Add test for range of current entry
2660
2661 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
2662 -- If a bound of an entry is given by a discriminant, retrieve the
2663 -- actual value of the discriminant from the enclosing object.
2664
2665 -------------------
2666 -- Add_If_Clause --
2667 -------------------
2668
2669 procedure Add_If_Clause (Expr : Node_Id) is
2670 Cond : Node_Id;
2671 Stats : constant List_Id :=
2672 New_List (
2673 Make_Simple_Return_Statement (Loc,
2674 Expression => Make_Integer_Literal (Loc, Index + 1)));
2675
2676 begin
2677 -- Index for current entry body
2678
2679 Index := Index + 1;
2680
2681 -- Compute total length of entry queues so far
2682
2683 if No (Siz) then
2684 Siz := Expr;
2685 else
2686 Siz :=
2687 Make_Op_Add (Loc,
2688 Left_Opnd => Siz,
2689 Right_Opnd => Expr);
2690 end if;
2691
2692 Cond :=
2693 Make_Op_Le (Loc,
2694 Left_Opnd => Make_Identifier (Loc, Name_uE),
2695 Right_Opnd => Siz);
2696
2697 -- Map entry queue indexes in the range of the current family
2698 -- into the current index, that designates the entry body.
2699
2700 if No (If_St) then
2701 If_St :=
2702 Make_Implicit_If_Statement (Typ,
2703 Condition => Cond,
2704 Then_Statements => Stats,
2705 Elsif_Parts => New_List);
2706 Ret := If_St;
2707
2708 else
2709 Append_To (Elsif_Parts (If_St),
2710 Make_Elsif_Part (Loc,
2711 Condition => Cond,
2712 Then_Statements => Stats));
2713 end if;
2714 end Add_If_Clause;
2715
2716 ------------------------------
2717 -- Convert_Discriminant_Ref --
2718 ------------------------------
2719
2720 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
2721 B : Node_Id;
2722
2723 begin
2724 if Is_Entity_Name (Bound)
2725 and then Ekind (Entity (Bound)) = E_Discriminant
2726 then
2727 B :=
2728 Make_Selected_Component (Loc,
2729 Prefix =>
2730 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
2731 Make_Explicit_Dereference (Loc,
2732 Make_Identifier (Loc, Name_uObject))),
2733 Selector_Name => Make_Identifier (Loc, Chars (Bound)));
2734 Set_Etype (B, Etype (Entity (Bound)));
2735 else
2736 B := New_Copy_Tree (Bound);
2737 end if;
2738
2739 return B;
2740 end Convert_Discriminant_Ref;
2741
2742 -- Start of processing for Build_Find_Body_Index
2743
2744 begin
2745 Spec := Build_Find_Body_Index_Spec (Typ);
2746
2747 Ent := First_Entity (Typ);
2748 while Present (Ent) loop
2749 if Ekind (Ent) = E_Entry_Family then
2750 Has_F := True;
2751 exit;
2752 end if;
2753
2754 Next_Entity (Ent);
2755 end loop;
2756
2757 if not Has_F then
2758
2759 -- If the protected type has no entry families, there is a one-one
2760 -- correspondence between entry queue and entry body.
2761
2762 Ret :=
2763 Make_Simple_Return_Statement (Loc,
2764 Expression => Make_Identifier (Loc, Name_uE));
2765
2766 else
2767 -- Suppose entries e1, e2, ... have size l1, l2, ... we generate
2768 -- the following:
2769
2770 -- if E <= l1 then return 1;
2771 -- elsif E <= l1 + l2 then return 2;
2772 -- ...
2773
2774 Index := 0;
2775 Siz := Empty;
2776 Ent := First_Entity (Typ);
2777
2778 Add_Object_Pointer (Loc, Typ, Decls);
2779
2780 while Present (Ent) loop
2781 if Ekind (Ent) = E_Entry then
2782 Add_If_Clause (Make_Integer_Literal (Loc, 1));
2783
2784 elsif Ekind (Ent) = E_Entry_Family then
2785 E_Typ := Entry_Index_Type (Ent);
2786 Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
2787 Lo := Convert_Discriminant_Ref (Type_Low_Bound (E_Typ));
2788 Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ, False));
2789 end if;
2790
2791 Next_Entity (Ent);
2792 end loop;
2793
2794 if Index = 1 then
2795 Decls := New_List;
2796 Ret :=
2797 Make_Simple_Return_Statement (Loc,
2798 Expression => Make_Integer_Literal (Loc, 1));
2799
2800 else
2801 pragma Assert (Present (Ret));
2802
2803 if Nkind (Ret) = N_If_Statement then
2804
2805 -- Ranges are in increasing order, so last one doesn't need
2806 -- guard.
2807
2808 declare
2809 Nod : constant Node_Id := Last (Elsif_Parts (Ret));
2810 begin
2811 Remove (Nod);
2812 Set_Else_Statements (Ret, Then_Statements (Nod));
2813 end;
2814 end if;
2815 end if;
2816 end if;
2817
2818 return
2819 Make_Subprogram_Body (Loc,
2820 Specification => Spec,
2821 Declarations => Decls,
2822 Handled_Statement_Sequence =>
2823 Make_Handled_Sequence_Of_Statements (Loc,
2824 Statements => New_List (Ret)));
2825 end Build_Find_Body_Index;
2826
2827 --------------------------------
2828 -- Build_Find_Body_Index_Spec --
2829 --------------------------------
2830
2831 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id is
2832 Loc : constant Source_Ptr := Sloc (Typ);
2833 Id : constant Entity_Id :=
2834 Make_Defining_Identifier (Loc,
2835 Chars => New_External_Name (Chars (Typ), 'F'));
2836 Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
2837 Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
2838
2839 begin
2840 return
2841 Make_Function_Specification (Loc,
2842 Defining_Unit_Name => Id,
2843 Parameter_Specifications => New_List (
2844 Make_Parameter_Specification (Loc,
2845 Defining_Identifier => Parm1,
2846 Parameter_Type =>
2847 New_Occurrence_Of (RTE (RE_Address), Loc)),
2848
2849 Make_Parameter_Specification (Loc,
2850 Defining_Identifier => Parm2,
2851 Parameter_Type =>
2852 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
2853
2854 Result_Definition => New_Occurrence_Of (
2855 RTE (RE_Protected_Entry_Index), Loc));
2856 end Build_Find_Body_Index_Spec;
2857
2858 -----------------------------------------------
2859 -- Build_Lock_Free_Protected_Subprogram_Body --
2860 -----------------------------------------------
2861
2862 function Build_Lock_Free_Protected_Subprogram_Body
2863 (N : Node_Id;
2864 Prot_Typ : Node_Id;
2865 Unprot_Spec : Node_Id) return Node_Id
2866 is
2867 Actuals : constant List_Id := New_List;
2868 Loc : constant Source_Ptr := Sloc (N);
2869 Spec : constant Node_Id := Specification (N);
2870 Unprot_Id : constant Entity_Id := Defining_Unit_Name (Unprot_Spec);
2871 Formal : Node_Id;
2872 Prot_Spec : Node_Id;
2873 Stmt : Node_Id;
2874
2875 begin
2876 -- Create the protected version of the body
2877
2878 Prot_Spec :=
2879 Build_Protected_Sub_Specification (N, Prot_Typ, Protected_Mode);
2880
2881 -- Build the actual parameters which appear in the call to the
2882 -- unprotected version of the body.
2883
2884 Formal := First (Parameter_Specifications (Prot_Spec));
2885 while Present (Formal) loop
2886 Append_To (Actuals,
2887 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
2888
2889 Next (Formal);
2890 end loop;
2891
2892 -- Function case, generate:
2893 -- return <Unprot_Func_Call>;
2894
2895 if Nkind (Spec) = N_Function_Specification then
2896 Stmt :=
2897 Make_Simple_Return_Statement (Loc,
2898 Expression =>
2899 Make_Function_Call (Loc,
2900 Name =>
2901 Make_Identifier (Loc, Chars (Unprot_Id)),
2902 Parameter_Associations => Actuals));
2903
2904 -- Procedure case, call the unprotected version
2905
2906 else
2907 Stmt :=
2908 Make_Procedure_Call_Statement (Loc,
2909 Name =>
2910 Make_Identifier (Loc, Chars (Unprot_Id)),
2911 Parameter_Associations => Actuals);
2912 end if;
2913
2914 return
2915 Make_Subprogram_Body (Loc,
2916 Declarations => Empty_List,
2917 Specification => Prot_Spec,
2918 Handled_Statement_Sequence =>
2919 Make_Handled_Sequence_Of_Statements (Loc,
2920 Statements => New_List (Stmt)));
2921 end Build_Lock_Free_Protected_Subprogram_Body;
2922
2923 -------------------------------------------------
2924 -- Build_Lock_Free_Unprotected_Subprogram_Body --
2925 -------------------------------------------------
2926
2927 -- Procedures which meet the lock-free implementation requirements and
2928 -- reference a unique scalar component Comp are expanded in the following
2929 -- manner:
2930
2931 -- procedure P (...) is
2932 -- Expected_Comp : constant Comp_Type :=
2933 -- Comp_Type
2934 -- (System.Atomic_Primitives.Lock_Free_Read_N
2935 -- (_Object.Comp'Address));
2936 -- begin
2937 -- loop
2938 -- declare
2939 -- <original declarations before the object renaming declaration
2940 -- of Comp>
2941 --
2942 -- Desired_Comp : Comp_Type := Expected_Comp;
2943 -- Comp : Comp_Type renames Desired_Comp;
2944 --
2945 -- <original delarations after the object renaming declaration
2946 -- of Comp>
2947 --
2948 -- begin
2949 -- <original statements>
2950 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
2951 -- (_Object.Comp'Address,
2952 -- Interfaces.Unsigned_N (Expected_Comp),
2953 -- Interfaces.Unsigned_N (Desired_Comp));
2954 -- end;
2955 -- end loop;
2956 -- end P;
2957
2958 -- Each return and raise statement of P is transformed into an atomic
2959 -- status check:
2960
2961 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
2962 -- (_Object.Comp'Address,
2963 -- Interfaces.Unsigned_N (Expected_Comp),
2964 -- Interfaces.Unsigned_N (Desired_Comp));
2965 -- then
2966 -- <original statement>
2967 -- else
2968 -- goto L0;
2969 -- end if;
2970
2971 -- Functions which meet the lock-free implementation requirements and
2972 -- reference a unique scalar component Comp are expanded in the following
2973 -- manner:
2974
2975 -- function F (...) return ... is
2976 -- <original declarations before the object renaming declaration
2977 -- of Comp>
2978 --
2979 -- Expected_Comp : constant Comp_Type :=
2980 -- Comp_Type
2981 -- (System.Atomic_Primitives.Lock_Free_Read_N
2982 -- (_Object.Comp'Address));
2983 -- Comp : Comp_Type renames Expected_Comp;
2984 --
2985 -- <original delarations after the object renaming declaration of
2986 -- Comp>
2987 --
2988 -- begin
2989 -- <original statements>
2990 -- end F;
2991
2992 function Build_Lock_Free_Unprotected_Subprogram_Body
2993 (N : Node_Id;
2994 Prot_Typ : Node_Id) return Node_Id
2995 is
2996 function Referenced_Component (N : Node_Id) return Entity_Id;
2997 -- Subprograms which meet the lock-free implementation criteria are
2998 -- allowed to reference only one unique component. Return the prival
2999 -- of the said component.
3000
3001 --------------------------
3002 -- Referenced_Component --
3003 --------------------------
3004
3005 function Referenced_Component (N : Node_Id) return Entity_Id is
3006 Comp : Entity_Id;
3007 Decl : Node_Id;
3008 Source_Comp : Entity_Id := Empty;
3009
3010 begin
3011 -- Find the unique source component which N references in its
3012 -- statements.
3013
3014 for Index in 1 .. Lock_Free_Subprogram_Table.Last loop
3015 declare
3016 Element : Lock_Free_Subprogram renames
3017 Lock_Free_Subprogram_Table.Table (Index);
3018 begin
3019 if Element.Sub_Body = N then
3020 Source_Comp := Element.Comp_Id;
3021 exit;
3022 end if;
3023 end;
3024 end loop;
3025
3026 if No (Source_Comp) then
3027 return Empty;
3028 end if;
3029
3030 -- Find the prival which corresponds to the source component within
3031 -- the declarations of N.
3032
3033 Decl := First (Declarations (N));
3034 while Present (Decl) loop
3035
3036 -- Privals appear as object renamings
3037
3038 if Nkind (Decl) = N_Object_Renaming_Declaration then
3039 Comp := Defining_Identifier (Decl);
3040
3041 if Present (Prival_Link (Comp))
3042 and then Prival_Link (Comp) = Source_Comp
3043 then
3044 return Comp;
3045 end if;
3046 end if;
3047
3048 Next (Decl);
3049 end loop;
3050
3051 return Empty;
3052 end Referenced_Component;
3053
3054 -- Local variables
3055
3056 Comp : constant Entity_Id := Referenced_Component (N);
3057 Loc : constant Source_Ptr := Sloc (N);
3058 Hand_Stmt_Seq : Node_Id := Handled_Statement_Sequence (N);
3059 Decls : List_Id := Declarations (N);
3060
3061 -- Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
3062
3063 begin
3064 -- Add renamings for the protection object, discriminals, privals, and
3065 -- the entry index constant for use by debugger.
3066
3067 Debug_Private_Data_Declarations (Decls);
3068
3069 -- Perform the lock-free expansion when the subprogram references a
3070 -- protected component.
3071
3072 if Present (Comp) then
3073 Protected_Component_Ref : declare
3074 Comp_Decl : constant Node_Id := Parent (Comp);
3075 Comp_Sel_Nam : constant Node_Id := Name (Comp_Decl);
3076 Comp_Type : constant Entity_Id := Etype (Comp);
3077
3078 Is_Procedure : constant Boolean :=
3079 Ekind (Corresponding_Spec (N)) = E_Procedure;
3080 -- Indicates if N is a protected procedure body
3081
3082 Block_Decls : List_Id := No_List;
3083 Try_Write : Entity_Id;
3084 Desired_Comp : Entity_Id;
3085 Decl : Node_Id;
3086 Label : Node_Id;
3087 Label_Id : Entity_Id := Empty;
3088 Read : Entity_Id;
3089 Expected_Comp : Entity_Id;
3090 Stmt : Node_Id;
3091 Stmts : List_Id :=
3092 New_Copy_List (Statements (Hand_Stmt_Seq));
3093 Typ_Size : Int;
3094 Unsigned : Entity_Id;
3095
3096 function Process_Node (N : Node_Id) return Traverse_Result;
3097 -- Transform a single node if it is a return statement, a raise
3098 -- statement or a reference to Comp.
3099
3100 procedure Process_Stmts (Stmts : List_Id);
3101 -- Given a statement sequence Stmts, wrap any return or raise
3102 -- statements in the following manner:
3103 --
3104 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
3105 -- (_Object.Comp'Address,
3106 -- Interfaces.Unsigned_N (Expected_Comp),
3107 -- Interfaces.Unsigned_N (Desired_Comp))
3108 -- then
3109 -- <Stmt>;
3110 -- else
3111 -- goto L0;
3112 -- end if;
3113
3114 ------------------
3115 -- Process_Node --
3116 ------------------
3117
3118 function Process_Node (N : Node_Id) return Traverse_Result is
3119
3120 procedure Wrap_Statement (Stmt : Node_Id);
3121 -- Wrap an arbitrary statement inside an if statement where the
3122 -- condition does an atomic check on the state of the object.
3123
3124 --------------------
3125 -- Wrap_Statement --
3126 --------------------
3127
3128 procedure Wrap_Statement (Stmt : Node_Id) is
3129 begin
3130 -- The first time through, create the declaration of a label
3131 -- which is used to skip the remainder of source statements
3132 -- if the state of the object has changed.
3133
3134 if No (Label_Id) then
3135 Label_Id :=
3136 Make_Identifier (Loc, New_External_Name ('L', 0));
3137 Set_Entity (Label_Id,
3138 Make_Defining_Identifier (Loc, Chars (Label_Id)));
3139 end if;
3140
3141 -- Generate:
3142 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
3143 -- (_Object.Comp'Address,
3144 -- Interfaces.Unsigned_N (Expected_Comp),
3145 -- Interfaces.Unsigned_N (Desired_Comp))
3146 -- then
3147 -- <Stmt>;
3148 -- else
3149 -- goto L0;
3150 -- end if;
3151
3152 Rewrite (Stmt,
3153 Make_Implicit_If_Statement (N,
3154 Condition =>
3155 Make_Function_Call (Loc,
3156 Name =>
3157 New_Occurrence_Of (Try_Write, Loc),
3158 Parameter_Associations => New_List (
3159 Make_Attribute_Reference (Loc,
3160 Prefix => Relocate_Node (Comp_Sel_Nam),
3161 Attribute_Name => Name_Address),
3162
3163 Unchecked_Convert_To (Unsigned,
3164 New_Occurrence_Of (Expected_Comp, Loc)),
3165
3166 Unchecked_Convert_To (Unsigned,
3167 New_Occurrence_Of (Desired_Comp, Loc)))),
3168
3169 Then_Statements => New_List (Relocate_Node (Stmt)),
3170
3171 Else_Statements => New_List (
3172 Make_Goto_Statement (Loc,
3173 Name =>
3174 New_Occurrence_Of (Entity (Label_Id), Loc)))));
3175 end Wrap_Statement;
3176
3177 -- Start of processing for Process_Node
3178
3179 begin
3180 -- Wrap each return and raise statement that appear inside a
3181 -- procedure. Skip the last return statement which is added by
3182 -- default since it is transformed into an exit statement.
3183
3184 if Is_Procedure
3185 and then ((Nkind (N) = N_Simple_Return_Statement
3186 and then N /= Last (Stmts))
3187 or else Nkind (N) = N_Extended_Return_Statement
3188 or else (Nkind (N) in
3189 N_Raise_xxx_Error | N_Raise_Statement
3190 and then Comes_From_Source (N)))
3191 then
3192 Wrap_Statement (N);
3193 return Skip;
3194 end if;
3195
3196 -- Force reanalysis
3197
3198 Set_Analyzed (N, False);
3199
3200 return OK;
3201 end Process_Node;
3202
3203 procedure Process_Nodes is new Traverse_Proc (Process_Node);
3204
3205 -------------------
3206 -- Process_Stmts --
3207 -------------------
3208
3209 procedure Process_Stmts (Stmts : List_Id) is
3210 Stmt : Node_Id;
3211 begin
3212 Stmt := First (Stmts);
3213 while Present (Stmt) loop
3214 Process_Nodes (Stmt);
3215 Next (Stmt);
3216 end loop;
3217 end Process_Stmts;
3218
3219 -- Start of processing for Protected_Component_Ref
3220
3221 begin
3222 -- Get the type size
3223
3224 if Known_Static_Esize (Comp_Type) then
3225 Typ_Size := UI_To_Int (Esize (Comp_Type));
3226
3227 -- If the Esize (Object_Size) is unknown at compile time, look at
3228 -- the RM_Size (Value_Size) since it may have been set by an
3229 -- explicit representation clause.
3230
3231 elsif Known_Static_RM_Size (Comp_Type) then
3232 Typ_Size := UI_To_Int (RM_Size (Comp_Type));
3233
3234 -- Should not happen since this has already been checked in
3235 -- Allows_Lock_Free_Implementation (see Sem_Ch9).
3236
3237 else
3238 raise Program_Error;
3239 end if;
3240
3241 -- Retrieve all relevant atomic routines and types
3242
3243 case Typ_Size is
3244 when 8 =>
3245 Try_Write := RTE (RE_Lock_Free_Try_Write_8);
3246 Read := RTE (RE_Lock_Free_Read_8);
3247 Unsigned := RTE (RE_Uint8);
3248
3249 when 16 =>
3250 Try_Write := RTE (RE_Lock_Free_Try_Write_16);
3251 Read := RTE (RE_Lock_Free_Read_16);
3252 Unsigned := RTE (RE_Uint16);
3253
3254 when 32 =>
3255 Try_Write := RTE (RE_Lock_Free_Try_Write_32);
3256 Read := RTE (RE_Lock_Free_Read_32);
3257 Unsigned := RTE (RE_Uint32);
3258
3259 when 64 =>
3260 Try_Write := RTE (RE_Lock_Free_Try_Write_64);
3261 Read := RTE (RE_Lock_Free_Read_64);
3262 Unsigned := RTE (RE_Uint64);
3263
3264 when others =>
3265 raise Program_Error;
3266 end case;
3267
3268 -- Generate:
3269 -- Expected_Comp : constant Comp_Type :=
3270 -- Comp_Type
3271 -- (System.Atomic_Primitives.Lock_Free_Read_N
3272 -- (_Object.Comp'Address));
3273
3274 Expected_Comp :=
3275 Make_Defining_Identifier (Loc,
3276 New_External_Name (Chars (Comp), Suffix => "_saved"));
3277
3278 Decl :=
3279 Make_Object_Declaration (Loc,
3280 Defining_Identifier => Expected_Comp,
3281 Object_Definition => New_Occurrence_Of (Comp_Type, Loc),
3282 Constant_Present => True,
3283 Expression =>
3284 Unchecked_Convert_To (Comp_Type,
3285 Make_Function_Call (Loc,
3286 Name => New_Occurrence_Of (Read, Loc),
3287 Parameter_Associations => New_List (
3288 Make_Attribute_Reference (Loc,
3289 Prefix => Relocate_Node (Comp_Sel_Nam),
3290 Attribute_Name => Name_Address)))));
3291
3292 -- Protected procedures
3293
3294 if Is_Procedure then
3295 -- Move the original declarations inside the generated block
3296
3297 Block_Decls := Decls;
3298
3299 -- Reset the declarations list of the protected procedure to
3300 -- contain only Decl.
3301
3302 Decls := New_List (Decl);
3303
3304 -- Generate:
3305 -- Desired_Comp : Comp_Type := Expected_Comp;
3306
3307 Desired_Comp :=
3308 Make_Defining_Identifier (Loc,
3309 New_External_Name (Chars (Comp), Suffix => "_current"));
3310
3311 -- Insert the declarations of Expected_Comp and Desired_Comp in
3312 -- the block declarations right before the renaming of the
3313 -- protected component.
3314
3315 Insert_Before (Comp_Decl,
3316 Make_Object_Declaration (Loc,
3317 Defining_Identifier => Desired_Comp,
3318 Object_Definition => New_Occurrence_Of (Comp_Type, Loc),
3319 Expression =>
3320 New_Occurrence_Of (Expected_Comp, Loc)));
3321
3322 -- Protected function
3323
3324 else
3325 Desired_Comp := Expected_Comp;
3326
3327 -- Insert the declaration of Expected_Comp in the function
3328 -- declarations right before the renaming of the protected
3329 -- component.
3330
3331 Insert_Before (Comp_Decl, Decl);
3332 end if;
3333
3334 -- Rewrite the protected component renaming declaration to be a
3335 -- renaming of Desired_Comp.
3336
3337 -- Generate:
3338 -- Comp : Comp_Type renames Desired_Comp;
3339
3340 Rewrite (Comp_Decl,
3341 Make_Object_Renaming_Declaration (Loc,
3342 Defining_Identifier =>
3343 Defining_Identifier (Comp_Decl),
3344 Subtype_Mark =>
3345 New_Occurrence_Of (Comp_Type, Loc),
3346 Name =>
3347 New_Occurrence_Of (Desired_Comp, Loc)));
3348
3349 -- Wrap any return or raise statements in Stmts in same the manner
3350 -- described in Process_Stmts.
3351
3352 Process_Stmts (Stmts);
3353
3354 -- Generate:
3355 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3356 -- (_Object.Comp'Address,
3357 -- Interfaces.Unsigned_N (Expected_Comp),
3358 -- Interfaces.Unsigned_N (Desired_Comp))
3359
3360 if Is_Procedure then
3361 Stmt :=
3362 Make_Exit_Statement (Loc,
3363 Condition =>
3364 Make_Function_Call (Loc,
3365 Name =>
3366 New_Occurrence_Of (Try_Write, Loc),
3367 Parameter_Associations => New_List (
3368 Make_Attribute_Reference (Loc,
3369 Prefix => Relocate_Node (Comp_Sel_Nam),
3370 Attribute_Name => Name_Address),
3371
3372 Unchecked_Convert_To (Unsigned,
3373 New_Occurrence_Of (Expected_Comp, Loc)),
3374
3375 Unchecked_Convert_To (Unsigned,
3376 New_Occurrence_Of (Desired_Comp, Loc)))));
3377
3378 -- Small optimization: transform the default return statement
3379 -- of a procedure into the atomic exit statement.
3380
3381 if Nkind (Last (Stmts)) = N_Simple_Return_Statement then
3382 Rewrite (Last (Stmts), Stmt);
3383 else
3384 Append_To (Stmts, Stmt);
3385 end if;
3386 end if;
3387
3388 -- Create the declaration of the label used to skip the rest of
3389 -- the source statements when the object state changes.
3390
3391 if Present (Label_Id) then
3392 Label := Make_Label (Loc, Label_Id);
3393 Append_To (Decls,
3394 Make_Implicit_Label_Declaration (Loc,
3395 Defining_Identifier => Entity (Label_Id),
3396 Label_Construct => Label));
3397 Append_To (Stmts, Label);
3398 end if;
3399
3400 -- Generate:
3401 -- loop
3402 -- declare
3403 -- <Decls>
3404 -- begin
3405 -- <Stmts>
3406 -- end;
3407 -- end loop;
3408
3409 if Is_Procedure then
3410 Stmts :=
3411 New_List (
3412 Make_Loop_Statement (Loc,
3413 Statements => New_List (
3414 Make_Block_Statement (Loc,
3415 Declarations => Block_Decls,
3416 Handled_Statement_Sequence =>
3417 Make_Handled_Sequence_Of_Statements (Loc,
3418 Statements => Stmts))),
3419 End_Label => Empty));
3420 end if;
3421
3422 Hand_Stmt_Seq :=
3423 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts);
3424 end Protected_Component_Ref;
3425 end if;
3426
3427 -- Make an unprotected version of the subprogram for use within the same
3428 -- object, with new name and extra parameter representing the object.
3429
3430 return
3431 Make_Subprogram_Body (Loc,
3432 Specification =>
3433 Build_Protected_Sub_Specification (N, Prot_Typ, Unprotected_Mode),
3434 Declarations => Decls,
3435 Handled_Statement_Sequence => Hand_Stmt_Seq);
3436 end Build_Lock_Free_Unprotected_Subprogram_Body;
3437
3438 -------------------------
3439 -- Build_Master_Entity --
3440 -------------------------
3441
3442 procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
3443 Loc : constant Source_Ptr := Sloc (Obj_Or_Typ);
3444 Context : Node_Id;
3445 Context_Id : Entity_Id;
3446 Decl : Node_Id;
3447 Decls : List_Id;
3448 Par : Node_Id;
3449
3450 begin
3451 -- No action needed if the run-time has no tasking support
3452
3453 if Global_No_Tasking then
3454 return;
3455 end if;
3456
3457 if Is_Itype (Obj_Or_Typ) then
3458 Par := Associated_Node_For_Itype (Obj_Or_Typ);
3459 else
3460 Par := Parent (Obj_Or_Typ);
3461 end if;
3462
3463 -- For transient scopes check if the master entity is already defined
3464
3465 if Is_Type (Obj_Or_Typ)
3466 and then Ekind (Scope (Obj_Or_Typ)) = E_Block
3467 and then Is_Internal (Scope (Obj_Or_Typ))
3468 then
3469 declare
3470 Master_Scope : constant Entity_Id :=
3471 Find_Master_Scope (Obj_Or_Typ);
3472 begin
3473 if Has_Master_Entity (Master_Scope)
3474 or else Is_Finalizer (Master_Scope)
3475 then
3476 return;
3477 end if;
3478
3479 if Present (Current_Entity_In_Scope (Name_uMaster)) then
3480 return;
3481 end if;
3482 end;
3483 end if;
3484
3485 -- When creating a master for a record component which is either a task
3486 -- or access-to-task, the enclosing record is the master scope and the
3487 -- proper insertion point is the component list.
3488
3489 if Is_Record_Type (Current_Scope) then
3490 Context := Par;
3491 Context_Id := Current_Scope;
3492 Decls := List_Containing (Context);
3493
3494 -- Default case for object declarations and access types. Note that the
3495 -- context is updated to the nearest enclosing body, block, package, or
3496 -- return statement.
3497
3498 else
3499 Find_Enclosing_Context (Par, Context, Context_Id, Decls);
3500 end if;
3501
3502 -- Nothing to do if the context already has a master; internally built
3503 -- finalizers don't need a master.
3504
3505 if Has_Master_Entity (Context_Id)
3506 or else Is_Finalizer (Context_Id)
3507 then
3508 return;
3509 end if;
3510
3511 Decl := Build_Master_Declaration (Loc);
3512
3513 -- The master is inserted at the start of the declarative list of the
3514 -- context.
3515
3516 Prepend_To (Decls, Decl);
3517
3518 -- In certain cases where transient scopes are involved, the immediate
3519 -- scope is not always the proper master scope. Ensure that the master
3520 -- declaration and entity appear in the same context.
3521
3522 if Context_Id /= Current_Scope then
3523 Push_Scope (Context_Id);
3524 Analyze (Decl);
3525 Pop_Scope;
3526 else
3527 Analyze (Decl);
3528 end if;
3529
3530 -- Mark the enclosing scope and its associated construct as being task
3531 -- masters.
3532
3533 Set_Has_Master_Entity (Context_Id);
3534
3535 while Present (Context)
3536 and then Nkind (Context) /= N_Compilation_Unit
3537 loop
3538 if Nkind (Context) in
3539 N_Block_Statement | N_Subprogram_Body | N_Task_Body
3540 then
3541 Set_Is_Task_Master (Context);
3542 exit;
3543
3544 elsif Nkind (Parent (Context)) = N_Subunit then
3545 Context := Corresponding_Stub (Parent (Context));
3546 end if;
3547
3548 Context := Parent (Context);
3549 end loop;
3550 end Build_Master_Entity;
3551
3552 ---------------------------
3553 -- Build_Master_Renaming --
3554 ---------------------------
3555
3556 procedure Build_Master_Renaming
3557 (Ptr_Typ : Entity_Id;
3558 Ins_Nod : Node_Id := Empty)
3559 is
3560 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
3561 Context : Node_Id;
3562 Master_Decl : Node_Id;
3563 Master_Id : Entity_Id;
3564
3565 begin
3566 -- No action needed if the run-time has no tasking support
3567
3568 if Global_No_Tasking then
3569 return;
3570 end if;
3571
3572 -- Determine the proper context to insert the master renaming
3573
3574 if Present (Ins_Nod) then
3575 Context := Ins_Nod;
3576
3577 elsif Is_Itype (Ptr_Typ) then
3578 Context := Associated_Node_For_Itype (Ptr_Typ);
3579
3580 -- When the context references a discriminant or a component of a
3581 -- private type and we are processing declarations in the private
3582 -- part of the enclosing package, we must insert the master renaming
3583 -- before the full declaration of the private type; otherwise the
3584 -- master renaming would be inserted in the public part of the
3585 -- package (and hence before the declaration of _master).
3586
3587 if In_Private_Part (Current_Scope) then
3588 declare
3589 Ctx : Node_Id := Context;
3590
3591 begin
3592 if Nkind (Context) = N_Discriminant_Specification then
3593 Ctx := Parent (Ctx);
3594 else
3595 while Nkind (Ctx) in
3596 N_Component_Declaration | N_Component_List
3597 loop
3598 Ctx := Parent (Ctx);
3599 end loop;
3600 end if;
3601
3602 if Nkind (Ctx) in N_Private_Type_Declaration
3603 | N_Private_Extension_Declaration
3604 then
3605 Context := Parent (Full_View (Defining_Identifier (Ctx)));
3606 end if;
3607 end;
3608 end if;
3609
3610 else
3611 Context := Parent (Ptr_Typ);
3612 end if;
3613
3614 -- Generate:
3615 -- <Ptr_Typ>M : Master_Id renames _Master;
3616 -- and add a numeric suffix to the name to ensure that it is
3617 -- unique in case other access types in nested constructs
3618 -- are homonyms of this one.
3619
3620 Master_Id :=
3621 Make_Defining_Identifier (Loc,
3622 New_External_Name (Chars (Ptr_Typ), 'M', -1));
3623
3624 Master_Decl :=
3625 Make_Object_Renaming_Declaration (Loc,
3626 Defining_Identifier => Master_Id,
3627 Subtype_Mark => New_Occurrence_Of (RTE (RE_Master_Id), Loc),
3628 Name => Make_Identifier (Loc, Name_uMaster));
3629
3630 Insert_Action (Context, Master_Decl);
3631
3632 -- The renamed master now services the access type
3633
3634 Set_Master_Id (Ptr_Typ, Master_Id);
3635 end Build_Master_Renaming;
3636
3637 ---------------------------
3638 -- Build_Protected_Entry --
3639 ---------------------------
3640
3641 function Build_Protected_Entry
3642 (N : Node_Id;
3643 Ent : Entity_Id;
3644 Pid : Node_Id) return Node_Id
3645 is
3646 Bod_Decls : constant List_Id := New_List;
3647 Decls : constant List_Id := Declarations (N);
3648 End_Lab : constant Node_Id :=
3649 End_Label (Handled_Statement_Sequence (N));
3650 End_Loc : constant Source_Ptr :=
3651 Sloc (Last (Statements (Handled_Statement_Sequence (N))));
3652 -- Used for the generated call to Complete_Entry_Body
3653
3654 Loc : constant Source_Ptr := Sloc (N);
3655
3656 Bod_Id : Entity_Id;
3657 Bod_Spec : Node_Id;
3658 Bod_Stmts : List_Id;
3659 Complete : Node_Id;
3660 Ohandle : Node_Id;
3661 Proc_Body : Node_Id;
3662
3663 EH_Loc : Source_Ptr;
3664 -- Used for the exception handler, inserted at end of the body
3665
3666 begin
3667 -- Set the source location on the exception handler only when debugging
3668 -- the expanded code (see Make_Implicit_Exception_Handler).
3669
3670 if Debug_Generated_Code then
3671 EH_Loc := End_Loc;
3672
3673 -- Otherwise the inserted code should not be visible to the debugger
3674
3675 else
3676 EH_Loc := No_Location;
3677 end if;
3678
3679 Bod_Id :=
3680 Make_Defining_Identifier (Loc,
3681 Chars => Chars (Protected_Body_Subprogram (Ent)));
3682 Bod_Spec := Build_Protected_Entry_Specification (Loc, Bod_Id, Empty);
3683
3684 -- Add the following declarations:
3685
3686 -- type poVP is access poV;
3687 -- _object : poVP := poVP (_O);
3688
3689 -- where _O is the formal parameter associated with the concurrent
3690 -- object. These declarations are needed for Complete_Entry_Body.
3691
3692 Add_Object_Pointer (Loc, Pid, Bod_Decls);
3693
3694 -- Add renamings for all formals, the Protection object, discriminals,
3695 -- privals and the entry index constant for use by debugger.
3696
3697 Add_Formal_Renamings (Bod_Spec, Bod_Decls, Ent, Loc);
3698 Debug_Private_Data_Declarations (Decls);
3699
3700 -- Put the declarations and the statements from the entry
3701
3702 Bod_Stmts :=
3703 New_List (
3704 Make_Block_Statement (Loc,
3705 Declarations => Decls,
3706 Handled_Statement_Sequence => Handled_Statement_Sequence (N)));
3707
3708 -- Analyze now and reset scopes for declarations so that Scope fields
3709 -- currently denoting the entry will now denote the block scope, and
3710 -- the block's scope will be set to the new procedure entity.
3711
3712 Analyze_Statements (Bod_Stmts);
3713
3714 Set_Scope (Entity (Identifier (First (Bod_Stmts))), Bod_Id);
3715
3716 Reset_Scopes_To
3717 (First (Bod_Stmts), Entity (Identifier (First (Bod_Stmts))));
3718
3719 case Corresponding_Runtime_Package (Pid) is
3720 when System_Tasking_Protected_Objects_Entries =>
3721 Append_To (Bod_Stmts,
3722 Make_Procedure_Call_Statement (End_Loc,
3723 Name =>
3724 New_Occurrence_Of (RTE (RE_Complete_Entry_Body), Loc),
3725 Parameter_Associations => New_List (
3726 Make_Attribute_Reference (End_Loc,
3727 Prefix =>
3728 Make_Selected_Component (End_Loc,
3729 Prefix =>
3730 Make_Identifier (End_Loc, Name_uObject),
3731 Selector_Name =>
3732 Make_Identifier (End_Loc, Name_uObject)),
3733 Attribute_Name => Name_Unchecked_Access))));
3734
3735 when System_Tasking_Protected_Objects_Single_Entry =>
3736
3737 -- Historically, a call to Complete_Single_Entry_Body was
3738 -- inserted, but it was a null procedure.
3739
3740 null;
3741
3742 when others =>
3743 raise Program_Error;
3744 end case;
3745
3746 -- When exceptions cannot be propagated, we never need to call
3747 -- Exception_Complete_Entry_Body.
3748
3749 if No_Exception_Handlers_Set then
3750 return
3751 Make_Subprogram_Body (Loc,
3752 Specification => Bod_Spec,
3753 Declarations => Bod_Decls,
3754 Handled_Statement_Sequence =>
3755 Make_Handled_Sequence_Of_Statements (Loc,
3756 Statements => Bod_Stmts,
3757 End_Label => End_Lab));
3758
3759 else
3760 Ohandle := Make_Others_Choice (Loc);
3761 Set_All_Others (Ohandle);
3762
3763 case Corresponding_Runtime_Package (Pid) is
3764 when System_Tasking_Protected_Objects_Entries =>
3765 Complete :=
3766 New_Occurrence_Of
3767 (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
3768
3769 when System_Tasking_Protected_Objects_Single_Entry =>
3770 Complete :=
3771 New_Occurrence_Of
3772 (RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
3773
3774 when others =>
3775 raise Program_Error;
3776 end case;
3777
3778 -- Establish link between subprogram body entity and source entry
3779
3780 Set_Corresponding_Protected_Entry (Bod_Id, Ent);
3781
3782 -- Create body of entry procedure. The renaming declarations are
3783 -- placed ahead of the block that contains the actual entry body.
3784
3785 Proc_Body :=
3786 Make_Subprogram_Body (Loc,
3787 Specification => Bod_Spec,
3788 Declarations => Bod_Decls,
3789 Handled_Statement_Sequence =>
3790 Make_Handled_Sequence_Of_Statements (Loc,
3791 Statements => Bod_Stmts,
3792 End_Label => End_Lab,
3793 Exception_Handlers => New_List (
3794 Make_Implicit_Exception_Handler (EH_Loc,
3795 Exception_Choices => New_List (Ohandle),
3796
3797 Statements => New_List (
3798 Make_Procedure_Call_Statement (EH_Loc,
3799 Name => Complete,
3800 Parameter_Associations => New_List (
3801 Make_Attribute_Reference (EH_Loc,
3802 Prefix =>
3803 Make_Selected_Component (EH_Loc,
3804 Prefix =>
3805 Make_Identifier (EH_Loc, Name_uObject),
3806 Selector_Name =>
3807 Make_Identifier (EH_Loc, Name_uObject)),
3808 Attribute_Name => Name_Unchecked_Access),
3809
3810 Make_Function_Call (EH_Loc,
3811 Name =>
3812 New_Occurrence_Of
3813 (RTE (RE_Get_GNAT_Exception), Loc)))))))));
3814
3815 Reset_Scopes_To (Proc_Body, Protected_Body_Subprogram (Ent));
3816 return Proc_Body;
3817 end if;
3818 end Build_Protected_Entry;
3819
3820 -----------------------------------------
3821 -- Build_Protected_Entry_Specification --
3822 -----------------------------------------
3823
3824 function Build_Protected_Entry_Specification
3825 (Loc : Source_Ptr;
3826 Def_Id : Entity_Id;
3827 Ent_Id : Entity_Id) return Node_Id
3828 is
3829 P : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uP);
3830
3831 begin
3832 Set_Debug_Info_Needed (Def_Id);
3833
3834 if Present (Ent_Id) then
3835 Append_Elmt (P, Accept_Address (Ent_Id));
3836 end if;
3837
3838 return
3839 Make_Procedure_Specification (Loc,
3840 Defining_Unit_Name => Def_Id,
3841 Parameter_Specifications => New_List (
3842 Make_Parameter_Specification (Loc,
3843 Defining_Identifier =>
3844 Make_Defining_Identifier (Loc, Name_uO),
3845 Parameter_Type =>
3846 New_Occurrence_Of (RTE (RE_Address), Loc)),
3847
3848 Make_Parameter_Specification (Loc,
3849 Defining_Identifier => P,
3850 Parameter_Type =>
3851 New_Occurrence_Of (RTE (RE_Address), Loc)),
3852
3853 Make_Parameter_Specification (Loc,
3854 Defining_Identifier =>
3855 Make_Defining_Identifier (Loc, Name_uE),
3856 Parameter_Type =>
3857 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))));
3858 end Build_Protected_Entry_Specification;
3859
3860 --------------------------
3861 -- Build_Protected_Spec --
3862 --------------------------
3863
3864 function Build_Protected_Spec
3865 (N : Node_Id;
3866 Obj_Type : Entity_Id;
3867 Ident : Entity_Id;
3868 Unprotected : Boolean := False) return List_Id
3869 is
3870 Loc : constant Source_Ptr := Sloc (N);
3871 Decl : Node_Id;
3872 Formal : Entity_Id;
3873 New_Plist : List_Id;
3874 New_Param : Node_Id;
3875
3876 begin
3877 New_Plist := New_List;
3878
3879 Formal := First_Formal (Ident);
3880 while Present (Formal) loop
3881 New_Param :=
3882 Make_Parameter_Specification (Loc,
3883 Defining_Identifier =>
3884 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
3885 Aliased_Present => Aliased_Present (Parent (Formal)),
3886 In_Present => In_Present (Parent (Formal)),
3887 Out_Present => Out_Present (Parent (Formal)),
3888 Parameter_Type => New_Occurrence_Of (Etype (Formal), Loc));
3889
3890 if Unprotected then
3891 Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
3892 Set_Ekind (Defining_Identifier (New_Param), Ekind (Formal));
3893 end if;
3894
3895 Append (New_Param, New_Plist);
3896 Next_Formal (Formal);
3897 end loop;
3898
3899 -- If the subprogram is a procedure and the context is not an access
3900 -- to protected subprogram, the parameter is in-out. Otherwise it is
3901 -- an in parameter.
3902
3903 Decl :=
3904 Make_Parameter_Specification (Loc,
3905 Defining_Identifier =>
3906 Make_Defining_Identifier (Loc, Name_uObject),
3907 In_Present => True,
3908 Out_Present =>
3909 (Etype (Ident) = Standard_Void_Type
3910 and then not Is_RTE (Obj_Type, RE_Address)),
3911 Parameter_Type =>
3912 New_Occurrence_Of (Obj_Type, Loc));
3913 Set_Debug_Info_Needed (Defining_Identifier (Decl));
3914 Prepend_To (New_Plist, Decl);
3915
3916 return New_Plist;
3917 end Build_Protected_Spec;
3918
3919 ---------------------------------------
3920 -- Build_Protected_Sub_Specification --
3921 ---------------------------------------
3922
3923 function Build_Protected_Sub_Specification
3924 (N : Node_Id;
3925 Prot_Typ : Entity_Id;
3926 Mode : Subprogram_Protection_Mode) return Node_Id
3927 is
3928 Loc : constant Source_Ptr := Sloc (N);
3929 Decl : Node_Id;
3930 Def_Id : Entity_Id;
3931 New_Id : Entity_Id;
3932 New_Plist : List_Id;
3933 New_Spec : Node_Id;
3934
3935 Append_Chr : constant array (Subprogram_Protection_Mode) of Character :=
3936 (Dispatching_Mode => ' ',
3937 Protected_Mode => 'P',
3938 Unprotected_Mode => 'N');
3939
3940 begin
3941 if Ekind (Defining_Unit_Name (Specification (N))) = E_Subprogram_Body
3942 then
3943 Decl := Unit_Declaration_Node (Corresponding_Spec (N));
3944 else
3945 Decl := N;
3946 end if;
3947
3948 Def_Id := Defining_Unit_Name (Specification (Decl));
3949
3950 New_Plist :=
3951 Build_Protected_Spec
3952 (Decl, Corresponding_Record_Type (Prot_Typ), Def_Id,
3953 Mode = Unprotected_Mode);
3954 New_Id :=
3955 Make_Defining_Identifier (Loc,
3956 Chars => Build_Selected_Name (Prot_Typ, Def_Id, Append_Chr (Mode)));
3957
3958 -- Reference the original nondispatching subprogram since the analysis
3959 -- of the object.operation notation may need its original name (see
3960 -- Sem_Ch4.Names_Match).
3961
3962 if Mode = Dispatching_Mode then
3963 Set_Ekind (New_Id, Ekind (Def_Id));
3964 Set_Original_Protected_Subprogram (New_Id, Def_Id);
3965 end if;
3966
3967 -- Link the protected or unprotected version to the original subprogram
3968 -- it emulates.
3969
3970 Set_Ekind (New_Id, Ekind (Def_Id));
3971 Set_Protected_Subprogram (New_Id, Def_Id);
3972
3973 -- The unprotected operation carries the user code, and debugging
3974 -- information must be generated for it, even though this spec does
3975 -- not come from source. It is also convenient to allow gdb to step
3976 -- into the protected operation, even though it only contains lock/
3977 -- unlock calls.
3978
3979 Set_Debug_Info_Needed (New_Id);
3980
3981 -- If a pragma Eliminate applies to the source entity, the internal
3982 -- subprograms will be eliminated as well.
3983
3984 Set_Is_Eliminated (New_Id, Is_Eliminated (Def_Id));
3985
3986 -- It seems we should set Has_Nested_Subprogram here, but instead we
3987 -- currently set it in Expand_N_Protected_Body, because the entity
3988 -- created here isn't the one that Corresponding_Spec of the body
3989 -- will later be set to, and that's the entity where it's needed. ???
3990
3991 Set_Has_Nested_Subprogram (New_Id, Has_Nested_Subprogram (Def_Id));
3992
3993 if Nkind (Specification (Decl)) = N_Procedure_Specification then
3994 New_Spec :=
3995 Make_Procedure_Specification (Loc,
3996 Defining_Unit_Name => New_Id,
3997 Parameter_Specifications => New_Plist);
3998
3999 -- Create a new specification for the anonymous subprogram type
4000
4001 else
4002 New_Spec :=
4003 Make_Function_Specification (Loc,
4004 Defining_Unit_Name => New_Id,
4005 Parameter_Specifications => New_Plist,
4006 Result_Definition =>
4007 Copy_Result_Type (Result_Definition (Specification (Decl))));
4008
4009 Set_Return_Present (Defining_Unit_Name (New_Spec));
4010 end if;
4011
4012 return New_Spec;
4013 end Build_Protected_Sub_Specification;
4014
4015 -------------------------------------
4016 -- Build_Protected_Subprogram_Body --
4017 -------------------------------------
4018
4019 function Build_Protected_Subprogram_Body
4020 (N : Node_Id;
4021 Pid : Node_Id;
4022 N_Op_Spec : Node_Id) return Node_Id
4023 is
4024 Exc_Safe : constant Boolean := not Might_Raise (N);
4025 -- True if N cannot raise an exception
4026
4027 Loc : constant Source_Ptr := Sloc (N);
4028 Op_Spec : constant Node_Id := Specification (N);
4029 P_Op_Spec : constant Node_Id :=
4030 Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
4031
4032 Lock_Kind : RE_Id;
4033 Lock_Name : Node_Id;
4034 Lock_Stmt : Node_Id;
4035 Object_Parm : Node_Id;
4036 Pformal : Node_Id;
4037 R : Node_Id;
4038 Return_Stmt : Node_Id := Empty; -- init to avoid gcc 3 warning
4039 Pre_Stmts : List_Id := No_List; -- init to avoid gcc 3 warning
4040 Stmts : List_Id;
4041 Sub_Body : Node_Id;
4042 Uactuals : List_Id;
4043 Unprot_Call : Node_Id;
4044
4045 begin
4046 -- Build a list of the formal parameters of the protected version of
4047 -- the subprogram to use as the actual parameters of the unprotected
4048 -- version.
4049
4050 Uactuals := New_List;
4051 Pformal := First (Parameter_Specifications (P_Op_Spec));
4052 while Present (Pformal) loop
4053 Append_To (Uactuals,
4054 Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))));
4055 Next (Pformal);
4056 end loop;
4057
4058 -- Make a call to the unprotected version of the subprogram built above
4059 -- for use by the protected version built below.
4060
4061 if Nkind (Op_Spec) = N_Function_Specification then
4062 if Exc_Safe then
4063 R := Make_Temporary (Loc, 'R');
4064
4065 Unprot_Call :=
4066 Make_Object_Declaration (Loc,
4067 Defining_Identifier => R,
4068 Constant_Present => True,
4069 Object_Definition =>
4070 New_Copy (Result_Definition (N_Op_Spec)),
4071 Expression =>
4072 Make_Function_Call (Loc,
4073 Name =>
4074 Make_Identifier (Loc,
4075 Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
4076 Parameter_Associations => Uactuals));
4077
4078 Return_Stmt :=
4079 Make_Simple_Return_Statement (Loc,
4080 Expression => New_Occurrence_Of (R, Loc));
4081
4082 else
4083 Unprot_Call :=
4084 Make_Simple_Return_Statement (Loc,
4085 Expression =>
4086 Make_Function_Call (Loc,
4087 Name =>
4088 Make_Identifier (Loc,
4089 Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
4090 Parameter_Associations => Uactuals));
4091 end if;
4092
4093 if Has_Aspect (Pid, Aspect_Exclusive_Functions)
4094 and then
4095 (No (Find_Value_Of_Aspect (Pid, Aspect_Exclusive_Functions))
4096 or else
4097 Is_True (Static_Boolean (Find_Value_Of_Aspect
4098 (Pid, Aspect_Exclusive_Functions))))
4099 then
4100 Lock_Kind := RE_Lock;
4101 else
4102 Lock_Kind := RE_Lock_Read_Only;
4103 end if;
4104 else
4105 Unprot_Call :=
4106 Make_Procedure_Call_Statement (Loc,
4107 Name =>
4108 Make_Identifier (Loc, Chars (Defining_Unit_Name (N_Op_Spec))),
4109 Parameter_Associations => Uactuals);
4110
4111 Lock_Kind := RE_Lock;
4112 end if;
4113
4114 -- Wrap call in block that will be covered by an at_end handler
4115
4116 if not Exc_Safe then
4117 Unprot_Call :=
4118 Make_Block_Statement (Loc,
4119 Handled_Statement_Sequence =>
4120 Make_Handled_Sequence_Of_Statements (Loc,
4121 Statements => New_List (Unprot_Call)));
4122 end if;
4123
4124 -- Make the protected subprogram body. This locks the protected
4125 -- object and calls the unprotected version of the subprogram.
4126
4127 case Corresponding_Runtime_Package (Pid) is
4128 when System_Tasking_Protected_Objects_Entries =>
4129 Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entries), Loc);
4130
4131 when System_Tasking_Protected_Objects_Single_Entry =>
4132 Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entry), Loc);
4133
4134 when System_Tasking_Protected_Objects =>
4135 Lock_Name := New_Occurrence_Of (RTE (Lock_Kind), Loc);
4136
4137 when others =>
4138 raise Program_Error;
4139 end case;
4140
4141 Object_Parm :=
4142 Make_Attribute_Reference (Loc,
4143 Prefix =>
4144 Make_Selected_Component (Loc,
4145 Prefix => Make_Identifier (Loc, Name_uObject),
4146 Selector_Name => Make_Identifier (Loc, Name_uObject)),
4147 Attribute_Name => Name_Unchecked_Access);
4148
4149 Lock_Stmt :=
4150 Make_Procedure_Call_Statement (Loc,
4151 Name => Lock_Name,
4152 Parameter_Associations => New_List (Object_Parm));
4153
4154 if Abort_Allowed then
4155 Stmts := New_List (
4156 Build_Runtime_Call (Loc, RE_Abort_Defer),
4157 Lock_Stmt);
4158
4159 else
4160 Stmts := New_List (Lock_Stmt);
4161 end if;
4162
4163 if not Exc_Safe then
4164 Append (Unprot_Call, Stmts);
4165 else
4166 if Nkind (Op_Spec) = N_Function_Specification then
4167 Pre_Stmts := Stmts;
4168 Stmts := Empty_List;
4169 else
4170 Append (Unprot_Call, Stmts);
4171 end if;
4172
4173 -- Historical note: Previously, call to the cleanup was inserted
4174 -- here. This is now done by Build_Protected_Subprogram_Call_Cleanup,
4175 -- which is also shared by the 'not Exc_Safe' path.
4176
4177 Build_Protected_Subprogram_Call_Cleanup (Op_Spec, Pid, Loc, Stmts);
4178
4179 if Nkind (Op_Spec) = N_Function_Specification then
4180 Append_To (Stmts, Return_Stmt);
4181 Append_To (Pre_Stmts,
4182 Make_Block_Statement (Loc,
4183 Declarations => New_List (Unprot_Call),
4184 Handled_Statement_Sequence =>
4185 Make_Handled_Sequence_Of_Statements (Loc,
4186 Statements => Stmts)));
4187 Stmts := Pre_Stmts;
4188 end if;
4189 end if;
4190
4191 Sub_Body :=
4192 Make_Subprogram_Body (Loc,
4193 Declarations => Empty_List,
4194 Specification => P_Op_Spec,
4195 Handled_Statement_Sequence =>
4196 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
4197
4198 -- Mark this subprogram as a protected subprogram body so that the
4199 -- cleanup will be inserted. This is done only in the 'not Exc_Safe'
4200 -- path as otherwise the cleanup has already been inserted.
4201
4202 if not Exc_Safe then
4203 Set_Is_Protected_Subprogram_Body (Sub_Body);
4204 end if;
4205
4206 return Sub_Body;
4207 end Build_Protected_Subprogram_Body;
4208
4209 -------------------------------------
4210 -- Build_Protected_Subprogram_Call --
4211 -------------------------------------
4212
4213 procedure Build_Protected_Subprogram_Call
4214 (N : Node_Id;
4215 Name : Node_Id;
4216 Rec : Node_Id;
4217 External : Boolean := True)
4218 is
4219 Loc : constant Source_Ptr := Sloc (N);
4220 Sub : constant Entity_Id := Entity (Name);
4221 New_Sub : Node_Id;
4222 Params : List_Id;
4223
4224 begin
4225 if External then
4226 New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
4227 else
4228 New_Sub :=
4229 New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
4230 end if;
4231
4232 if Present (Parameter_Associations (N)) then
4233 Params := New_Copy_List_Tree (Parameter_Associations (N));
4234 else
4235 Params := New_List;
4236 end if;
4237
4238 -- If the type is an untagged derived type, convert to the root type,
4239 -- which is the one on which the operations are defined.
4240
4241 if Nkind (Rec) = N_Unchecked_Type_Conversion
4242 and then not Is_Tagged_Type (Etype (Rec))
4243 and then Is_Derived_Type (Etype (Rec))
4244 then
4245 Set_Etype (Rec, Root_Type (Etype (Rec)));
4246 Set_Subtype_Mark (Rec,
4247 New_Occurrence_Of (Root_Type (Etype (Rec)), Sloc (N)));
4248 end if;
4249
4250 Prepend (Rec, Params);
4251
4252 if Ekind (Sub) = E_Procedure then
4253 Rewrite (N,
4254 Make_Procedure_Call_Statement (Loc,
4255 Name => New_Sub,
4256 Parameter_Associations => Params));
4257
4258 else
4259 pragma Assert (Ekind (Sub) = E_Function);
4260 Rewrite (N,
4261 Make_Function_Call (Loc,
4262 Name => New_Sub,
4263 Parameter_Associations => Params));
4264
4265 -- Preserve type of call for subsequent processing (required for
4266 -- call to Wrap_Transient_Expression in the case of a shared passive
4267 -- protected).
4268
4269 Set_Etype (N, Etype (New_Sub));
4270 end if;
4271
4272 if External
4273 and then Nkind (Rec) = N_Unchecked_Type_Conversion
4274 and then Is_Entity_Name (Expression (Rec))
4275 and then Is_Shared_Passive (Entity (Expression (Rec)))
4276 then
4277 Add_Shared_Var_Lock_Procs (N);
4278 end if;
4279 end Build_Protected_Subprogram_Call;
4280
4281 ---------------------------------------------
4282 -- Build_Protected_Subprogram_Call_Cleanup --
4283 ---------------------------------------------
4284
4285 procedure Build_Protected_Subprogram_Call_Cleanup
4286 (Op_Spec : Node_Id;
4287 Conc_Typ : Node_Id;
4288 Loc : Source_Ptr;
4289 Stmts : List_Id)
4290 is
4291 Nam : Node_Id;
4292
4293 begin
4294 -- If the associated protected object has entries, a protected
4295 -- procedure has to service entry queues. In this case generate:
4296
4297 -- Service_Entries (_object._object'Access);
4298
4299 if Nkind (Op_Spec) = N_Procedure_Specification
4300 and then Has_Entries (Conc_Typ)
4301 then
4302 case Corresponding_Runtime_Package (Conc_Typ) is
4303 when System_Tasking_Protected_Objects_Entries =>
4304 Nam := New_Occurrence_Of (RTE (RE_Service_Entries), Loc);
4305
4306 when System_Tasking_Protected_Objects_Single_Entry =>
4307 Nam := New_Occurrence_Of (RTE (RE_Service_Entry), Loc);
4308
4309 when others =>
4310 raise Program_Error;
4311 end case;
4312
4313 Append_To (Stmts,
4314 Make_Procedure_Call_Statement (Loc,
4315 Name => Nam,
4316 Parameter_Associations => New_List (
4317 Make_Attribute_Reference (Loc,
4318 Prefix =>
4319 Make_Selected_Component (Loc,
4320 Prefix => Make_Identifier (Loc, Name_uObject),
4321 Selector_Name => Make_Identifier (Loc, Name_uObject)),
4322 Attribute_Name => Name_Unchecked_Access))));
4323
4324 else
4325 -- Generate:
4326 -- Unlock (_object._object'Access);
4327
4328 case Corresponding_Runtime_Package (Conc_Typ) is
4329 when System_Tasking_Protected_Objects_Entries =>
4330 Nam := New_Occurrence_Of (RTE (RE_Unlock_Entries), Loc);
4331
4332 when System_Tasking_Protected_Objects_Single_Entry =>
4333 Nam := New_Occurrence_Of (RTE (RE_Unlock_Entry), Loc);
4334
4335 when System_Tasking_Protected_Objects =>
4336 Nam := New_Occurrence_Of (RTE (RE_Unlock), Loc);
4337
4338 when others =>
4339 raise Program_Error;
4340 end case;
4341
4342 Append_To (Stmts,
4343 Make_Procedure_Call_Statement (Loc,
4344 Name => Nam,
4345 Parameter_Associations => New_List (
4346 Make_Attribute_Reference (Loc,
4347 Prefix =>
4348 Make_Selected_Component (Loc,
4349 Prefix => Make_Identifier (Loc, Name_uObject),
4350 Selector_Name => Make_Identifier (Loc, Name_uObject)),
4351 Attribute_Name => Name_Unchecked_Access))));
4352 end if;
4353
4354 -- Generate:
4355 -- Abort_Undefer;
4356
4357 if Abort_Allowed then
4358 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Abort_Undefer));
4359 end if;
4360 end Build_Protected_Subprogram_Call_Cleanup;
4361
4362 -------------------------
4363 -- Build_Selected_Name --
4364 -------------------------
4365
4366 function Build_Selected_Name
4367 (Prefix : Entity_Id;
4368 Selector : Entity_Id;
4369 Append_Char : Character := ' ') return Name_Id
4370 is
4371 Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
4372 Select_Len : Natural;
4373
4374 begin
4375 Get_Name_String (Chars (Selector));
4376 Select_Len := Name_Len;
4377 Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
4378 Get_Name_String (Chars (Prefix));
4379
4380 -- If scope is anonymous type, discard suffix to recover name of
4381 -- single protected object. Otherwise use protected type name.
4382
4383 if Name_Buffer (Name_Len) = 'T' then
4384 Name_Len := Name_Len - 1;
4385 end if;
4386
4387 Add_Str_To_Name_Buffer ("__");
4388 for J in 1 .. Select_Len loop
4389 Add_Char_To_Name_Buffer (Select_Buffer (J));
4390 end loop;
4391
4392 -- Now add the Append_Char if specified. The encoding to follow
4393 -- depends on the type of entity. If Append_Char is either 'N' or 'P',
4394 -- then the entity is associated to a protected type subprogram.
4395 -- Otherwise, it is a protected type entry. For each case, the
4396 -- encoding to follow for the suffix is documented in exp_dbug.ads.
4397
4398 -- It would be better to encapsulate this as a routine in Exp_Dbug ???
4399
4400 if Append_Char /= ' ' then
4401 if Append_Char = 'P' or Append_Char = 'N' then
4402 Add_Char_To_Name_Buffer (Append_Char);
4403 return Name_Find;
4404 else
4405 Add_Str_To_Name_Buffer ((1 => '_', 2 => Append_Char));
4406 return New_External_Name (Name_Find, ' ', -1);
4407 end if;
4408 else
4409 return Name_Find;
4410 end if;
4411 end Build_Selected_Name;
4412
4413 -----------------------------
4414 -- Build_Simple_Entry_Call --
4415 -----------------------------
4416
4417 -- A task entry call is converted to a call to Call_Simple
4418
4419 -- declare
4420 -- P : parms := (parm, parm, parm);
4421 -- begin
4422 -- Call_Simple (acceptor-task, entry-index, P'Address);
4423 -- parm := P.param;
4424 -- parm := P.param;
4425 -- ...
4426 -- end;
4427
4428 -- Here Pnn is an aggregate of the type constructed for the entry to hold
4429 -- the parameters, and the constructed aggregate value contains either the
4430 -- parameters or, in the case of non-elementary types, references to these
4431 -- parameters. Then the address of this aggregate is passed to the runtime
4432 -- routine, along with the task id value and the task entry index value.
4433 -- Pnn is only required if parameters are present.
4434
4435 -- The assignments after the call are present only in the case of in-out
4436 -- or out parameters for elementary types, and are used to assign back the
4437 -- resulting values of such parameters.
4438
4439 -- Note: the reason that we insert a block here is that in the context
4440 -- of selects, conditional entry calls etc. the entry call statement
4441 -- appears on its own, not as an element of a list.
4442
4443 -- A protected entry call is converted to a Protected_Entry_Call:
4444
4445 -- declare
4446 -- P : E1_Params := (param, param, param);
4447 -- Pnn : Boolean;
4448 -- Bnn : Communications_Block;
4449
4450 -- declare
4451 -- P : E1_Params := (param, param, param);
4452 -- Bnn : Communications_Block;
4453
4454 -- begin
4455 -- Protected_Entry_Call (
4456 -- Object => po._object'Access,
4457 -- E => <entry index>;
4458 -- Uninterpreted_Data => P'Address;
4459 -- Mode => Simple_Call;
4460 -- Block => Bnn);
4461 -- parm := P.param;
4462 -- parm := P.param;
4463 -- ...
4464 -- end;
4465
4466 procedure Build_Simple_Entry_Call
4467 (N : Node_Id;
4468 Concval : Node_Id;
4469 Ename : Node_Id;
4470 Index : Node_Id)
4471 is
4472 begin
4473 Expand_Call (N);
4474
4475 -- If call has been inlined, nothing left to do
4476
4477 if Nkind (N) = N_Block_Statement then
4478 return;
4479 end if;
4480
4481 -- Convert entry call to Call_Simple call
4482
4483 declare
4484 Loc : constant Source_Ptr := Sloc (N);
4485 Parms : constant List_Id := Parameter_Associations (N);
4486 Stats : constant List_Id := New_List;
4487 Actual : Node_Id;
4488 Call : Node_Id;
4489 Comm_Name : Entity_Id;
4490 Conctyp : Node_Id;
4491 Decls : List_Id;
4492 Ent : Entity_Id;
4493 Ent_Acc : Entity_Id;
4494 Formal : Node_Id;
4495 Iface_Tag : Entity_Id;
4496 Iface_Typ : Entity_Id;
4497 N_Node : Node_Id;
4498 N_Var : Node_Id;
4499 P : Entity_Id;
4500 Parm1 : Node_Id;
4501 Parm2 : Node_Id;
4502 Parm3 : Node_Id;
4503 Pdecl : Node_Id;
4504 Plist : List_Id;
4505 X : Entity_Id;
4506 Xdecl : Node_Id;
4507
4508 begin
4509 -- Simple entry and entry family cases merge here
4510
4511 Ent := Entity (Ename);
4512 Ent_Acc := Entry_Parameters_Type (Ent);
4513 Conctyp := Etype (Concval);
4514
4515 -- Special case for protected subprogram calls
4516
4517 if Is_Protected_Type (Conctyp)
4518 and then Is_Subprogram (Entity (Ename))
4519 then
4520 if not Is_Eliminated (Entity (Ename)) then
4521 Build_Protected_Subprogram_Call
4522 (N, Ename, Convert_Concurrent (Concval, Conctyp));
4523 Analyze (N);
4524 end if;
4525
4526 return;
4527 end if;
4528
4529 -- First parameter is the Task_Id value from the task value or the
4530 -- Object from the protected object value, obtained by selecting
4531 -- the _Task_Id or _Object from the result of doing an unchecked
4532 -- conversion to convert the value to the corresponding record type.
4533
4534 if Nkind (Concval) = N_Function_Call
4535 and then Is_Task_Type (Conctyp)
4536 and then Ada_Version >= Ada_2005
4537 then
4538 declare
4539 ExpR : constant Node_Id := Relocate_Node (Concval);
4540 Obj : constant Entity_Id := Make_Temporary (Loc, 'F', ExpR);
4541 Decl : Node_Id;
4542
4543 begin
4544 Decl :=
4545 Make_Object_Declaration (Loc,
4546 Defining_Identifier => Obj,
4547 Object_Definition => New_Occurrence_Of (Conctyp, Loc),
4548 Expression => ExpR);
4549 Set_Etype (Obj, Conctyp);
4550 Decls := New_List (Decl);
4551 Rewrite (Concval, New_Occurrence_Of (Obj, Loc));
4552 end;
4553
4554 else
4555 Decls := New_List;
4556 end if;
4557
4558 Parm1 := Concurrent_Ref (Concval);
4559
4560 -- Second parameter is the entry index, computed by the routine
4561 -- provided for this purpose. The value of this expression is
4562 -- assigned to an intermediate variable to assure that any entry
4563 -- family index expressions are evaluated before the entry
4564 -- parameters.
4565
4566 if not Is_Protected_Type (Conctyp)
4567 or else
4568 Corresponding_Runtime_Package (Conctyp) =
4569 System_Tasking_Protected_Objects_Entries
4570 then
4571 X := Make_Defining_Identifier (Loc, Name_uX);
4572
4573 Xdecl :=
4574 Make_Object_Declaration (Loc,
4575 Defining_Identifier => X,
4576 Object_Definition =>
4577 New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc),
4578 Expression => Actual_Index_Expression (
4579 Loc, Entity (Ename), Index, Concval));
4580
4581 Append_To (Decls, Xdecl);
4582 Parm2 := New_Occurrence_Of (X, Loc);
4583
4584 else
4585 Xdecl := Empty;
4586 Parm2 := Empty;
4587 end if;
4588
4589 -- The third parameter is the packaged parameters. If there are
4590 -- none, then it is just the null address, since nothing is passed.
4591
4592 if No (Parms) then
4593 Parm3 := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
4594 P := Empty;
4595
4596 -- Case of parameters present, where third argument is the address
4597 -- of a packaged record containing the required parameter values.
4598
4599 else
4600 -- First build a list of parameter values, which are references to
4601 -- objects of the parameter types.
4602
4603 Plist := New_List;
4604
4605 Actual := First_Actual (N);
4606 Formal := First_Formal (Ent);
4607 while Present (Actual) loop
4608
4609 -- If it is a by-copy type, copy it to a new variable. The
4610 -- packaged record has a field that points to this variable.
4611
4612 if Is_By_Copy_Type (Etype (Actual)) then
4613 N_Node :=
4614 Make_Object_Declaration (Loc,
4615 Defining_Identifier => Make_Temporary (Loc, 'J'),
4616 Aliased_Present => True,
4617 Object_Definition =>
4618 New_Occurrence_Of (Etype (Formal), Loc));
4619
4620 -- Mark the object as not needing initialization since the
4621 -- initialization is performed separately, avoiding errors
4622 -- on cases such as formals of null-excluding access types.
4623
4624 Set_No_Initialization (N_Node);
4625
4626 -- We must make a separate assignment statement for the
4627 -- case of limited types. We cannot assign it unless the
4628 -- Assignment_OK flag is set first. An out formal of an
4629 -- access type or whose type has a Default_Value must also
4630 -- be initialized from the actual (see RM 6.4.1 (13-13.1)),
4631 -- but no constraint, predicate, or null-exclusion check is
4632 -- applied before the call.
4633
4634 if Ekind (Formal) /= E_Out_Parameter
4635 or else Is_Access_Type (Etype (Formal))
4636 or else
4637 (Is_Scalar_Type (Etype (Formal))
4638 and then
4639 Present (Default_Aspect_Value (Etype (Formal))))
4640 then
4641 N_Var :=
4642 New_Occurrence_Of (Defining_Identifier (N_Node), Loc);
4643 Set_Assignment_OK (N_Var);
4644 Append_To (Stats,
4645 Make_Assignment_Statement (Loc,
4646 Name => N_Var,
4647 Expression => Relocate_Node (Actual)));
4648
4649 -- Mark the object as internal, so we don't later reset
4650 -- No_Initialization flag in Default_Initialize_Object,
4651 -- which would lead to needless default initialization.
4652 -- We don't set this outside the if statement, because
4653 -- out scalar parameters without Default_Value do require
4654 -- default initialization if Initialize_Scalars applies.
4655
4656 Set_Is_Internal (Defining_Identifier (N_Node));
4657
4658 -- If actual is an out parameter of a null-excluding
4659 -- access type, there is access check on entry, so set
4660 -- Suppress_Assignment_Checks on the generated statement
4661 -- that assigns the actual to the parameter block.
4662
4663 Set_Suppress_Assignment_Checks (Last (Stats));
4664 end if;
4665
4666 Append (N_Node, Decls);
4667
4668 Append_To (Plist,
4669 Make_Attribute_Reference (Loc,
4670 Attribute_Name => Name_Unchecked_Access,
4671 Prefix =>
4672 New_Occurrence_Of
4673 (Defining_Identifier (N_Node), Loc)));
4674
4675 else
4676 -- Interface class-wide formal
4677
4678 if Ada_Version >= Ada_2005
4679 and then Ekind (Etype (Formal)) = E_Class_Wide_Type
4680 and then Is_Interface (Etype (Formal))
4681 then
4682 Iface_Typ := Etype (Etype (Formal));
4683
4684 -- Generate:
4685 -- formal_iface_type! (actual.iface_tag)'reference
4686
4687 Iface_Tag :=
4688 Find_Interface_Tag (Etype (Actual), Iface_Typ);
4689 pragma Assert (Present (Iface_Tag));
4690
4691 Append_To (Plist,
4692 Make_Reference (Loc,
4693 Unchecked_Convert_To (Iface_Typ,
4694 Make_Selected_Component (Loc,
4695 Prefix =>
4696 Relocate_Node (Actual),
4697 Selector_Name =>
4698 New_Occurrence_Of (Iface_Tag, Loc)))));
4699 else
4700 -- Generate:
4701 -- actual'reference
4702
4703 Append_To (Plist,
4704 Make_Reference (Loc, Relocate_Node (Actual)));
4705 end if;
4706 end if;
4707
4708 Next_Actual (Actual);
4709 Next_Formal_With_Extras (Formal);
4710 end loop;
4711
4712 -- Now build the declaration of parameters initialized with the
4713 -- aggregate containing this constructed parameter list.
4714
4715 P := Make_Defining_Identifier (Loc, Name_uP);
4716
4717 Pdecl :=
4718 Make_Object_Declaration (Loc,
4719 Defining_Identifier => P,
4720 Object_Definition =>
4721 New_Occurrence_Of (Designated_Type (Ent_Acc), Loc),
4722 Expression =>
4723 Make_Aggregate (Loc, Expressions => Plist));
4724
4725 Parm3 :=
4726 Make_Attribute_Reference (Loc,
4727 Prefix => New_Occurrence_Of (P, Loc),
4728 Attribute_Name => Name_Address);
4729
4730 Append (Pdecl, Decls);
4731 end if;
4732
4733 -- Now we can create the call, case of protected type
4734
4735 if Is_Protected_Type (Conctyp) then
4736 case Corresponding_Runtime_Package (Conctyp) is
4737 when System_Tasking_Protected_Objects_Entries =>
4738
4739 -- Change the type of the index declaration
4740
4741 Set_Object_Definition (Xdecl,
4742 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc));
4743
4744 -- Some additional declarations for protected entry calls
4745
4746 if No (Decls) then
4747 Decls := New_List;
4748 end if;
4749
4750 -- Bnn : Communications_Block;
4751
4752 Comm_Name := Make_Temporary (Loc, 'B');
4753
4754 Append_To (Decls,
4755 Make_Object_Declaration (Loc,
4756 Defining_Identifier => Comm_Name,
4757 Object_Definition =>
4758 New_Occurrence_Of
4759 (RTE (RE_Communication_Block), Loc)));
4760
4761 -- Some additional statements for protected entry calls
4762
4763 -- Protected_Entry_Call
4764 -- (Object => po._object'Access,
4765 -- E => <entry index>;
4766 -- Uninterpreted_Data => P'Address;
4767 -- Mode => Simple_Call;
4768 -- Block => Bnn);
4769
4770 Call :=
4771 Make_Procedure_Call_Statement (Loc,
4772 Name =>
4773 New_Occurrence_Of (RTE (RE_Protected_Entry_Call), Loc),
4774
4775 Parameter_Associations => New_List (
4776 Make_Attribute_Reference (Loc,
4777 Attribute_Name => Name_Unchecked_Access,
4778 Prefix => Parm1),
4779 Parm2,
4780 Parm3,
4781 New_Occurrence_Of (RTE (RE_Simple_Call), Loc),
4782 New_Occurrence_Of (Comm_Name, Loc)));
4783
4784 when System_Tasking_Protected_Objects_Single_Entry =>
4785
4786 -- Protected_Single_Entry_Call
4787 -- (Object => po._object'Access,
4788 -- Uninterpreted_Data => P'Address);
4789
4790 Call :=
4791 Make_Procedure_Call_Statement (Loc,
4792 Name =>
4793 New_Occurrence_Of
4794 (RTE (RE_Protected_Single_Entry_Call), Loc),
4795
4796 Parameter_Associations => New_List (
4797 Make_Attribute_Reference (Loc,
4798 Attribute_Name => Name_Unchecked_Access,
4799 Prefix => Parm1),
4800 Parm3));
4801
4802 when others =>
4803 raise Program_Error;
4804 end case;
4805
4806 -- Case of task type
4807
4808 else
4809 Call :=
4810 Make_Procedure_Call_Statement (Loc,
4811 Name =>
4812 New_Occurrence_Of (RTE (RE_Call_Simple), Loc),
4813 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
4814
4815 end if;
4816
4817 Append_To (Stats, Call);
4818
4819 -- If there are out or in/out parameters by copy add assignment
4820 -- statements for the result values.
4821
4822 if Present (Parms) then
4823 Actual := First_Actual (N);
4824 Formal := First_Formal (Ent);
4825
4826 Set_Assignment_OK (Actual);
4827 while Present (Actual) loop
4828 if Is_By_Copy_Type (Etype (Actual))
4829 and then Ekind (Formal) /= E_In_Parameter
4830 then
4831 N_Node :=
4832 Make_Assignment_Statement (Loc,
4833 Name => New_Copy (Actual),
4834 Expression =>
4835 Make_Explicit_Dereference (Loc,
4836 Make_Selected_Component (Loc,
4837 Prefix => New_Occurrence_Of (P, Loc),
4838 Selector_Name =>
4839 Make_Identifier (Loc, Chars (Formal)))));
4840
4841 -- In all cases (including limited private types) we want
4842 -- the assignment to be valid.
4843
4844 Set_Assignment_OK (Name (N_Node));
4845
4846 -- If the call is the triggering alternative in an
4847 -- asynchronous select, or the entry_call alternative of a
4848 -- conditional entry call, the assignments for in-out
4849 -- parameters are incorporated into the statement list that
4850 -- follows, so that there are executed only if the entry
4851 -- call succeeds.
4852
4853 if (Nkind (Parent (N)) = N_Triggering_Alternative
4854 and then N = Triggering_Statement (Parent (N)))
4855 or else
4856 (Nkind (Parent (N)) = N_Entry_Call_Alternative
4857 and then N = Entry_Call_Statement (Parent (N)))
4858 then
4859 if No (Statements (Parent (N))) then
4860 Set_Statements (Parent (N), New_List);
4861 end if;
4862
4863 Prepend (N_Node, Statements (Parent (N)));
4864
4865 else
4866 Insert_After (Call, N_Node);
4867 end if;
4868 end if;
4869
4870 Next_Actual (Actual);
4871 Next_Formal_With_Extras (Formal);
4872 end loop;
4873 end if;
4874
4875 -- Finally, create block and analyze it
4876
4877 Rewrite (N,
4878 Make_Block_Statement (Loc,
4879 Declarations => Decls,
4880 Handled_Statement_Sequence =>
4881 Make_Handled_Sequence_Of_Statements (Loc,
4882 Statements => Stats)));
4883
4884 Analyze (N);
4885 end;
4886 end Build_Simple_Entry_Call;
4887
4888 --------------------------------
4889 -- Build_Task_Activation_Call --
4890 --------------------------------
4891
4892 procedure Build_Task_Activation_Call (N : Node_Id) is
4893 function Activation_Call_Loc return Source_Ptr;
4894 -- Find a suitable source location for the activation call
4895
4896 -------------------------
4897 -- Activation_Call_Loc --
4898 -------------------------
4899
4900 function Activation_Call_Loc return Source_Ptr is
4901 begin
4902 -- The activation call must carry the location of the "end" keyword
4903 -- when the context is a package declaration.
4904
4905 if Nkind (N) = N_Package_Declaration then
4906 return End_Keyword_Location (N);
4907
4908 -- Otherwise the activation call must carry the location of the
4909 -- "begin" keyword.
4910
4911 else
4912 return Begin_Keyword_Location (N);
4913 end if;
4914 end Activation_Call_Loc;
4915
4916 -- Local variables
4917
4918 Chain : Entity_Id;
4919 Call : Node_Id;
4920 Loc : Source_Ptr;
4921 Name : Node_Id;
4922 Owner : Node_Id;
4923 Stmt : Node_Id;
4924
4925 -- Start of processing for Build_Task_Activation_Call
4926
4927 begin
4928 -- For sequential elaboration policy, all the tasks will be activated at
4929 -- the end of the elaboration.
4930
4931 if Partition_Elaboration_Policy = 'S' then
4932 return;
4933
4934 -- Do not create an activation call for a package spec if the package
4935 -- has a completing body. The activation call will be inserted after
4936 -- the "begin" of the body.
4937
4938 elsif Nkind (N) = N_Package_Declaration
4939 and then Present (Corresponding_Body (N))
4940 then
4941 return;
4942 end if;
4943
4944 -- Obtain the activation chain entity. Block statements, entry bodies,
4945 -- subprogram bodies, and task bodies keep the entity in their nodes.
4946 -- Package bodies on the other hand store it in the declaration of the
4947 -- corresponding package spec.
4948
4949 Owner := N;
4950
4951 if Nkind (Owner) = N_Package_Body then
4952 Owner := Unit_Declaration_Node (Corresponding_Spec (Owner));
4953 end if;
4954
4955 Chain := Activation_Chain_Entity (Owner);
4956
4957 -- Nothing to do when there are no tasks to activate. This is indicated
4958 -- by a missing activation chain entity; also skip generating it when
4959 -- it is a ghost entity.
4960
4961 if No (Chain) or else Is_Ignored_Ghost_Entity (Chain) then
4962 return;
4963
4964 -- The availability of the activation chain entity does not ensure
4965 -- that we have tasks to activate because it may have been declared
4966 -- by the frontend to pass a required extra formal to a build-in-place
4967 -- subprogram call. If we are within the scope of a protected type and
4968 -- pragma Detect_Blocking is active we can assume that no tasks will be
4969 -- activated; if tasks are created in a protected object and this pragma
4970 -- is active then the frontend emits a warning and Program_Error is
4971 -- raised at runtime.
4972
4973 elsif Detect_Blocking and then Within_Protected_Type (Current_Scope) then
4974 return;
4975 end if;
4976
4977 -- The location of the activation call must be as close as possible to
4978 -- the intended semantic location of the activation because the ABE
4979 -- mechanism relies heavily on accurate locations.
4980
4981 Loc := Activation_Call_Loc;
4982
4983 if Restricted_Profile then
4984 Name := New_Occurrence_Of (RTE (RE_Activate_Restricted_Tasks), Loc);
4985 else
4986 Name := New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc);
4987 end if;
4988
4989 Call :=
4990 Make_Procedure_Call_Statement (Loc,
4991 Name => Name,
4992 Parameter_Associations =>
4993 New_List (Make_Attribute_Reference (Loc,
4994 Prefix => New_Occurrence_Of (Chain, Loc),
4995 Attribute_Name => Name_Unchecked_Access)));
4996
4997 if Nkind (N) = N_Package_Declaration then
4998 if Present (Private_Declarations (Specification (N))) then
4999 Append (Call, Private_Declarations (Specification (N)));
5000 else
5001 Append (Call, Visible_Declarations (Specification (N)));
5002 end if;
5003
5004 else
5005 -- The call goes at the start of the statement sequence after the
5006 -- start of exception range label if one is present.
5007
5008 if Present (Handled_Statement_Sequence (N)) then
5009 Stmt := First (Statements (Handled_Statement_Sequence (N)));
5010
5011 -- A special case, skip exception range label if one is present
5012 -- (from front end zcx processing).
5013
5014 if Nkind (Stmt) = N_Label and then Exception_Junk (Stmt) then
5015 Next (Stmt);
5016 end if;
5017
5018 -- Another special case, if the first statement is a block from
5019 -- optimization of a local raise to a goto, then the call goes
5020 -- inside this block.
5021
5022 if Nkind (Stmt) = N_Block_Statement
5023 and then Exception_Junk (Stmt)
5024 then
5025 Stmt := First (Statements (Handled_Statement_Sequence (Stmt)));
5026 end if;
5027
5028 -- Insertion point is after any exception label pushes, since we
5029 -- want it covered by any local handlers.
5030
5031 while Nkind (Stmt) in N_Push_xxx_Label loop
5032 Next (Stmt);
5033 end loop;
5034
5035 -- Now we have the proper insertion point
5036
5037 Insert_Before (Stmt, Call);
5038
5039 else
5040 Set_Handled_Statement_Sequence (N,
5041 Make_Handled_Sequence_Of_Statements (Loc,
5042 Statements => New_List (Call)));
5043 end if;
5044 end if;
5045
5046 Analyze (Call);
5047
5048 if Legacy_Elaboration_Checks then
5049 Check_Task_Activation (N);
5050 end if;
5051 end Build_Task_Activation_Call;
5052
5053 -------------------------------
5054 -- Build_Task_Allocate_Block --
5055 -------------------------------
5056
5057 procedure Build_Task_Allocate_Block
5058 (Actions : List_Id;
5059 N : Node_Id;
5060 Args : List_Id)
5061 is
5062 T : constant Entity_Id := Entity (Expression (N));
5063 Init : constant Entity_Id := Base_Init_Proc (T);
5064 Loc : constant Source_Ptr := Sloc (N);
5065 Chain : constant Entity_Id :=
5066 Make_Defining_Identifier (Loc, Name_uChain);
5067 Blkent : constant Entity_Id := Make_Temporary (Loc, 'A');
5068 Block : Node_Id;
5069
5070 begin
5071 Block :=
5072 Make_Block_Statement (Loc,
5073 Identifier => New_Occurrence_Of (Blkent, Loc),
5074 Declarations => New_List (
5075
5076 -- _Chain : Activation_Chain;
5077
5078 Make_Object_Declaration (Loc,
5079 Defining_Identifier => Chain,
5080 Aliased_Present => True,
5081 Object_Definition =>
5082 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
5083
5084 Handled_Statement_Sequence =>
5085 Make_Handled_Sequence_Of_Statements (Loc,
5086
5087 Statements => New_List (
5088
5089 -- Init (Args);
5090
5091 Make_Procedure_Call_Statement (Loc,
5092 Name => New_Occurrence_Of (Init, Loc),
5093 Parameter_Associations => Args),
5094
5095 -- Activate_Tasks (_Chain);
5096
5097 Make_Procedure_Call_Statement (Loc,
5098 Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
5099 Parameter_Associations => New_List (
5100 Make_Attribute_Reference (Loc,
5101 Prefix => New_Occurrence_Of (Chain, Loc),
5102 Attribute_Name => Name_Unchecked_Access))))),
5103
5104 Has_Created_Identifier => True,
5105 Is_Task_Allocation_Block => True);
5106
5107 Append_To (Actions,
5108 Make_Implicit_Label_Declaration (Loc,
5109 Defining_Identifier => Blkent,
5110 Label_Construct => Block));
5111
5112 Append_To (Actions, Block);
5113
5114 Set_Activation_Chain_Entity (Block, Chain);
5115 end Build_Task_Allocate_Block;
5116
5117 -----------------------------------------------
5118 -- Build_Task_Allocate_Block_With_Init_Stmts --
5119 -----------------------------------------------
5120
5121 procedure Build_Task_Allocate_Block_With_Init_Stmts
5122 (Actions : List_Id;
5123 N : Node_Id;
5124 Init_Stmts : List_Id)
5125 is
5126 Loc : constant Source_Ptr := Sloc (N);
5127 Chain : constant Entity_Id :=
5128 Make_Defining_Identifier (Loc, Name_uChain);
5129 Blkent : constant Entity_Id := Make_Temporary (Loc, 'A');
5130 Block : Node_Id;
5131
5132 begin
5133 Append_To (Init_Stmts,
5134 Make_Procedure_Call_Statement (Loc,
5135 Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
5136 Parameter_Associations => New_List (
5137 Make_Attribute_Reference (Loc,
5138 Prefix => New_Occurrence_Of (Chain, Loc),
5139 Attribute_Name => Name_Unchecked_Access))));
5140
5141 Block :=
5142 Make_Block_Statement (Loc,
5143 Identifier => New_Occurrence_Of (Blkent, Loc),
5144 Declarations => New_List (
5145
5146 -- _Chain : Activation_Chain;
5147
5148 Make_Object_Declaration (Loc,
5149 Defining_Identifier => Chain,
5150 Aliased_Present => True,
5151 Object_Definition =>
5152 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
5153
5154 Handled_Statement_Sequence =>
5155 Make_Handled_Sequence_Of_Statements (Loc, Init_Stmts),
5156
5157 Has_Created_Identifier => True,
5158 Is_Task_Allocation_Block => True);
5159
5160 Append_To (Actions,
5161 Make_Implicit_Label_Declaration (Loc,
5162 Defining_Identifier => Blkent,
5163 Label_Construct => Block));
5164
5165 Append_To (Actions, Block);
5166
5167 Set_Activation_Chain_Entity (Block, Chain);
5168 end Build_Task_Allocate_Block_With_Init_Stmts;
5169
5170 -----------------------------------
5171 -- Build_Task_Proc_Specification --
5172 -----------------------------------
5173
5174 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
5175 Loc : constant Source_Ptr := Sloc (T);
5176 Spec_Id : Entity_Id;
5177
5178 begin
5179 -- Case of explicit task type, suffix TB
5180
5181 if Comes_From_Source (T) then
5182 Spec_Id :=
5183 Make_Defining_Identifier (Loc, New_External_Name (Chars (T), "TB"));
5184
5185 -- Case of anonymous task type, suffix B
5186
5187 else
5188 Spec_Id :=
5189 Make_Defining_Identifier (Loc, New_External_Name (Chars (T), 'B'));
5190 end if;
5191
5192 Set_Is_Internal (Spec_Id);
5193
5194 -- Associate the procedure with the task, if this is the declaration
5195 -- (and not the body) of the procedure.
5196
5197 if No (Task_Body_Procedure (T)) then
5198 Set_Task_Body_Procedure (T, Spec_Id);
5199 end if;
5200
5201 return
5202 Make_Procedure_Specification (Loc,
5203 Defining_Unit_Name => Spec_Id,
5204 Parameter_Specifications => New_List (
5205 Make_Parameter_Specification (Loc,
5206 Defining_Identifier =>
5207 Make_Defining_Identifier (Loc, Name_uTask),
5208 Parameter_Type =>
5209 Make_Access_Definition (Loc,
5210 Subtype_Mark =>
5211 New_Occurrence_Of (Corresponding_Record_Type (T), Loc)))));
5212 end Build_Task_Proc_Specification;
5213
5214 ---------------------------------------
5215 -- Build_Unprotected_Subprogram_Body --
5216 ---------------------------------------
5217
5218 function Build_Unprotected_Subprogram_Body
5219 (N : Node_Id;
5220 Pid : Node_Id) return Node_Id
5221 is
5222 Decls : constant List_Id := Declarations (N);
5223
5224 begin
5225 -- Add renamings for the Protection object, discriminals, privals, and
5226 -- the entry index constant for use by debugger.
5227
5228 Debug_Private_Data_Declarations (Decls);
5229
5230 -- Make an unprotected version of the subprogram for use within the same
5231 -- object, with a new name and an additional parameter representing the
5232 -- object.
5233
5234 return
5235 Make_Subprogram_Body (Sloc (N),
5236 Specification =>
5237 Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode),
5238 Declarations => Decls,
5239 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
5240 end Build_Unprotected_Subprogram_Body;
5241
5242 ----------------------------
5243 -- Collect_Entry_Families --
5244 ----------------------------
5245
5246 procedure Collect_Entry_Families
5247 (Loc : Source_Ptr;
5248 Cdecls : List_Id;
5249 Current_Node : in out Node_Id;
5250 Conctyp : Entity_Id)
5251 is
5252 Efam : Entity_Id;
5253 Efam_Decl : Node_Id;
5254 Efam_Type : Entity_Id;
5255
5256 begin
5257 Efam := First_Entity (Conctyp);
5258 while Present (Efam) loop
5259 if Ekind (Efam) = E_Entry_Family then
5260 Efam_Type := Make_Temporary (Loc, 'F');
5261
5262 declare
5263 Eityp : constant Entity_Id := Entry_Index_Type (Efam);
5264 Lo : constant Node_Id := Type_Low_Bound (Eityp);
5265 Hi : constant Node_Id := Type_High_Bound (Eityp);
5266 Bdecl : Node_Id;
5267 Bityp : Entity_Id;
5268
5269 begin
5270 Bityp := Base_Type (Eityp);
5271
5272 if Is_Potentially_Large_Family (Bityp, Conctyp, Lo, Hi) then
5273 Bityp := Make_Temporary (Loc, 'B');
5274
5275 Bdecl :=
5276 Make_Subtype_Declaration (Loc,
5277 Defining_Identifier => Bityp,
5278 Subtype_Indication =>
5279 Make_Subtype_Indication (Loc,
5280 Subtype_Mark =>
5281 New_Occurrence_Of (Standard_Integer, Loc),
5282 Constraint =>
5283 Make_Range_Constraint (Loc,
5284 Range_Expression => Make_Range (Loc,
5285 Make_Integer_Literal
5286 (Loc, -Entry_Family_Bound),
5287 Make_Integer_Literal
5288 (Loc, Entry_Family_Bound - 1)))));
5289
5290 Insert_After (Current_Node, Bdecl);
5291 Current_Node := Bdecl;
5292 Analyze (Bdecl);
5293 end if;
5294
5295 Efam_Decl :=
5296 Make_Full_Type_Declaration (Loc,
5297 Defining_Identifier => Efam_Type,
5298 Type_Definition =>
5299 Make_Unconstrained_Array_Definition (Loc,
5300 Subtype_Marks =>
5301 (New_List (New_Occurrence_Of (Bityp, Loc))),
5302
5303 Component_Definition =>
5304 Make_Component_Definition (Loc,
5305 Aliased_Present => False,
5306 Subtype_Indication =>
5307 New_Occurrence_Of (Standard_Character, Loc))));
5308 end;
5309
5310 Insert_After (Current_Node, Efam_Decl);
5311 Current_Node := Efam_Decl;
5312 Analyze (Efam_Decl);
5313
5314 Append_To (Cdecls,
5315 Make_Component_Declaration (Loc,
5316 Defining_Identifier =>
5317 Make_Defining_Identifier (Loc, Chars (Efam)),
5318
5319 Component_Definition =>
5320 Make_Component_Definition (Loc,
5321 Aliased_Present => False,
5322 Subtype_Indication =>
5323 Make_Subtype_Indication (Loc,
5324 Subtype_Mark =>
5325 New_Occurrence_Of (Efam_Type, Loc),
5326
5327 Constraint =>
5328 Make_Index_Or_Discriminant_Constraint (Loc,
5329 Constraints => New_List (
5330 New_Occurrence_Of (Entry_Index_Type (Efam),
5331 Loc)))))));
5332 end if;
5333
5334 Next_Entity (Efam);
5335 end loop;
5336 end Collect_Entry_Families;
5337
5338 -----------------------
5339 -- Concurrent_Object --
5340 -----------------------
5341
5342 function Concurrent_Object
5343 (Spec_Id : Entity_Id;
5344 Conc_Typ : Entity_Id) return Entity_Id
5345 is
5346 begin
5347 -- Parameter _O or _object
5348
5349 if Is_Protected_Type (Conc_Typ) then
5350 return First_Formal (Protected_Body_Subprogram (Spec_Id));
5351
5352 -- Parameter _task
5353
5354 else
5355 pragma Assert (Is_Task_Type (Conc_Typ));
5356 return First_Formal (Task_Body_Procedure (Conc_Typ));
5357 end if;
5358 end Concurrent_Object;
5359
5360 ----------------------
5361 -- Copy_Result_Type --
5362 ----------------------
5363
5364 function Copy_Result_Type (Res : Node_Id) return Node_Id is
5365 New_Res : constant Node_Id := New_Copy_Tree (Res);
5366 Par_Spec : Node_Id;
5367 Formal : Entity_Id;
5368
5369 begin
5370 -- If the result type is an access_to_subprogram, we must create new
5371 -- entities for its spec.
5372
5373 if Nkind (New_Res) = N_Access_Definition
5374 and then Present (Access_To_Subprogram_Definition (New_Res))
5375 then
5376 -- Provide new entities for the formals
5377
5378 Par_Spec := First (Parameter_Specifications
5379 (Access_To_Subprogram_Definition (New_Res)));
5380 while Present (Par_Spec) loop
5381 Formal := Defining_Identifier (Par_Spec);
5382 Set_Defining_Identifier (Par_Spec,
5383 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)));
5384 Next (Par_Spec);
5385 end loop;
5386 end if;
5387
5388 return New_Res;
5389 end Copy_Result_Type;
5390
5391 --------------------
5392 -- Concurrent_Ref --
5393 --------------------
5394
5395 -- The expression returned for a reference to a concurrent object has the
5396 -- form:
5397
5398 -- taskV!(name)._Task_Id
5399
5400 -- for a task, and
5401
5402 -- objectV!(name)._Object
5403
5404 -- for a protected object. For the case of an access to a concurrent
5405 -- object, there is an extra explicit dereference:
5406
5407 -- taskV!(name.all)._Task_Id
5408 -- objectV!(name.all)._Object
5409
5410 -- here taskV and objectV are the types for the associated records, which
5411 -- contain the required _Task_Id and _Object fields for tasks and protected
5412 -- objects, respectively.
5413
5414 -- For the case of a task type name, the expression is
5415
5416 -- Self;
5417
5418 -- i.e. a call to the Self function which returns precisely this Task_Id
5419
5420 -- For the case of a protected type name, the expression is
5421
5422 -- objectR
5423
5424 -- which is a renaming of the _object field of the current object
5425 -- record, passed into protected operations as a parameter.
5426
5427 function Concurrent_Ref (N : Node_Id) return Node_Id is
5428 Loc : constant Source_Ptr := Sloc (N);
5429 Ntyp : constant Entity_Id := Etype (N);
5430 Dtyp : Entity_Id;
5431 Sel : Name_Id;
5432
5433 function Is_Current_Task (T : Entity_Id) return Boolean;
5434 -- Check whether the reference is to the immediately enclosing task
5435 -- type, or to an outer one (rare but legal).
5436
5437 ---------------------
5438 -- Is_Current_Task --
5439 ---------------------
5440
5441 function Is_Current_Task (T : Entity_Id) return Boolean is
5442 Scop : Entity_Id;
5443
5444 begin
5445 Scop := Current_Scope;
5446 while Present (Scop) and then Scop /= Standard_Standard loop
5447 if Scop = T then
5448 return True;
5449
5450 elsif Is_Task_Type (Scop) then
5451 return False;
5452
5453 -- If this is a procedure nested within the task type, we must
5454 -- assume that it can be called from an inner task, and therefore
5455 -- cannot treat it as a local reference.
5456
5457 elsif Is_Overloadable (Scop) and then In_Open_Scopes (T) then
5458 return False;
5459
5460 else
5461 Scop := Scope (Scop);
5462 end if;
5463 end loop;
5464
5465 -- We know that we are within the task body, so should have found it
5466 -- in scope.
5467
5468 raise Program_Error;
5469 end Is_Current_Task;
5470
5471 -- Start of processing for Concurrent_Ref
5472
5473 begin
5474 if Is_Access_Type (Ntyp) then
5475 Dtyp := Designated_Type (Ntyp);
5476
5477 if Is_Protected_Type (Dtyp) then
5478 Sel := Name_uObject;
5479 else
5480 Sel := Name_uTask_Id;
5481 end if;
5482
5483 return
5484 Make_Selected_Component (Loc,
5485 Prefix =>
5486 Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
5487 Make_Explicit_Dereference (Loc, N)),
5488 Selector_Name => Make_Identifier (Loc, Sel));
5489
5490 elsif Is_Entity_Name (N) and then Is_Concurrent_Type (Entity (N)) then
5491 if Is_Task_Type (Entity (N)) then
5492
5493 if Is_Current_Task (Entity (N)) then
5494 return
5495 Make_Function_Call (Loc,
5496 Name => New_Occurrence_Of (RTE (RE_Self), Loc));
5497
5498 else
5499 declare
5500 Decl : Node_Id;
5501 T_Self : constant Entity_Id := Make_Temporary (Loc, 'T');
5502 T_Body : constant Node_Id :=
5503 Parent (Corresponding_Body (Parent (Entity (N))));
5504
5505 begin
5506 Decl :=
5507 Make_Object_Declaration (Loc,
5508 Defining_Identifier => T_Self,
5509 Object_Definition =>
5510 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
5511 Expression =>
5512 Make_Function_Call (Loc,
5513 Name => New_Occurrence_Of (RTE (RE_Self), Loc)));
5514 Prepend (Decl, Declarations (T_Body));
5515 Analyze (Decl);
5516 Set_Scope (T_Self, Entity (N));
5517 return New_Occurrence_Of (T_Self, Loc);
5518 end;
5519 end if;
5520
5521 else
5522 pragma Assert (Is_Protected_Type (Entity (N)));
5523
5524 return
5525 New_Occurrence_Of (Find_Protection_Object (Current_Scope), Loc);
5526 end if;
5527
5528 else
5529 if Is_Protected_Type (Ntyp) then
5530 Sel := Name_uObject;
5531 elsif Is_Task_Type (Ntyp) then
5532 Sel := Name_uTask_Id;
5533 else
5534 raise Program_Error;
5535 end if;
5536
5537 return
5538 Make_Selected_Component (Loc,
5539 Prefix =>
5540 Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
5541 New_Copy_Tree (N)),
5542 Selector_Name => Make_Identifier (Loc, Sel));
5543 end if;
5544 end Concurrent_Ref;
5545
5546 ------------------------
5547 -- Convert_Concurrent --
5548 ------------------------
5549
5550 function Convert_Concurrent
5551 (N : Node_Id;
5552 Typ : Entity_Id) return Node_Id
5553 is
5554 begin
5555 if not Is_Concurrent_Type (Typ) then
5556 return N;
5557 else
5558 return
5559 Unchecked_Convert_To
5560 (Corresponding_Record_Type (Typ), New_Copy_Tree (N));
5561 end if;
5562 end Convert_Concurrent;
5563
5564 -------------------------------------
5565 -- Create_Secondary_Stack_For_Task --
5566 -------------------------------------
5567
5568 function Create_Secondary_Stack_For_Task (T : Node_Id) return Boolean is
5569 begin
5570 return
5571 (Restriction_Active (No_Implicit_Heap_Allocations)
5572 or else Restriction_Active (No_Implicit_Task_Allocations))
5573 and then not Restriction_Active (No_Secondary_Stack)
5574 and then Has_Rep_Pragma
5575 (T, Name_Secondary_Stack_Size, Check_Parents => False);
5576 end Create_Secondary_Stack_For_Task;
5577
5578 -------------------------------------
5579 -- Debug_Private_Data_Declarations --
5580 -------------------------------------
5581
5582 procedure Debug_Private_Data_Declarations (Decls : List_Id) is
5583 Debug_Nod : Node_Id;
5584 Decl : Node_Id;
5585
5586 begin
5587 Decl := First (Decls);
5588 while Present (Decl) and then not Comes_From_Source (Decl) loop
5589
5590 -- Declaration for concurrent entity _object and its access type,
5591 -- along with the entry index subtype:
5592 -- type prot_typVP is access prot_typV;
5593 -- _object : prot_typVP := prot_typV (_O);
5594 -- subtype Jnn is <Type of Index> range Low .. High;
5595
5596 if Nkind (Decl) in N_Full_Type_Declaration | N_Object_Declaration then
5597 Set_Debug_Info_Needed (Defining_Identifier (Decl));
5598
5599 -- Declaration for the Protection object, discriminals, privals, and
5600 -- entry index constant:
5601 -- conc_typR : protection_typ renames _object._object;
5602 -- discr_nameD : discr_typ renames _object.discr_name;
5603 -- discr_nameD : discr_typ renames _task.discr_name;
5604 -- prival_name : comp_typ renames _object.comp_name;
5605 -- J : constant Jnn :=
5606 -- Jnn'Val (_E - <Index expression> + Jnn'Pos (Jnn'First));
5607
5608 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
5609 Set_Debug_Info_Needed (Defining_Identifier (Decl));
5610 Debug_Nod := Debug_Renaming_Declaration (Decl);
5611
5612 if Present (Debug_Nod) then
5613 Insert_After (Decl, Debug_Nod);
5614 end if;
5615 end if;
5616
5617 Next (Decl);
5618 end loop;
5619 end Debug_Private_Data_Declarations;
5620
5621 ------------------------------
5622 -- Ensure_Statement_Present --
5623 ------------------------------
5624
5625 procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id) is
5626 Stmt : Node_Id;
5627
5628 begin
5629 if Opt.Suppress_Control_Flow_Optimizations
5630 and then Is_Empty_List (Statements (Alt))
5631 then
5632 Stmt := Make_Null_Statement (Loc);
5633
5634 -- Mark NULL statement as coming from source so that it is not
5635 -- eliminated by GIGI.
5636
5637 -- Another covert channel. If this is a requirement, it must be
5638 -- documented in sinfo/einfo ???
5639
5640 Set_Comes_From_Source (Stmt, True);
5641
5642 Set_Statements (Alt, New_List (Stmt));
5643 end if;
5644 end Ensure_Statement_Present;
5645
5646 ----------------------------
5647 -- Entry_Index_Expression --
5648 ----------------------------
5649
5650 function Entry_Index_Expression
5651 (Sloc : Source_Ptr;
5652 Ent : Entity_Id;
5653 Index : Node_Id;
5654 Ttyp : Entity_Id) return Node_Id
5655 is
5656 Expr : Node_Id;
5657 Num : Node_Id;
5658 Lo : Node_Id;
5659 Hi : Node_Id;
5660 Prev : Entity_Id;
5661 S : Node_Id;
5662
5663 begin
5664 -- The queues of entries and entry families appear in textual order in
5665 -- the associated record. The entry index is computed as the sum of the
5666 -- number of queues for all entries that precede the designated one, to
5667 -- which is added the index expression, if this expression denotes a
5668 -- member of a family.
5669
5670 -- The following is a place holder for the count of simple entries
5671
5672 Num := Make_Integer_Literal (Sloc, 1);
5673
5674 -- We construct an expression which is a series of addition operations.
5675 -- The first operand is the number of single entries that precede this
5676 -- one, the second operand is the index value relative to the start of
5677 -- the referenced family, and the remaining operands are the lengths of
5678 -- the entry families that precede this entry, i.e. the constructed
5679 -- expression is:
5680
5681 -- number_simple_entries +
5682 -- (s'pos (index-value) - s'pos (family'first)) + 1 +
5683 -- family'length + ...
5684
5685 -- where index-value is the given index value, and s is the index
5686 -- subtype (we have to use pos because the subtype might be an
5687 -- enumeration type preventing direct subtraction). Note that the task
5688 -- entry array is one-indexed.
5689
5690 -- The upper bound of the entry family may be a discriminant, so we
5691 -- retrieve the lower bound explicitly to compute offset, rather than
5692 -- using the index subtype which may mention a discriminant.
5693
5694 if Present (Index) then
5695 S := Entry_Index_Type (Ent);
5696
5697 -- First make sure the index is in range if requested. The index type
5698 -- is the pristine Entry_Index_Type of the entry.
5699
5700 if Do_Range_Check (Index) then
5701 Generate_Range_Check (Index, S, CE_Range_Check_Failed);
5702 end if;
5703
5704 Expr :=
5705 Make_Op_Add (Sloc,
5706 Left_Opnd => Num,
5707 Right_Opnd =>
5708 Family_Offset
5709 (Sloc,
5710 Make_Attribute_Reference (Sloc,
5711 Attribute_Name => Name_Pos,
5712 Prefix => New_Occurrence_Of (Base_Type (S), Sloc),
5713 Expressions => New_List (Relocate_Node (Index))),
5714 Type_Low_Bound (S),
5715 Ttyp,
5716 False));
5717 else
5718 Expr := Num;
5719 end if;
5720
5721 -- Now add lengths of preceding entries and entry families
5722
5723 Prev := First_Entity (Ttyp);
5724 while Chars (Prev) /= Chars (Ent)
5725 or else (Ekind (Prev) /= Ekind (Ent))
5726 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
5727 loop
5728 if Ekind (Prev) = E_Entry then
5729 Set_Intval (Num, Intval (Num) + 1);
5730
5731 elsif Ekind (Prev) = E_Entry_Family then
5732 S := Entry_Index_Type (Prev);
5733 Lo := Type_Low_Bound (S);
5734 Hi := Type_High_Bound (S);
5735
5736 Expr :=
5737 Make_Op_Add (Sloc,
5738 Left_Opnd => Expr,
5739 Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp, False));
5740
5741 -- Other components are anonymous types to be ignored
5742
5743 else
5744 null;
5745 end if;
5746
5747 Next_Entity (Prev);
5748 end loop;
5749
5750 return Expr;
5751 end Entry_Index_Expression;
5752
5753 ---------------------------
5754 -- Establish_Task_Master --
5755 ---------------------------
5756
5757 procedure Establish_Task_Master (N : Node_Id) is
5758 Call : Node_Id;
5759
5760 begin
5761 if Restriction_Active (No_Task_Hierarchy) = False then
5762 Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
5763
5764 -- The block may have no declarations (and nevertheless be a task
5765 -- master) if it contains a call that may return an object that
5766 -- contains tasks.
5767
5768 if No (Declarations (N)) then
5769 Set_Declarations (N, New_List (Call));
5770 else
5771 Prepend_To (Declarations (N), Call);
5772 end if;
5773
5774 Analyze (Call);
5775 end if;
5776 end Establish_Task_Master;
5777
5778 --------------------------------
5779 -- Expand_Accept_Declarations --
5780 --------------------------------
5781
5782 -- Part of the expansion of an accept statement involves the creation of
5783 -- a declaration that can be referenced from the statement sequence of
5784 -- the accept:
5785
5786 -- Ann : Address;
5787
5788 -- This declaration is inserted immediately before the accept statement
5789 -- and it is important that it be inserted before the statements of the
5790 -- statement sequence are analyzed. Thus it would be too late to create
5791 -- this declaration in the Expand_N_Accept_Statement routine, which is
5792 -- why there is a separate procedure to be called directly from Sem_Ch9.
5793
5794 -- Ann is used to hold the address of the record containing the parameters
5795 -- (see Expand_N_Entry_Call for more details on how this record is built).
5796 -- References to the parameters do an unchecked conversion of this address
5797 -- to a pointer to the required record type, and then access the field that
5798 -- holds the value of the required parameter. The entity for the address
5799 -- variable is held as the top stack element (i.e. the last element) of the
5800 -- Accept_Address stack in the corresponding entry entity, and this element
5801 -- must be set in place before the statements are processed.
5802
5803 -- The above description applies to the case of a stand alone accept
5804 -- statement, i.e. one not appearing as part of a select alternative.
5805
5806 -- For the case of an accept that appears as part of a select alternative
5807 -- of a selective accept, we must still create the declaration right away,
5808 -- since Ann is needed immediately, but there is an important difference:
5809
5810 -- The declaration is inserted before the selective accept, not before
5811 -- the accept statement (which is not part of a list anyway, and so would
5812 -- not accommodate inserted declarations)
5813
5814 -- We only need one address variable for the entire selective accept. So
5815 -- the Ann declaration is created only for the first accept alternative,
5816 -- and subsequent accept alternatives reference the same Ann variable.
5817
5818 -- We can distinguish the two cases by seeing whether the accept statement
5819 -- is part of a list. If not, then it must be in an accept alternative.
5820
5821 -- To expand the requeue statement, a label is provided at the end of the
5822 -- accept statement or alternative of which it is a part, so that the
5823 -- statement can be skipped after the requeue is complete. This label is
5824 -- created here rather than during the expansion of the accept statement,
5825 -- because it will be needed by any requeue statements within the accept,
5826 -- which are expanded before the accept.
5827
5828 procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
5829 Loc : constant Source_Ptr := Sloc (N);
5830 Stats : constant Node_Id := Handled_Statement_Sequence (N);
5831 Ann : Entity_Id := Empty;
5832 Adecl : Node_Id;
5833 Lab : Node_Id;
5834 Ldecl : Node_Id;
5835 Ldecl2 : Node_Id;
5836
5837 begin
5838 if Expander_Active then
5839
5840 -- If we have no handled statement sequence, we may need to build
5841 -- a dummy sequence consisting of a null statement. This can be
5842 -- skipped if the trivial accept optimization is permitted.
5843
5844 if not Trivial_Accept_OK
5845 and then (No (Stats) or else Null_Statements (Statements (Stats)))
5846 then
5847 Set_Handled_Statement_Sequence (N,
5848 Make_Handled_Sequence_Of_Statements (Loc,
5849 Statements => New_List (Make_Null_Statement (Loc))));
5850 end if;
5851
5852 -- Create and declare two labels to be placed at the end of the
5853 -- accept statement. The first label is used to allow requeues to
5854 -- skip the remainder of entry processing. The second label is used
5855 -- to skip the remainder of entry processing if the rendezvous
5856 -- completes in the middle of the accept body.
5857
5858 if Present (Handled_Statement_Sequence (N)) then
5859 declare
5860 Ent : Entity_Id;
5861
5862 begin
5863 Ent := Make_Temporary (Loc, 'L');
5864 Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
5865 Ldecl :=
5866 Make_Implicit_Label_Declaration (Loc,
5867 Defining_Identifier => Ent,
5868 Label_Construct => Lab);
5869 Append (Lab, Statements (Handled_Statement_Sequence (N)));
5870
5871 Ent := Make_Temporary (Loc, 'L');
5872 Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
5873 Ldecl2 :=
5874 Make_Implicit_Label_Declaration (Loc,
5875 Defining_Identifier => Ent,
5876 Label_Construct => Lab);
5877 Append (Lab, Statements (Handled_Statement_Sequence (N)));
5878 end;
5879
5880 else
5881 Ldecl := Empty;
5882 Ldecl2 := Empty;
5883 end if;
5884
5885 -- Case of stand alone accept statement
5886
5887 if Is_List_Member (N) then
5888
5889 if Present (Handled_Statement_Sequence (N)) then
5890 Ann := Make_Temporary (Loc, 'A');
5891
5892 Adecl :=
5893 Make_Object_Declaration (Loc,
5894 Defining_Identifier => Ann,
5895 Object_Definition =>
5896 New_Occurrence_Of (RTE (RE_Address), Loc));
5897
5898 Insert_Before_And_Analyze (N, Adecl);
5899 Insert_Before_And_Analyze (N, Ldecl);
5900 Insert_Before_And_Analyze (N, Ldecl2);
5901 end if;
5902
5903 -- Case of accept statement which is in an accept alternative
5904
5905 else
5906 declare
5907 Acc_Alt : constant Node_Id := Parent (N);
5908 Sel_Acc : constant Node_Id := Parent (Acc_Alt);
5909 Alt : Node_Id;
5910
5911 begin
5912 pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
5913 pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
5914
5915 -- ??? Consider a single label for select statements
5916
5917 if Present (Handled_Statement_Sequence (N)) then
5918 Prepend (Ldecl2,
5919 Statements (Handled_Statement_Sequence (N)));
5920 Analyze (Ldecl2);
5921
5922 Prepend (Ldecl,
5923 Statements (Handled_Statement_Sequence (N)));
5924 Analyze (Ldecl);
5925 end if;
5926
5927 -- Find first accept alternative of the selective accept. A
5928 -- valid selective accept must have at least one accept in it.
5929
5930 Alt := First (Select_Alternatives (Sel_Acc));
5931
5932 while Nkind (Alt) /= N_Accept_Alternative loop
5933 Next (Alt);
5934 end loop;
5935
5936 -- If this is the first accept statement, then we have to
5937 -- create the Ann variable, as for the stand alone case, except
5938 -- that it is inserted before the selective accept. Similarly,
5939 -- a label for requeue expansion must be declared.
5940
5941 if N = Accept_Statement (Alt) then
5942 Ann := Make_Temporary (Loc, 'A');
5943 Adecl :=
5944 Make_Object_Declaration (Loc,
5945 Defining_Identifier => Ann,
5946 Object_Definition =>
5947 New_Occurrence_Of (RTE (RE_Address), Loc));
5948
5949 Insert_Before_And_Analyze (Sel_Acc, Adecl);
5950
5951 -- If this is not the first accept statement, then find the Ann
5952 -- variable allocated by the first accept and use it.
5953
5954 else
5955 Ann :=
5956 Node (Last_Elmt (Accept_Address
5957 (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
5958 end if;
5959 end;
5960 end if;
5961
5962 -- Merge here with Ann either created or referenced, and Adecl
5963 -- pointing to the corresponding declaration. Remaining processing
5964 -- is the same for the two cases.
5965
5966 if Present (Ann) then
5967 Append_Elmt (Ann, Accept_Address (Ent));
5968 Set_Debug_Info_Needed (Ann);
5969 end if;
5970
5971 -- Create renaming declarations for the entry formals. Each reference
5972 -- to a formal becomes a dereference of a component of the parameter
5973 -- block, whose address is held in Ann. These declarations are
5974 -- eventually inserted into the accept block, and analyzed there so
5975 -- that they have the proper scope for gdb and do not conflict with
5976 -- other declarations.
5977
5978 if Present (Parameter_Specifications (N))
5979 and then Present (Handled_Statement_Sequence (N))
5980 then
5981 declare
5982 Comp : Entity_Id;
5983 Decl : Node_Id;
5984 Formal : Entity_Id;
5985 New_F : Entity_Id;
5986 Renamed_Formal : Node_Id;
5987
5988 begin
5989 Push_Scope (Ent);
5990 Formal := First_Formal (Ent);
5991
5992 while Present (Formal) loop
5993 Comp := Entry_Component (Formal);
5994 New_F := Make_Defining_Identifier (Loc, Chars (Formal));
5995
5996 Set_Etype (New_F, Etype (Formal));
5997 Set_Scope (New_F, Ent);
5998
5999 -- Now we set debug info needed on New_F even though it does
6000 -- not come from source, so that the debugger will get the
6001 -- right information for these generated names.
6002
6003 Set_Debug_Info_Needed (New_F);
6004
6005 if Ekind (Formal) = E_In_Parameter then
6006 Set_Ekind (New_F, E_Constant);
6007 else
6008 Set_Ekind (New_F, E_Variable);
6009 Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
6010 end if;
6011
6012 Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
6013
6014 Renamed_Formal :=
6015 Make_Selected_Component (Loc,
6016 Prefix =>
6017 Make_Explicit_Dereference (Loc,
6018 Unchecked_Convert_To (
6019 Entry_Parameters_Type (Ent),
6020 New_Occurrence_Of (Ann, Loc))),
6021 Selector_Name =>
6022 New_Occurrence_Of (Comp, Loc));
6023
6024 Decl :=
6025 Build_Renamed_Formal_Declaration
6026 (New_F, Formal, Comp, Renamed_Formal);
6027
6028 if No (Declarations (N)) then
6029 Set_Declarations (N, New_List);
6030 end if;
6031
6032 Append (Decl, Declarations (N));
6033 Set_Renamed_Object (Formal, New_F);
6034 Next_Formal (Formal);
6035 end loop;
6036
6037 End_Scope;
6038 end;
6039 end if;
6040 end if;
6041 end Expand_Accept_Declarations;
6042
6043 ---------------------------------------------
6044 -- Expand_Access_Protected_Subprogram_Type --
6045 ---------------------------------------------
6046
6047 procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
6048 Loc : constant Source_Ptr := Sloc (N);
6049 T : constant Entity_Id := Defining_Identifier (N);
6050 D_T : constant Entity_Id := Designated_Type (T);
6051 D_T2 : constant Entity_Id := Make_Temporary (Loc, 'D');
6052 E_T : constant Entity_Id := Make_Temporary (Loc, 'E');
6053 P_List : constant List_Id :=
6054 Build_Protected_Spec (N, RTE (RE_Address), D_T, False);
6055
6056 Comps : List_Id;
6057 Decl1 : Node_Id;
6058 Decl2 : Node_Id;
6059 Def1 : Node_Id;
6060
6061 begin
6062 -- Create access to subprogram with full signature
6063
6064 if Etype (D_T) /= Standard_Void_Type then
6065 Def1 :=
6066 Make_Access_Function_Definition (Loc,
6067 Parameter_Specifications => P_List,
6068 Result_Definition =>
6069 Copy_Result_Type (Result_Definition (Type_Definition (N))));
6070
6071 else
6072 Def1 :=
6073 Make_Access_Procedure_Definition (Loc,
6074 Parameter_Specifications => P_List);
6075 end if;
6076
6077 Decl1 :=
6078 Make_Full_Type_Declaration (Loc,
6079 Defining_Identifier => D_T2,
6080 Type_Definition => Def1);
6081
6082 -- Declare the new types before the original one since the latter will
6083 -- refer to them through the Equivalent_Type slot.
6084
6085 Insert_Before_And_Analyze (N, Decl1);
6086
6087 -- Associate the access to subprogram with its original access to
6088 -- protected subprogram type. Needed by the backend to know that this
6089 -- type corresponds with an access to protected subprogram type.
6090
6091 Set_Original_Access_Type (D_T2, T);
6092
6093 -- Create Equivalent_Type, a record with two components for an access to
6094 -- object and an access to subprogram.
6095
6096 Comps := New_List (
6097 Make_Component_Declaration (Loc,
6098 Defining_Identifier => Make_Temporary (Loc, 'P'),
6099 Component_Definition =>
6100 Make_Component_Definition (Loc,
6101 Aliased_Present => False,
6102 Subtype_Indication =>
6103 New_Occurrence_Of (RTE (RE_Address), Loc))),
6104
6105 Make_Component_Declaration (Loc,
6106 Defining_Identifier => Make_Temporary (Loc, 'S'),
6107 Component_Definition =>
6108 Make_Component_Definition (Loc,
6109 Aliased_Present => False,
6110 Subtype_Indication => New_Occurrence_Of (D_T2, Loc))));
6111
6112 Decl2 :=
6113 Make_Full_Type_Declaration (Loc,
6114 Defining_Identifier => E_T,
6115 Type_Definition =>
6116 Make_Record_Definition (Loc,
6117 Component_List =>
6118 Make_Component_List (Loc, Component_Items => Comps)));
6119
6120 Insert_Before_And_Analyze (N, Decl2);
6121 Set_Equivalent_Type (T, E_T);
6122 end Expand_Access_Protected_Subprogram_Type;
6123
6124 --------------------------
6125 -- Expand_Entry_Barrier --
6126 --------------------------
6127
6128 procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
6129 Cond : constant Node_Id := Condition (Entry_Body_Formal_Part (N));
6130 Prot : constant Entity_Id := Scope (Ent);
6131 Spec_Decl : constant Node_Id := Parent (Prot);
6132
6133 Func_Id : Entity_Id := Empty;
6134 -- The entity of the barrier function
6135
6136 function Is_Global_Entity (N : Node_Id) return Traverse_Result;
6137 -- Check whether entity in Barrier is external to protected type.
6138 -- If so, barrier may not be properly synchronized.
6139
6140 function Is_Pure_Barrier (N : Node_Id) return Traverse_Result;
6141 -- Check whether N meets the Pure_Barriers restriction. Return OK if
6142 -- so.
6143
6144 function Is_Simple_Barrier (N : Node_Id) return Boolean;
6145 -- Check whether N meets the Simple_Barriers restriction. Return OK if
6146 -- so.
6147
6148 ----------------------
6149 -- Is_Global_Entity --
6150 ----------------------
6151
6152 function Is_Global_Entity (N : Node_Id) return Traverse_Result is
6153 E : Entity_Id;
6154 S : Entity_Id;
6155
6156 begin
6157 if Is_Entity_Name (N) and then Present (Entity (N)) then
6158 E := Entity (N);
6159 S := Scope (E);
6160
6161 if Ekind (E) = E_Variable then
6162
6163 -- If the variable is local to the barrier function generated
6164 -- during expansion, it is ok. If expansion is not performed,
6165 -- then Func is Empty so this test cannot succeed.
6166
6167 if Scope (E) = Func_Id then
6168 null;
6169
6170 -- A protected call from a barrier to another object is ok
6171
6172 elsif Ekind (Etype (E)) = E_Protected_Type then
6173 null;
6174
6175 -- If the variable is within the package body we consider
6176 -- this safe. This is a common (if dubious) idiom.
6177
6178 elsif S = Scope (Prot)
6179 and then Is_Package_Or_Generic_Package (S)
6180 and then Nkind (Parent (E)) = N_Object_Declaration
6181 and then Nkind (Parent (Parent (E))) = N_Package_Body
6182 then
6183 null;
6184
6185 else
6186 Error_Msg_N ("potentially unsynchronized barrier??", N);
6187 Error_Msg_N ("\& should be private component of type??", N);
6188 end if;
6189 end if;
6190 end if;
6191
6192 return OK;
6193 end Is_Global_Entity;
6194
6195 procedure Check_Unprotected_Barrier is
6196 new Traverse_Proc (Is_Global_Entity);
6197
6198 -----------------------
6199 -- Is_Simple_Barrier --
6200 -----------------------
6201
6202 function Is_Simple_Barrier (N : Node_Id) return Boolean is
6203 Renamed : Node_Id;
6204
6205 begin
6206 if Is_Static_Expression (N) then
6207 return True;
6208 elsif Ada_Version >= Ada_2020
6209 and then Nkind (N) in N_Selected_Component | N_Indexed_Component
6210 and then Statically_Names_Object (N)
6211 then
6212 -- Restriction relaxed in Ada2020 to allow statically named
6213 -- subcomponents.
6214 return Is_Simple_Barrier (Prefix (N));
6215 end if;
6216
6217 -- Check if the name is a component of the protected object. If
6218 -- the expander is active, the component has been transformed into a
6219 -- renaming of _object.all.component. Original_Node is needed in case
6220 -- validity checking is enabled, in which case the simple object
6221 -- reference will have been rewritten.
6222
6223 if Expander_Active then
6224
6225 -- The expanded name may have been constant folded in which case
6226 -- the original node is not necessarily an entity name (e.g. an
6227 -- indexed component).
6228
6229 if not Is_Entity_Name (Original_Node (N)) then
6230 return False;
6231 end if;
6232
6233 Renamed := Renamed_Object (Entity (Original_Node (N)));
6234
6235 return
6236 Present (Renamed)
6237 and then Nkind (Renamed) = N_Selected_Component
6238 and then Chars (Prefix (Prefix (Renamed))) = Name_uObject;
6239 elsif not Is_Entity_Name (N) then
6240 return False;
6241 else
6242 return Is_Protected_Component (Entity (N));
6243 end if;
6244 end Is_Simple_Barrier;
6245
6246 ---------------------
6247 -- Is_Pure_Barrier --
6248 ---------------------
6249
6250 function Is_Pure_Barrier (N : Node_Id) return Traverse_Result is
6251 begin
6252 case Nkind (N) is
6253 when N_Expanded_Name
6254 | N_Identifier
6255 =>
6256
6257 -- Because of N_Expanded_Name case, return Skip instead of OK.
6258
6259 if No (Entity (N)) then
6260 return Abandon;
6261
6262 elsif Is_Numeric_Type (Entity (N)) then
6263 return Skip;
6264 end if;
6265
6266 case Ekind (Entity (N)) is
6267 when E_Constant
6268 | E_Discriminant
6269 =>
6270 return Skip;
6271
6272 when E_Enumeration_Literal
6273 | E_Named_Integer
6274 | E_Named_Real
6275 =>
6276 if not Is_OK_Static_Expression (N) then
6277 return Abandon;
6278 end if;
6279 return Skip;
6280
6281 when E_Component =>
6282 return Skip;
6283
6284 when E_Variable =>
6285 if Is_Simple_Barrier (N) then
6286 return Skip;
6287 end if;
6288
6289 when E_Function =>
6290
6291 -- The count attribute has been transformed into run-time
6292 -- calls.
6293
6294 if Is_RTE (Entity (N), RE_Protected_Count)
6295 or else Is_RTE (Entity (N), RE_Protected_Count_Entry)
6296 then
6297 return Skip;
6298 end if;
6299
6300 when others =>
6301 null;
6302 end case;
6303
6304 when N_Function_Call =>
6305
6306 -- Function call checks are carried out as part of the analysis
6307 -- of the function call name.
6308
6309 return OK;
6310
6311 when N_Character_Literal
6312 | N_Integer_Literal
6313 | N_Real_Literal
6314 =>
6315 return OK;
6316
6317 when N_Op_Boolean
6318 | N_Op_Not
6319 =>
6320 if Ekind (Entity (N)) = E_Operator then
6321 return OK;
6322 end if;
6323
6324 when N_Short_Circuit
6325 | N_If_Expression
6326 | N_Case_Expression
6327 =>
6328 return OK;
6329
6330 when N_Indexed_Component | N_Selected_Component =>
6331 if Statically_Names_Object (N) then
6332 return Is_Pure_Barrier (Prefix (N));
6333 else
6334 return Abandon;
6335 end if;
6336
6337 when N_Case_Expression_Alternative =>
6338 -- do not traverse Discrete_Choices subtree
6339 if Is_Pure_Barrier (Expression (N)) /= Abandon then
6340 return Skip;
6341 end if;
6342
6343 when N_Expression_With_Actions =>
6344 -- this may occur in the case of a Count attribute reference
6345 if Original_Node (N) /= N
6346 and then Is_Pure_Barrier (Original_Node (N)) /= Abandon
6347 then
6348 return Skip;
6349 end if;
6350
6351 when N_Membership_Test =>
6352 if Is_Pure_Barrier (Left_Opnd (N)) /= Abandon
6353 and then All_Membership_Choices_Static (N)
6354 then
6355 return Skip;
6356 end if;
6357
6358 when N_Type_Conversion =>
6359
6360 -- Conversions to Universal_Integer do not raise constraint
6361 -- errors. Likewise if the expression's type is statically
6362 -- compatible with the target's type.
6363
6364 if Etype (N) = Universal_Integer
6365 or else Subtypes_Statically_Compatible
6366 (Etype (Expression (N)), Etype (N))
6367 then
6368 return OK;
6369 end if;
6370
6371 when N_Unchecked_Type_Conversion =>
6372 return OK;
6373
6374 when others =>
6375 null;
6376 end case;
6377
6378 return Abandon;
6379 end Is_Pure_Barrier;
6380
6381 function Check_Pure_Barriers is new Traverse_Func (Is_Pure_Barrier);
6382
6383 -- Local variables
6384
6385 Cond_Id : Entity_Id;
6386 Entry_Body : Node_Id;
6387 Func_Body : Node_Id := Empty;
6388
6389 -- Start of processing for Expand_Entry_Barrier
6390
6391 begin
6392 if No_Run_Time_Mode then
6393 Error_Msg_CRT ("entry barrier", N);
6394 return;
6395 end if;
6396
6397 -- Prevent cascaded errors
6398
6399 if Nkind (Cond) = N_Error then
6400 return;
6401 end if;
6402
6403 -- The body of the entry barrier must be analyzed in the context of the
6404 -- protected object, but its scope is external to it, just as any other
6405 -- unprotected version of a protected operation. The specification has
6406 -- been produced when the protected type declaration was elaborated. We
6407 -- build the body, insert it in the enclosing scope, but analyze it in
6408 -- the current context. A more uniform approach would be to treat the
6409 -- barrier just as a protected function, and discard the protected
6410 -- version of it because it is never called.
6411
6412 if Expander_Active then
6413 Func_Body := Build_Barrier_Function (N, Ent, Prot);
6414 Func_Id := Barrier_Function (Ent);
6415 Set_Corresponding_Spec (Func_Body, Func_Id);
6416
6417 Entry_Body := Parent (Corresponding_Body (Spec_Decl));
6418
6419 if Nkind (Parent (Entry_Body)) = N_Subunit then
6420 Entry_Body := Corresponding_Stub (Parent (Entry_Body));
6421 end if;
6422
6423 Insert_Before_And_Analyze (Entry_Body, Func_Body);
6424
6425 Set_Discriminals (Spec_Decl);
6426 Set_Scope (Func_Id, Scope (Prot));
6427
6428 else
6429 Analyze_And_Resolve (Cond, Any_Boolean);
6430 end if;
6431
6432 -- Check Simple_Barriers and Pure_Barriers restrictions.
6433 -- Note that it is safe to be calling Check_Restriction from here, even
6434 -- though this is part of the expander, since Expand_Entry_Barrier is
6435 -- called from Sem_Ch9 even in -gnatc mode.
6436
6437 if not Is_Simple_Barrier (Cond) then
6438 -- flag restriction violation
6439 Check_Restriction (Simple_Barriers, Cond);
6440 end if;
6441
6442 if Check_Pure_Barriers (Cond) = Abandon then
6443 -- flag restriction violation
6444 Check_Restriction (Pure_Barriers, Cond);
6445
6446 -- Emit warning if barrier contains global entities and is thus
6447 -- potentially unsynchronized (if Pure_Barriers restrictions
6448 -- are met then no need to check for this).
6449 Check_Unprotected_Barrier (Cond);
6450 end if;
6451
6452 if Is_Entity_Name (Cond) then
6453 Cond_Id := Entity (Cond);
6454
6455 -- Perform a small optimization of simple barrier functions. If the
6456 -- scope of the condition's entity is not the barrier function, then
6457 -- the condition does not depend on any of the generated renamings.
6458 -- If this is the case, eliminate the renamings as they are useless.
6459 -- This optimization is not performed when the condition was folded
6460 -- and validity checks are in effect because the original condition
6461 -- may have produced at least one check that depends on the generated
6462 -- renamings.
6463
6464 if Expander_Active
6465 and then Scope (Cond_Id) /= Func_Id
6466 and then not Validity_Check_Operands
6467 then
6468 Set_Declarations (Func_Body, Empty_List);
6469 end if;
6470
6471 -- Note that after analysis variables in this context will be
6472 -- replaced by the corresponding prival, that is to say a renaming
6473 -- of a selected component of the form _Object.Var. If expansion is
6474 -- disabled, as within a generic, we check that the entity appears in
6475 -- the current scope.
6476 end if;
6477 end Expand_Entry_Barrier;
6478
6479 ------------------------------
6480 -- Expand_N_Abort_Statement --
6481 ------------------------------
6482
6483 -- Expand abort T1, T2, .. Tn; into:
6484 -- Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
6485
6486 procedure Expand_N_Abort_Statement (N : Node_Id) is
6487 Loc : constant Source_Ptr := Sloc (N);
6488 Tlist : constant List_Id := Names (N);
6489 Count : Nat;
6490 Aggr : Node_Id;
6491 Tasknm : Node_Id;
6492
6493 begin
6494 Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
6495 Count := 0;
6496
6497 Tasknm := First (Tlist);
6498
6499 while Present (Tasknm) loop
6500 Count := Count + 1;
6501
6502 -- A task interface class-wide type object is being aborted. Retrieve
6503 -- its _task_id by calling a dispatching routine.
6504
6505 if Ada_Version >= Ada_2005
6506 and then Ekind (Etype (Tasknm)) = E_Class_Wide_Type
6507 and then Is_Interface (Etype (Tasknm))
6508 and then Is_Task_Interface (Etype (Tasknm))
6509 then
6510 Append_To (Component_Associations (Aggr),
6511 Make_Component_Association (Loc,
6512 Choices => New_List (Make_Integer_Literal (Loc, Count)),
6513 Expression =>
6514
6515 -- Task_Id (Tasknm._disp_get_task_id)
6516
6517 Make_Unchecked_Type_Conversion (Loc,
6518 Subtype_Mark =>
6519 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
6520 Expression =>
6521 Make_Selected_Component (Loc,
6522 Prefix => New_Copy_Tree (Tasknm),
6523 Selector_Name =>
6524 Make_Identifier (Loc, Name_uDisp_Get_Task_Id)))));
6525
6526 else
6527 Append_To (Component_Associations (Aggr),
6528 Make_Component_Association (Loc,
6529 Choices => New_List (Make_Integer_Literal (Loc, Count)),
6530 Expression => Concurrent_Ref (Tasknm)));
6531 end if;
6532
6533 Next (Tasknm);
6534 end loop;
6535
6536 Rewrite (N,
6537 Make_Procedure_Call_Statement (Loc,
6538 Name => New_Occurrence_Of (RTE (RE_Abort_Tasks), Loc),
6539 Parameter_Associations => New_List (
6540 Make_Qualified_Expression (Loc,
6541 Subtype_Mark => New_Occurrence_Of (RTE (RE_Task_List), Loc),
6542 Expression => Aggr))));
6543
6544 Analyze (N);
6545 end Expand_N_Abort_Statement;
6546
6547 -------------------------------
6548 -- Expand_N_Accept_Statement --
6549 -------------------------------
6550
6551 -- This procedure handles expansion of accept statements that stand alone,
6552 -- i.e. they are not part of an accept alternative. The expansion of
6553 -- accept statement in accept alternatives is handled by the routines
6554 -- Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
6555 -- following description applies only to stand alone accept statements.
6556
6557 -- If there is no handled statement sequence, or only null statements, then
6558 -- this is called a trivial accept, and the expansion is:
6559
6560 -- Accept_Trivial (entry-index)
6561
6562 -- If there is a handled statement sequence, then the expansion is:
6563
6564 -- Ann : Address;
6565 -- {Lnn : Label}
6566
6567 -- begin
6568 -- begin
6569 -- Accept_Call (entry-index, Ann);
6570 -- Renaming_Declarations for formals
6571 -- <statement sequence from N_Accept_Statement node>
6572 -- Complete_Rendezvous;
6573 -- <<Lnn>>
6574 --
6575 -- exception
6576 -- when ... =>
6577 -- <exception handler from N_Accept_Statement node>
6578 -- Complete_Rendezvous;
6579 -- when ... =>
6580 -- <exception handler from N_Accept_Statement node>
6581 -- Complete_Rendezvous;
6582 -- ...
6583 -- end;
6584
6585 -- exception
6586 -- when all others =>
6587 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
6588 -- end;
6589
6590 -- The first three declarations were already inserted ahead of the accept
6591 -- statement by the Expand_Accept_Declarations procedure, which was called
6592 -- directly from the semantics during analysis of the accept statement,
6593 -- before analyzing its contained statements.
6594
6595 -- The declarations from the N_Accept_Statement, as noted in Sinfo, come
6596 -- from possible expansion activity (the original source of course does
6597 -- not have any declarations associated with the accept statement, since
6598 -- an accept statement has no declarative part). In particular, if the
6599 -- expander is active, the first such declaration is the declaration of
6600 -- the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
6601
6602 -- The two blocks are merged into a single block if the inner block has
6603 -- no exception handlers, but otherwise two blocks are required, since
6604 -- exceptions might be raised in the exception handlers of the inner
6605 -- block, and Exceptional_Complete_Rendezvous must be called.
6606
6607 procedure Expand_N_Accept_Statement (N : Node_Id) is
6608 Loc : constant Source_Ptr := Sloc (N);
6609 Stats : constant Node_Id := Handled_Statement_Sequence (N);
6610 Ename : constant Node_Id := Entry_Direct_Name (N);
6611 Eindx : constant Node_Id := Entry_Index (N);
6612 Eent : constant Entity_Id := Entity (Ename);
6613 Acstack : constant Elist_Id := Accept_Address (Eent);
6614 Ann : constant Entity_Id := Node (Last_Elmt (Acstack));
6615 Ttyp : constant Entity_Id := Etype (Scope (Eent));
6616 Blkent : Entity_Id;
6617 Call : Node_Id;
6618 Block : Node_Id;
6619
6620 begin
6621 -- If the accept statement is not part of a list, then its parent must
6622 -- be an accept alternative, and, as described above, we do not do any
6623 -- expansion for such accept statements at this level.
6624
6625 if not Is_List_Member (N) then
6626 pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
6627 return;
6628
6629 -- Trivial accept case (no statement sequence, or null statements).
6630 -- If the accept statement has declarations, then just insert them
6631 -- before the procedure call.
6632
6633 elsif Trivial_Accept_OK
6634 and then (No (Stats) or else Null_Statements (Statements (Stats)))
6635 then
6636 -- Remove declarations for renamings, because the parameter block
6637 -- will not be assigned.
6638
6639 declare
6640 D : Node_Id;
6641 Next_D : Node_Id;
6642
6643 begin
6644 D := First (Declarations (N));
6645 while Present (D) loop
6646 Next_D := Next (D);
6647 if Nkind (D) = N_Object_Renaming_Declaration then
6648 Remove (D);
6649 end if;
6650
6651 D := Next_D;
6652 end loop;
6653 end;
6654
6655 if Present (Declarations (N)) then
6656 Insert_Actions (N, Declarations (N));
6657 end if;
6658
6659 Rewrite (N,
6660 Make_Procedure_Call_Statement (Loc,
6661 Name => New_Occurrence_Of (RTE (RE_Accept_Trivial), Loc),
6662 Parameter_Associations => New_List (
6663 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
6664
6665 Analyze (N);
6666
6667 -- Ada 2020 (AI12-0279)
6668
6669 if Has_Yield_Aspect (Eent)
6670 and then RTE_Available (RE_Yield)
6671 then
6672 Insert_Action_After (N,
6673 Make_Procedure_Call_Statement (Loc,
6674 New_Occurrence_Of (RTE (RE_Yield), Loc)));
6675 end if;
6676
6677 -- Discard Entry_Address that was created for it, so it will not be
6678 -- emitted if this accept statement is in the statement part of a
6679 -- delay alternative.
6680
6681 if Present (Stats) then
6682 Remove_Last_Elmt (Acstack);
6683 end if;
6684
6685 -- Case of statement sequence present
6686
6687 else
6688 -- Construct the block, using the declarations from the accept
6689 -- statement if any to initialize the declarations of the block.
6690
6691 Blkent := Make_Temporary (Loc, 'A');
6692 Set_Ekind (Blkent, E_Block);
6693 Set_Etype (Blkent, Standard_Void_Type);
6694 Set_Scope (Blkent, Current_Scope);
6695
6696 Block :=
6697 Make_Block_Statement (Loc,
6698 Identifier => New_Occurrence_Of (Blkent, Loc),
6699 Declarations => Declarations (N),
6700 Handled_Statement_Sequence => Build_Accept_Body (N));
6701
6702 -- Reset the Scope of local entities associated with the accept
6703 -- statement (that currently reference the entry scope) to the
6704 -- block scope, to avoid having references to the locals treated
6705 -- as up-level references.
6706
6707 Reset_Scopes_To (Block, Blkent);
6708
6709 -- For the analysis of the generated declarations, the parent node
6710 -- must be properly set.
6711
6712 Set_Parent (Block, Parent (N));
6713 Set_Parent (Blkent, Block);
6714
6715 -- Prepend call to Accept_Call to main statement sequence If the
6716 -- accept has exception handlers, the statement sequence is wrapped
6717 -- in a block. Insert call and renaming declarations in the
6718 -- declarations of the block, so they are elaborated before the
6719 -- handlers.
6720
6721 Call :=
6722 Make_Procedure_Call_Statement (Loc,
6723 Name => New_Occurrence_Of (RTE (RE_Accept_Call), Loc),
6724 Parameter_Associations => New_List (
6725 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
6726 New_Occurrence_Of (Ann, Loc)));
6727
6728 if Parent (Stats) = N then
6729 Prepend (Call, Statements (Stats));
6730 else
6731 Set_Declarations (Parent (Stats), New_List (Call));
6732 end if;
6733
6734 Analyze (Call);
6735
6736 Push_Scope (Blkent);
6737
6738 declare
6739 D : Node_Id;
6740 Next_D : Node_Id;
6741 Typ : Entity_Id;
6742
6743 begin
6744 D := First (Declarations (N));
6745 while Present (D) loop
6746 Next_D := Next (D);
6747
6748 if Nkind (D) = N_Object_Renaming_Declaration then
6749
6750 -- The renaming declarations for the formals were created
6751 -- during analysis of the accept statement, and attached to
6752 -- the list of declarations. Place them now in the context
6753 -- of the accept block or subprogram.
6754
6755 Remove (D);
6756 Typ := Entity (Subtype_Mark (D));
6757 Insert_After (Call, D);
6758 Analyze (D);
6759
6760 -- If the formal is class_wide, it does not have an actual
6761 -- subtype. The analysis of the renaming declaration creates
6762 -- one, but we need to retain the class-wide nature of the
6763 -- entity.
6764
6765 if Is_Class_Wide_Type (Typ) then
6766 Set_Etype (Defining_Identifier (D), Typ);
6767 end if;
6768
6769 end if;
6770
6771 D := Next_D;
6772 end loop;
6773 end;
6774
6775 End_Scope;
6776
6777 -- Replace the accept statement by the new block
6778
6779 Rewrite (N, Block);
6780 Analyze (N);
6781
6782 -- Last step is to unstack the Accept_Address value
6783
6784 Remove_Last_Elmt (Acstack);
6785 end if;
6786 end Expand_N_Accept_Statement;
6787
6788 ----------------------------------
6789 -- Expand_N_Asynchronous_Select --
6790 ----------------------------------
6791
6792 -- This procedure assumes that the trigger statement is an entry call or
6793 -- a dispatching procedure call. A delay alternative should already have
6794 -- been expanded into an entry call to the appropriate delay object Wait
6795 -- entry.
6796
6797 -- If the trigger is a task entry call, the select is implemented with
6798 -- a Task_Entry_Call:
6799
6800 -- declare
6801 -- B : Boolean;
6802 -- C : Boolean;
6803 -- P : parms := (parm, parm, parm);
6804
6805 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6806
6807 -- procedure _clean is
6808 -- begin
6809 -- ...
6810 -- Cancel_Task_Entry_Call (C);
6811 -- ...
6812 -- end _clean;
6813
6814 -- begin
6815 -- Abort_Defer;
6816 -- Task_Entry_Call
6817 -- (<acceptor-task>, -- Acceptor
6818 -- <entry-index>, -- E
6819 -- P'Address, -- Uninterpreted_Data
6820 -- Asynchronous_Call, -- Mode
6821 -- B); -- Rendezvous_Successful
6822
6823 -- begin
6824 -- begin
6825 -- Abort_Undefer;
6826 -- <abortable-part>
6827 -- at end
6828 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6829 -- end;
6830 -- exception
6831 -- when Abort_Signal => Abort_Undefer;
6832 -- end;
6833
6834 -- parm := P.param;
6835 -- parm := P.param;
6836 -- ...
6837 -- if not C then
6838 -- <triggered-statements>
6839 -- end if;
6840 -- end;
6841
6842 -- Note that Build_Simple_Entry_Call is used to expand the entry of the
6843 -- asynchronous entry call (by Expand_N_Entry_Call_Statement procedure)
6844 -- as follows:
6845
6846 -- declare
6847 -- P : parms := (parm, parm, parm);
6848 -- begin
6849 -- Call_Simple (acceptor-task, entry-index, P'Address);
6850 -- parm := P.param;
6851 -- parm := P.param;
6852 -- ...
6853 -- end;
6854
6855 -- so the task at hand is to convert the latter expansion into the former
6856
6857 -- If the trigger is a protected entry call, the select is implemented
6858 -- with Protected_Entry_Call:
6859
6860 -- declare
6861 -- P : E1_Params := (param, param, param);
6862 -- Bnn : Communications_Block;
6863
6864 -- begin
6865 -- declare
6866
6867 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6868
6869 -- procedure _clean is
6870 -- begin
6871 -- ...
6872 -- if Enqueued (Bnn) then
6873 -- Cancel_Protected_Entry_Call (Bnn);
6874 -- end if;
6875 -- ...
6876 -- end _clean;
6877
6878 -- begin
6879 -- begin
6880 -- Protected_Entry_Call
6881 -- (po._object'Access, -- Object
6882 -- <entry index>, -- E
6883 -- P'Address, -- Uninterpreted_Data
6884 -- Asynchronous_Call, -- Mode
6885 -- Bnn); -- Block
6886
6887 -- if Enqueued (Bnn) then
6888 -- <abortable-part>
6889 -- end if;
6890 -- at end
6891 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6892 -- end;
6893 -- exception
6894 -- when Abort_Signal => Abort_Undefer;
6895 -- end;
6896
6897 -- if not Cancelled (Bnn) then
6898 -- <triggered-statements>
6899 -- end if;
6900 -- end;
6901
6902 -- Build_Simple_Entry_Call is used to expand the all to a simple protected
6903 -- entry call:
6904
6905 -- declare
6906 -- P : E1_Params := (param, param, param);
6907 -- Bnn : Communications_Block;
6908
6909 -- begin
6910 -- Protected_Entry_Call
6911 -- (po._object'Access, -- Object
6912 -- <entry index>, -- E
6913 -- P'Address, -- Uninterpreted_Data
6914 -- Simple_Call, -- Mode
6915 -- Bnn); -- Block
6916 -- parm := P.param;
6917 -- parm := P.param;
6918 -- ...
6919 -- end;
6920
6921 -- Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
6922 -- expanded into:
6923
6924 -- declare
6925 -- B : Boolean := False;
6926 -- Bnn : Communication_Block;
6927 -- C : Ada.Tags.Prim_Op_Kind;
6928 -- D : System.Storage_Elements.Dummy_Communication_Block;
6929 -- K : Ada.Tags.Tagged_Kind :=
6930 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
6931 -- P : Parameters := (Param1 .. ParamN);
6932 -- S : Integer;
6933 -- U : Boolean;
6934
6935 -- begin
6936 -- if K = Ada.Tags.TK_Limited_Tagged
6937 -- or else K = Ada.Tags.TK_Tagged
6938 -- then
6939 -- <dispatching-call>;
6940 -- <triggering-statements>;
6941
6942 -- else
6943 -- S :=
6944 -- Ada.Tags.Get_Offset_Index
6945 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
6946
6947 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
6948
6949 -- if C = POK_Protected_Entry then
6950 -- declare
6951 -- procedure _clean is
6952 -- begin
6953 -- if Enqueued (Bnn) then
6954 -- Cancel_Protected_Entry_Call (Bnn);
6955 -- end if;
6956 -- end _clean;
6957
6958 -- begin
6959 -- begin
6960 -- _Disp_Asynchronous_Select
6961 -- (<object>, S, P'Address, D, B);
6962 -- Bnn := Communication_Block (D);
6963
6964 -- Param1 := P.Param1;
6965 -- ...
6966 -- ParamN := P.ParamN;
6967
6968 -- if Enqueued (Bnn) then
6969 -- <abortable-statements>
6970 -- end if;
6971 -- at end
6972 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6973 -- end;
6974 -- exception
6975 -- when Abort_Signal => Abort_Undefer;
6976 -- end;
6977
6978 -- if not Cancelled (Bnn) then
6979 -- <triggering-statements>
6980 -- end if;
6981
6982 -- elsif C = POK_Task_Entry then
6983 -- declare
6984 -- procedure _clean is
6985 -- begin
6986 -- Cancel_Task_Entry_Call (U);
6987 -- end _clean;
6988
6989 -- begin
6990 -- Abort_Defer;
6991
6992 -- _Disp_Asynchronous_Select
6993 -- (<object>, S, P'Address, D, B);
6994 -- Bnn := Communication_Bloc (D);
6995
6996 -- Param1 := P.Param1;
6997 -- ...
6998 -- ParamN := P.ParamN;
6999
7000 -- begin
7001 -- begin
7002 -- Abort_Undefer;
7003 -- <abortable-statements>
7004 -- at end
7005 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
7006 -- end;
7007 -- exception
7008 -- when Abort_Signal => Abort_Undefer;
7009 -- end;
7010
7011 -- if not U then
7012 -- <triggering-statements>
7013 -- end if;
7014 -- end;
7015
7016 -- else
7017 -- <dispatching-call>;
7018 -- <triggering-statements>
7019 -- end if;
7020 -- end if;
7021 -- end;
7022
7023 -- The job is to convert this to the asynchronous form
7024
7025 -- If the trigger is a delay statement, it will have been expanded into
7026 -- a call to one of the GNARL delay procedures. This routine will convert
7027 -- this into a protected entry call on a delay object and then continue
7028 -- processing as for a protected entry call trigger. This requires
7029 -- declaring a Delay_Block object and adding a pointer to this object to
7030 -- the parameter list of the delay procedure to form the parameter list of
7031 -- the entry call. This object is used by the runtime to queue the delay
7032 -- request.
7033
7034 -- For a description of the use of P and the assignments after the call,
7035 -- see Expand_N_Entry_Call_Statement.
7036
7037 procedure Expand_N_Asynchronous_Select (N : Node_Id) is
7038 Loc : constant Source_Ptr := Sloc (N);
7039 Abrt : constant Node_Id := Abortable_Part (N);
7040 Trig : constant Node_Id := Triggering_Alternative (N);
7041
7042 Abort_Block_Ent : Entity_Id;
7043 Abortable_Block : Node_Id;
7044 Actuals : List_Id;
7045 Astats : List_Id;
7046 Blk_Ent : constant Entity_Id := Make_Temporary (Loc, 'A');
7047 Blk_Typ : Entity_Id;
7048 Call : Node_Id;
7049 Call_Ent : Entity_Id;
7050 Cancel_Param : Entity_Id;
7051 Cleanup_Block : Node_Id;
7052 Cleanup_Block_Ent : Entity_Id;
7053 Cleanup_Stmts : List_Id;
7054 Conc_Typ_Stmts : List_Id;
7055 Concval : Node_Id;
7056 Dblock_Ent : Entity_Id;
7057 Decl : Node_Id;
7058 Decls : List_Id;
7059 Ecall : Node_Id;
7060 Ename : Node_Id;
7061 Enqueue_Call : Node_Id;
7062 Formals : List_Id;
7063 Hdle : List_Id;
7064 Index : Node_Id;
7065 Lim_Typ_Stmts : List_Id;
7066 N_Orig : Node_Id;
7067 Obj : Entity_Id;
7068 Param : Node_Id;
7069 Params : List_Id;
7070 Pdef : Entity_Id;
7071 ProtE_Stmts : List_Id;
7072 ProtP_Stmts : List_Id;
7073 Stmt : Node_Id;
7074 Stmts : List_Id;
7075 TaskE_Stmts : List_Id;
7076 Tstats : List_Id;
7077
7078 B : Entity_Id; -- Call status flag
7079 Bnn : Entity_Id; -- Communication block
7080 C : Entity_Id; -- Call kind
7081 K : Entity_Id; -- Tagged kind
7082 P : Entity_Id; -- Parameter block
7083 S : Entity_Id; -- Primitive operation slot
7084 T : Entity_Id; -- Additional status flag
7085
7086 procedure Rewrite_Abortable_Part;
7087 -- If the trigger is a dispatching call, the expansion inserts multiple
7088 -- copies of the abortable part. This is both inefficient, and may lead
7089 -- to duplicate definitions that the back-end will reject, when the
7090 -- abortable part includes loops. This procedure rewrites the abortable
7091 -- part into a call to a generated procedure.
7092
7093 ----------------------------
7094 -- Rewrite_Abortable_Part --
7095 ----------------------------
7096
7097 procedure Rewrite_Abortable_Part is
7098 Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
7099 Decl : Node_Id;
7100
7101 begin
7102 Decl :=
7103 Make_Subprogram_Body (Loc,
7104 Specification =>
7105 Make_Procedure_Specification (Loc, Defining_Unit_Name => Proc),
7106 Declarations => New_List,
7107 Handled_Statement_Sequence =>
7108 Make_Handled_Sequence_Of_Statements (Loc, Astats));
7109 Insert_Before (N, Decl);
7110 Analyze (Decl);
7111
7112 -- Rewrite abortable part into a call to this procedure
7113
7114 Astats :=
7115 New_List (
7116 Make_Procedure_Call_Statement (Loc,
7117 Name => New_Occurrence_Of (Proc, Loc)));
7118 end Rewrite_Abortable_Part;
7119
7120 -- Start of processing for Expand_N_Asynchronous_Select
7121
7122 begin
7123 -- Asynchronous select is not supported on restricted runtimes. Don't
7124 -- try to expand.
7125
7126 if Restricted_Profile then
7127 return;
7128 end if;
7129
7130 Process_Statements_For_Controlled_Objects (Trig);
7131 Process_Statements_For_Controlled_Objects (Abrt);
7132
7133 Ecall := Triggering_Statement (Trig);
7134
7135 Ensure_Statement_Present (Sloc (Ecall), Trig);
7136
7137 -- Retrieve Astats and Tstats now because the finalization machinery may
7138 -- wrap them in blocks.
7139
7140 Astats := Statements (Abrt);
7141 Tstats := Statements (Trig);
7142
7143 -- The arguments in the call may require dynamic allocation, and the
7144 -- call statement may have been transformed into a block. The block
7145 -- may contain additional declarations for internal entities, and the
7146 -- original call is found by sequential search.
7147
7148 if Nkind (Ecall) = N_Block_Statement then
7149 Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
7150 while Nkind (Ecall) not in
7151 N_Procedure_Call_Statement | N_Entry_Call_Statement
7152 loop
7153 Next (Ecall);
7154 end loop;
7155 end if;
7156
7157 -- This is either a dispatching call or a delay statement used as a
7158 -- trigger which was expanded into a procedure call.
7159
7160 if Nkind (Ecall) = N_Procedure_Call_Statement then
7161 if Ada_Version >= Ada_2005
7162 and then
7163 (No (Original_Node (Ecall))
7164 or else Nkind (Original_Node (Ecall)) not in N_Delay_Statement)
7165 then
7166 Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
7167
7168 Rewrite_Abortable_Part;
7169 Decls := New_List;
7170 Stmts := New_List;
7171
7172 -- Call status flag processing, generate:
7173 -- B : Boolean := False;
7174
7175 B := Build_B (Loc, Decls);
7176
7177 -- Communication block processing, generate:
7178 -- Bnn : Communication_Block;
7179
7180 Bnn := Make_Temporary (Loc, 'B');
7181 Append_To (Decls,
7182 Make_Object_Declaration (Loc,
7183 Defining_Identifier => Bnn,
7184 Object_Definition =>
7185 New_Occurrence_Of (RTE (RE_Communication_Block), Loc)));
7186
7187 -- Call kind processing, generate:
7188 -- C : Ada.Tags.Prim_Op_Kind;
7189
7190 C := Build_C (Loc, Decls);
7191
7192 -- Tagged kind processing, generate:
7193 -- K : Ada.Tags.Tagged_Kind :=
7194 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7195
7196 -- Dummy communication block, generate:
7197 -- D : Dummy_Communication_Block;
7198
7199 Append_To (Decls,
7200 Make_Object_Declaration (Loc,
7201 Defining_Identifier =>
7202 Make_Defining_Identifier (Loc, Name_uD),
7203 Object_Definition =>
7204 New_Occurrence_Of
7205 (RTE (RE_Dummy_Communication_Block), Loc)));
7206
7207 K := Build_K (Loc, Decls, Obj);
7208
7209 -- Parameter block processing
7210
7211 Blk_Typ := Build_Parameter_Block
7212 (Loc, Actuals, Formals, Decls);
7213 P := Parameter_Block_Pack
7214 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
7215
7216 -- Dispatch table slot processing, generate:
7217 -- S : Integer;
7218
7219 S := Build_S (Loc, Decls);
7220
7221 -- Additional status flag processing, generate:
7222 -- Tnn : Boolean;
7223
7224 T := Make_Temporary (Loc, 'T');
7225 Append_To (Decls,
7226 Make_Object_Declaration (Loc,
7227 Defining_Identifier => T,
7228 Object_Definition =>
7229 New_Occurrence_Of (Standard_Boolean, Loc)));
7230
7231 ------------------------------
7232 -- Protected entry handling --
7233 ------------------------------
7234
7235 -- Generate:
7236 -- Param1 := P.Param1;
7237 -- ...
7238 -- ParamN := P.ParamN;
7239
7240 Cleanup_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
7241
7242 -- Generate:
7243 -- Bnn := Communication_Block (D);
7244
7245 Prepend_To (Cleanup_Stmts,
7246 Make_Assignment_Statement (Loc,
7247 Name => New_Occurrence_Of (Bnn, Loc),
7248 Expression =>
7249 Make_Unchecked_Type_Conversion (Loc,
7250 Subtype_Mark =>
7251 New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
7252 Expression => Make_Identifier (Loc, Name_uD))));
7253
7254 -- Generate:
7255 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
7256
7257 Prepend_To (Cleanup_Stmts,
7258 Make_Procedure_Call_Statement (Loc,
7259 Name =>
7260 New_Occurrence_Of
7261 (Find_Prim_Op
7262 (Etype (Etype (Obj)), Name_uDisp_Asynchronous_Select),
7263 Loc),
7264 Parameter_Associations =>
7265 New_List (
7266 New_Copy_Tree (Obj), -- <object>
7267 New_Occurrence_Of (S, Loc), -- S
7268 Make_Attribute_Reference (Loc, -- P'Address
7269 Prefix => New_Occurrence_Of (P, Loc),
7270 Attribute_Name => Name_Address),
7271 Make_Identifier (Loc, Name_uD), -- D
7272 New_Occurrence_Of (B, Loc)))); -- B
7273
7274 -- Generate:
7275 -- if Enqueued (Bnn) then
7276 -- <abortable-statements>
7277 -- end if;
7278
7279 Append_To (Cleanup_Stmts,
7280 Make_Implicit_If_Statement (N,
7281 Condition =>
7282 Make_Function_Call (Loc,
7283 Name =>
7284 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
7285 Parameter_Associations =>
7286 New_List (New_Occurrence_Of (Bnn, Loc))),
7287
7288 Then_Statements =>
7289 New_Copy_List_Tree (Astats)));
7290
7291 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7292 -- will then generate a _clean for the communication block Bnn.
7293
7294 -- Generate:
7295 -- declare
7296 -- procedure _clean is
7297 -- begin
7298 -- if Enqueued (Bnn) then
7299 -- Cancel_Protected_Entry_Call (Bnn);
7300 -- end if;
7301 -- end _clean;
7302 -- begin
7303 -- Cleanup_Stmts
7304 -- at end
7305 -- _clean;
7306 -- end;
7307
7308 Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
7309 Cleanup_Block :=
7310 Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, Bnn);
7311
7312 -- Wrap the cleanup block in an exception handling block
7313
7314 -- Generate:
7315 -- begin
7316 -- Cleanup_Block
7317 -- exception
7318 -- when Abort_Signal => Abort_Undefer;
7319 -- end;
7320
7321 Abort_Block_Ent := Make_Temporary (Loc, 'A');
7322 ProtE_Stmts :=
7323 New_List (
7324 Make_Implicit_Label_Declaration (Loc,
7325 Defining_Identifier => Abort_Block_Ent),
7326
7327 Build_Abort_Block
7328 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
7329
7330 -- Generate:
7331 -- if not Cancelled (Bnn) then
7332 -- <triggering-statements>
7333 -- end if;
7334
7335 Append_To (ProtE_Stmts,
7336 Make_Implicit_If_Statement (N,
7337 Condition =>
7338 Make_Op_Not (Loc,
7339 Right_Opnd =>
7340 Make_Function_Call (Loc,
7341 Name =>
7342 New_Occurrence_Of (RTE (RE_Cancelled), Loc),
7343 Parameter_Associations =>
7344 New_List (New_Occurrence_Of (Bnn, Loc)))),
7345
7346 Then_Statements =>
7347 New_Copy_List_Tree (Tstats)));
7348
7349 -------------------------
7350 -- Task entry handling --
7351 -------------------------
7352
7353 -- Generate:
7354 -- Param1 := P.Param1;
7355 -- ...
7356 -- ParamN := P.ParamN;
7357
7358 TaskE_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
7359
7360 -- Generate:
7361 -- Bnn := Communication_Block (D);
7362
7363 Append_To (TaskE_Stmts,
7364 Make_Assignment_Statement (Loc,
7365 Name =>
7366 New_Occurrence_Of (Bnn, Loc),
7367 Expression =>
7368 Make_Unchecked_Type_Conversion (Loc,
7369 Subtype_Mark =>
7370 New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
7371 Expression => Make_Identifier (Loc, Name_uD))));
7372
7373 -- Generate:
7374 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
7375
7376 Prepend_To (TaskE_Stmts,
7377 Make_Procedure_Call_Statement (Loc,
7378 Name =>
7379 New_Occurrence_Of (
7380 Find_Prim_Op (Etype (Etype (Obj)),
7381 Name_uDisp_Asynchronous_Select),
7382 Loc),
7383
7384 Parameter_Associations => New_List (
7385 New_Copy_Tree (Obj), -- <object>
7386 New_Occurrence_Of (S, Loc), -- S
7387 Make_Attribute_Reference (Loc, -- P'Address
7388 Prefix => New_Occurrence_Of (P, Loc),
7389 Attribute_Name => Name_Address),
7390 Make_Identifier (Loc, Name_uD), -- D
7391 New_Occurrence_Of (B, Loc)))); -- B
7392
7393 -- Generate:
7394 -- Abort_Defer;
7395
7396 Prepend_To (TaskE_Stmts, Build_Runtime_Call (Loc, RE_Abort_Defer));
7397
7398 -- Generate:
7399 -- Abort_Undefer;
7400 -- <abortable-statements>
7401
7402 Cleanup_Stmts := New_Copy_List_Tree (Astats);
7403
7404 Prepend_To
7405 (Cleanup_Stmts, Build_Runtime_Call (Loc, RE_Abort_Undefer));
7406
7407 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7408 -- will generate a _clean for the additional status flag.
7409
7410 -- Generate:
7411 -- declare
7412 -- procedure _clean is
7413 -- begin
7414 -- Cancel_Task_Entry_Call (U);
7415 -- end _clean;
7416 -- begin
7417 -- Cleanup_Stmts
7418 -- at end
7419 -- _clean;
7420 -- end;
7421
7422 Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
7423 Cleanup_Block :=
7424 Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, T);
7425
7426 -- Wrap the cleanup block in an exception handling block
7427
7428 -- Generate:
7429 -- begin
7430 -- Cleanup_Block
7431 -- exception
7432 -- when Abort_Signal => Abort_Undefer;
7433 -- end;
7434
7435 Abort_Block_Ent := Make_Temporary (Loc, 'A');
7436
7437 Append_To (TaskE_Stmts,
7438 Make_Implicit_Label_Declaration (Loc,
7439 Defining_Identifier => Abort_Block_Ent));
7440
7441 Append_To (TaskE_Stmts,
7442 Build_Abort_Block
7443 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
7444
7445 -- Generate:
7446 -- if not T then
7447 -- <triggering-statements>
7448 -- end if;
7449
7450 Append_To (TaskE_Stmts,
7451 Make_Implicit_If_Statement (N,
7452 Condition =>
7453 Make_Op_Not (Loc, Right_Opnd => New_Occurrence_Of (T, Loc)),
7454
7455 Then_Statements =>
7456 New_Copy_List_Tree (Tstats)));
7457
7458 ----------------------------------
7459 -- Protected procedure handling --
7460 ----------------------------------
7461
7462 -- Generate:
7463 -- <dispatching-call>;
7464 -- <triggering-statements>
7465
7466 ProtP_Stmts := New_Copy_List_Tree (Tstats);
7467 Prepend_To (ProtP_Stmts, New_Copy_Tree (Ecall));
7468
7469 -- Generate:
7470 -- S := Ada.Tags.Get_Offset_Index
7471 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
7472
7473 Conc_Typ_Stmts :=
7474 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
7475
7476 -- Generate:
7477 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
7478
7479 Append_To (Conc_Typ_Stmts,
7480 Make_Procedure_Call_Statement (Loc,
7481 Name =>
7482 New_Occurrence_Of
7483 (Find_Prim_Op (Etype (Etype (Obj)),
7484 Name_uDisp_Get_Prim_Op_Kind),
7485 Loc),
7486 Parameter_Associations =>
7487 New_List (
7488 New_Copy_Tree (Obj),
7489 New_Occurrence_Of (S, Loc),
7490 New_Occurrence_Of (C, Loc))));
7491
7492 -- Generate:
7493 -- if C = POK_Procedure_Entry then
7494 -- ProtE_Stmts
7495 -- elsif C = POK_Task_Entry then
7496 -- TaskE_Stmts
7497 -- else
7498 -- ProtP_Stmts
7499 -- end if;
7500
7501 Append_To (Conc_Typ_Stmts,
7502 Make_Implicit_If_Statement (N,
7503 Condition =>
7504 Make_Op_Eq (Loc,
7505 Left_Opnd =>
7506 New_Occurrence_Of (C, Loc),
7507 Right_Opnd =>
7508 New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
7509
7510 Then_Statements =>
7511 ProtE_Stmts,
7512
7513 Elsif_Parts =>
7514 New_List (
7515 Make_Elsif_Part (Loc,
7516 Condition =>
7517 Make_Op_Eq (Loc,
7518 Left_Opnd =>
7519 New_Occurrence_Of (C, Loc),
7520 Right_Opnd =>
7521 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc)),
7522
7523 Then_Statements =>
7524 TaskE_Stmts)),
7525
7526 Else_Statements =>
7527 ProtP_Stmts));
7528
7529 -- Generate:
7530 -- <dispatching-call>;
7531 -- <triggering-statements>
7532
7533 Lim_Typ_Stmts := New_Copy_List_Tree (Tstats);
7534 Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Ecall));
7535
7536 -- Generate:
7537 -- if K = Ada.Tags.TK_Limited_Tagged
7538 -- or else K = Ada.Tags.TK_Tagged
7539 -- then
7540 -- Lim_Typ_Stmts
7541 -- else
7542 -- Conc_Typ_Stmts
7543 -- end if;
7544
7545 Append_To (Stmts,
7546 Make_Implicit_If_Statement (N,
7547 Condition => Build_Dispatching_Tag_Check (K, N),
7548 Then_Statements => Lim_Typ_Stmts,
7549 Else_Statements => Conc_Typ_Stmts));
7550
7551 Rewrite (N,
7552 Make_Block_Statement (Loc,
7553 Declarations =>
7554 Decls,
7555 Handled_Statement_Sequence =>
7556 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7557
7558 Analyze (N);
7559 return;
7560
7561 -- Delay triggering statement processing
7562
7563 else
7564 -- Add a Delay_Block object to the parameter list of the delay
7565 -- procedure to form the parameter list of the Wait entry call.
7566
7567 Dblock_Ent := Make_Temporary (Loc, 'D');
7568
7569 Pdef := Entity (Name (Ecall));
7570
7571 if Is_RTE (Pdef, RO_CA_Delay_For) then
7572 Enqueue_Call :=
7573 New_Occurrence_Of (RTE (RE_Enqueue_Duration), Loc);
7574
7575 elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
7576 Enqueue_Call :=
7577 New_Occurrence_Of (RTE (RE_Enqueue_Calendar), Loc);
7578
7579 else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
7580 Enqueue_Call := New_Occurrence_Of (RTE (RE_Enqueue_RT), Loc);
7581 end if;
7582
7583 Append_To (Parameter_Associations (Ecall),
7584 Make_Attribute_Reference (Loc,
7585 Prefix => New_Occurrence_Of (Dblock_Ent, Loc),
7586 Attribute_Name => Name_Unchecked_Access));
7587
7588 -- Create the inner block to protect the abortable part
7589
7590 Hdle := New_List (Build_Abort_Block_Handler (Loc));
7591
7592 Prepend_To (Astats, Build_Runtime_Call (Loc, RE_Abort_Undefer));
7593
7594 Abortable_Block :=
7595 Make_Block_Statement (Loc,
7596 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
7597 Handled_Statement_Sequence =>
7598 Make_Handled_Sequence_Of_Statements (Loc,
7599 Statements => Astats),
7600 Has_Created_Identifier => True,
7601 Is_Asynchronous_Call_Block => True);
7602
7603 -- Append call to if Enqueue (When, DB'Unchecked_Access) then
7604
7605 Rewrite (Ecall,
7606 Make_Implicit_If_Statement (N,
7607 Condition =>
7608 Make_Function_Call (Loc,
7609 Name => Enqueue_Call,
7610 Parameter_Associations => Parameter_Associations (Ecall)),
7611 Then_Statements =>
7612 New_List (Make_Block_Statement (Loc,
7613 Handled_Statement_Sequence =>
7614 Make_Handled_Sequence_Of_Statements (Loc,
7615 Statements => New_List (
7616 Make_Implicit_Label_Declaration (Loc,
7617 Defining_Identifier => Blk_Ent,
7618 Label_Construct => Abortable_Block),
7619 Abortable_Block),
7620 Exception_Handlers => Hdle)))));
7621
7622 Stmts := New_List (Ecall);
7623
7624 -- Construct statement sequence for new block
7625
7626 Append_To (Stmts,
7627 Make_Implicit_If_Statement (N,
7628 Condition =>
7629 Make_Function_Call (Loc,
7630 Name => New_Occurrence_Of (
7631 RTE (RE_Timed_Out), Loc),
7632 Parameter_Associations => New_List (
7633 Make_Attribute_Reference (Loc,
7634 Prefix => New_Occurrence_Of (Dblock_Ent, Loc),
7635 Attribute_Name => Name_Unchecked_Access))),
7636 Then_Statements => Tstats));
7637
7638 -- The result is the new block
7639
7640 Set_Entry_Cancel_Parameter (Blk_Ent, Dblock_Ent);
7641
7642 Rewrite (N,
7643 Make_Block_Statement (Loc,
7644 Declarations => New_List (
7645 Make_Object_Declaration (Loc,
7646 Defining_Identifier => Dblock_Ent,
7647 Aliased_Present => True,
7648 Object_Definition =>
7649 New_Occurrence_Of (RTE (RE_Delay_Block), Loc))),
7650
7651 Handled_Statement_Sequence =>
7652 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7653
7654 Analyze (N);
7655 return;
7656 end if;
7657
7658 else
7659 N_Orig := N;
7660 end if;
7661
7662 Extract_Entry (Ecall, Concval, Ename, Index);
7663 Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
7664
7665 Stmts := Statements (Handled_Statement_Sequence (Ecall));
7666 Decls := Declarations (Ecall);
7667
7668 if Is_Protected_Type (Etype (Concval)) then
7669
7670 -- Get the declarations of the block expanded from the entry call
7671
7672 Decl := First (Decls);
7673 while Present (Decl)
7674 and then (Nkind (Decl) /= N_Object_Declaration
7675 or else not Is_RTE (Etype (Object_Definition (Decl)),
7676 RE_Communication_Block))
7677 loop
7678 Next (Decl);
7679 end loop;
7680
7681 pragma Assert (Present (Decl));
7682 Cancel_Param := Defining_Identifier (Decl);
7683
7684 -- Change the mode of the Protected_Entry_Call call
7685
7686 -- Protected_Entry_Call (
7687 -- Object => po._object'Access,
7688 -- E => <entry index>;
7689 -- Uninterpreted_Data => P'Address;
7690 -- Mode => Asynchronous_Call;
7691 -- Block => Bnn);
7692
7693 -- Skip assignments to temporaries created for in-out parameters
7694
7695 -- This makes unwarranted assumptions about the shape of the expanded
7696 -- tree for the call, and should be cleaned up ???
7697
7698 Stmt := First (Stmts);
7699 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7700 Next (Stmt);
7701 end loop;
7702
7703 Call := Stmt;
7704
7705 Param := First (Parameter_Associations (Call));
7706 while Present (Param)
7707 and then not Is_RTE (Etype (Param), RE_Call_Modes)
7708 loop
7709 Next (Param);
7710 end loop;
7711
7712 pragma Assert (Present (Param));
7713 Rewrite (Param, New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
7714 Analyze (Param);
7715
7716 -- Append an if statement to execute the abortable part
7717
7718 -- Generate:
7719 -- if Enqueued (Bnn) then
7720
7721 Append_To (Stmts,
7722 Make_Implicit_If_Statement (N,
7723 Condition =>
7724 Make_Function_Call (Loc,
7725 Name => New_Occurrence_Of (RTE (RE_Enqueued), Loc),
7726 Parameter_Associations => New_List (
7727 New_Occurrence_Of (Cancel_Param, Loc))),
7728 Then_Statements => Astats));
7729
7730 Abortable_Block :=
7731 Make_Block_Statement (Loc,
7732 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
7733 Handled_Statement_Sequence =>
7734 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts),
7735 Has_Created_Identifier => True,
7736 Is_Asynchronous_Call_Block => True);
7737
7738 Stmts := New_List (
7739 Make_Block_Statement (Loc,
7740 Handled_Statement_Sequence =>
7741 Make_Handled_Sequence_Of_Statements (Loc,
7742 Statements => New_List (
7743 Make_Implicit_Label_Declaration (Loc,
7744 Defining_Identifier => Blk_Ent,
7745 Label_Construct => Abortable_Block),
7746 Abortable_Block),
7747
7748 -- exception
7749
7750 Exception_Handlers => New_List (
7751 Make_Implicit_Exception_Handler (Loc,
7752
7753 -- when Abort_Signal =>
7754 -- null;
7755
7756 Exception_Choices =>
7757 New_List (New_Occurrence_Of (Stand.Abort_Signal, Loc)),
7758 Statements => New_List (Make_Null_Statement (Loc)))))),
7759
7760 -- if not Cancelled (Bnn) then
7761 -- triggered statements
7762 -- end if;
7763
7764 Make_Implicit_If_Statement (N,
7765 Condition => Make_Op_Not (Loc,
7766 Right_Opnd =>
7767 Make_Function_Call (Loc,
7768 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
7769 Parameter_Associations => New_List (
7770 New_Occurrence_Of (Cancel_Param, Loc)))),
7771 Then_Statements => Tstats));
7772
7773 -- Asynchronous task entry call
7774
7775 else
7776 if No (Decls) then
7777 Decls := New_List;
7778 end if;
7779
7780 B := Make_Defining_Identifier (Loc, Name_uB);
7781
7782 -- Insert declaration of B in declarations of existing block
7783
7784 Prepend_To (Decls,
7785 Make_Object_Declaration (Loc,
7786 Defining_Identifier => B,
7787 Object_Definition =>
7788 New_Occurrence_Of (Standard_Boolean, Loc)));
7789
7790 Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
7791
7792 -- Insert the declaration of C in the declarations of the existing
7793 -- block. The variable is initialized to something (True or False,
7794 -- does not matter) to prevent CodePeer from complaining about a
7795 -- possible read of an uninitialized variable.
7796
7797 Prepend_To (Decls,
7798 Make_Object_Declaration (Loc,
7799 Defining_Identifier => Cancel_Param,
7800 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
7801 Expression => New_Occurrence_Of (Standard_False, Loc),
7802 Has_Init_Expression => True));
7803
7804 -- Remove and save the call to Call_Simple
7805
7806 Stmt := First (Stmts);
7807
7808 -- Skip assignments to temporaries created for in-out parameters.
7809 -- This makes unwarranted assumptions about the shape of the expanded
7810 -- tree for the call, and should be cleaned up ???
7811
7812 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7813 Next (Stmt);
7814 end loop;
7815
7816 Call := Stmt;
7817
7818 -- Create the inner block to protect the abortable part
7819
7820 Hdle := New_List (Build_Abort_Block_Handler (Loc));
7821
7822 Prepend_To (Astats, Build_Runtime_Call (Loc, RE_Abort_Undefer));
7823
7824 Abortable_Block :=
7825 Make_Block_Statement (Loc,
7826 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
7827 Handled_Statement_Sequence =>
7828 Make_Handled_Sequence_Of_Statements (Loc, Statements => Astats),
7829 Has_Created_Identifier => True,
7830 Is_Asynchronous_Call_Block => True);
7831
7832 Insert_After (Call,
7833 Make_Block_Statement (Loc,
7834 Handled_Statement_Sequence =>
7835 Make_Handled_Sequence_Of_Statements (Loc,
7836 Statements => New_List (
7837 Make_Implicit_Label_Declaration (Loc,
7838 Defining_Identifier => Blk_Ent,
7839 Label_Construct => Abortable_Block),
7840 Abortable_Block),
7841 Exception_Handlers => Hdle)));
7842
7843 -- Create new call statement
7844
7845 Params := Parameter_Associations (Call);
7846
7847 Append_To (Params,
7848 New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
7849 Append_To (Params, New_Occurrence_Of (B, Loc));
7850
7851 Rewrite (Call,
7852 Make_Procedure_Call_Statement (Loc,
7853 Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
7854 Parameter_Associations => Params));
7855
7856 -- Construct statement sequence for new block
7857
7858 Append_To (Stmts,
7859 Make_Implicit_If_Statement (N,
7860 Condition =>
7861 Make_Op_Not (Loc, New_Occurrence_Of (Cancel_Param, Loc)),
7862 Then_Statements => Tstats));
7863
7864 -- Protected the call against abort
7865
7866 Prepend_To (Stmts, Build_Runtime_Call (Loc, RE_Abort_Defer));
7867 end if;
7868
7869 Set_Entry_Cancel_Parameter (Blk_Ent, Cancel_Param);
7870
7871 -- The result is the new block
7872
7873 Rewrite (N_Orig,
7874 Make_Block_Statement (Loc,
7875 Declarations => Decls,
7876 Handled_Statement_Sequence =>
7877 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7878
7879 Analyze (N_Orig);
7880 end Expand_N_Asynchronous_Select;
7881
7882 -------------------------------------
7883 -- Expand_N_Conditional_Entry_Call --
7884 -------------------------------------
7885
7886 -- The conditional task entry call is converted to a call to
7887 -- Task_Entry_Call:
7888
7889 -- declare
7890 -- B : Boolean;
7891 -- P : parms := (parm, parm, parm);
7892
7893 -- begin
7894 -- Task_Entry_Call
7895 -- (<acceptor-task>, -- Acceptor
7896 -- <entry-index>, -- E
7897 -- P'Address, -- Uninterpreted_Data
7898 -- Conditional_Call, -- Mode
7899 -- B); -- Rendezvous_Successful
7900 -- parm := P.param;
7901 -- parm := P.param;
7902 -- ...
7903 -- if B then
7904 -- normal-statements
7905 -- else
7906 -- else-statements
7907 -- end if;
7908 -- end;
7909
7910 -- For a description of the use of P and the assignments after the call,
7911 -- see Expand_N_Entry_Call_Statement. Note that the entry call of the
7912 -- conditional entry call has already been expanded (by the Expand_N_Entry
7913 -- _Call_Statement procedure) as follows:
7914
7915 -- declare
7916 -- P : parms := (parm, parm, parm);
7917 -- begin
7918 -- ... info for in-out parameters
7919 -- Call_Simple (acceptor-task, entry-index, P'Address);
7920 -- parm := P.param;
7921 -- parm := P.param;
7922 -- ...
7923 -- end;
7924
7925 -- so the task at hand is to convert the latter expansion into the former
7926
7927 -- The conditional protected entry call is converted to a call to
7928 -- Protected_Entry_Call:
7929
7930 -- declare
7931 -- P : parms := (parm, parm, parm);
7932 -- Bnn : Communications_Block;
7933
7934 -- begin
7935 -- Protected_Entry_Call
7936 -- (po._object'Access, -- Object
7937 -- <entry index>, -- E
7938 -- P'Address, -- Uninterpreted_Data
7939 -- Conditional_Call, -- Mode
7940 -- Bnn); -- Block
7941 -- parm := P.param;
7942 -- parm := P.param;
7943 -- ...
7944 -- if Cancelled (Bnn) then
7945 -- else-statements
7946 -- else
7947 -- normal-statements
7948 -- end if;
7949 -- end;
7950
7951 -- Ada 2005 (AI-345): A dispatching conditional entry call is converted
7952 -- into:
7953
7954 -- declare
7955 -- B : Boolean := False;
7956 -- C : Ada.Tags.Prim_Op_Kind;
7957 -- K : Ada.Tags.Tagged_Kind :=
7958 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7959 -- P : Parameters := (Param1 .. ParamN);
7960 -- S : Integer;
7961
7962 -- begin
7963 -- if K = Ada.Tags.TK_Limited_Tagged
7964 -- or else K = Ada.Tags.TK_Tagged
7965 -- then
7966 -- <dispatching-call>;
7967 -- <triggering-statements>
7968
7969 -- else
7970 -- S :=
7971 -- Ada.Tags.Get_Offset_Index
7972 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
7973
7974 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
7975
7976 -- if C = POK_Protected_Entry
7977 -- or else C = POK_Task_Entry
7978 -- then
7979 -- Param1 := P.Param1;
7980 -- ...
7981 -- ParamN := P.ParamN;
7982 -- end if;
7983
7984 -- if B then
7985 -- if C = POK_Procedure
7986 -- or else C = POK_Protected_Procedure
7987 -- or else C = POK_Task_Procedure
7988 -- then
7989 -- <dispatching-call>;
7990 -- end if;
7991
7992 -- <triggering-statements>
7993 -- else
7994 -- <else-statements>
7995 -- end if;
7996 -- end if;
7997 -- end;
7998
7999 procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
8000 Loc : constant Source_Ptr := Sloc (N);
8001 Alt : constant Node_Id := Entry_Call_Alternative (N);
8002 Blk : Node_Id := Entry_Call_Statement (Alt);
8003
8004 Actuals : List_Id;
8005 Blk_Typ : Entity_Id;
8006 Call : Node_Id;
8007 Call_Ent : Entity_Id;
8008 Conc_Typ_Stmts : List_Id;
8009 Decl : Node_Id;
8010 Decls : List_Id;
8011 Formals : List_Id;
8012 Lim_Typ_Stmts : List_Id;
8013 N_Stats : List_Id;
8014 Obj : Entity_Id;
8015 Param : Node_Id;
8016 Params : List_Id;
8017 Stmt : Node_Id;
8018 Stmts : List_Id;
8019 Transient_Blk : Node_Id;
8020 Unpack : List_Id;
8021
8022 B : Entity_Id; -- Call status flag
8023 C : Entity_Id; -- Call kind
8024 K : Entity_Id; -- Tagged kind
8025 P : Entity_Id; -- Parameter block
8026 S : Entity_Id; -- Primitive operation slot
8027
8028 begin
8029 Process_Statements_For_Controlled_Objects (N);
8030
8031 if Ada_Version >= Ada_2005
8032 and then Nkind (Blk) = N_Procedure_Call_Statement
8033 then
8034 Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
8035
8036 Decls := New_List;
8037 Stmts := New_List;
8038
8039 -- Call status flag processing, generate:
8040 -- B : Boolean := False;
8041
8042 B := Build_B (Loc, Decls);
8043
8044 -- Call kind processing, generate:
8045 -- C : Ada.Tags.Prim_Op_Kind;
8046
8047 C := Build_C (Loc, Decls);
8048
8049 -- Tagged kind processing, generate:
8050 -- K : Ada.Tags.Tagged_Kind :=
8051 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
8052
8053 K := Build_K (Loc, Decls, Obj);
8054
8055 -- Parameter block processing
8056
8057 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
8058 P := Parameter_Block_Pack
8059 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
8060
8061 -- Dispatch table slot processing, generate:
8062 -- S : Integer;
8063
8064 S := Build_S (Loc, Decls);
8065
8066 -- Generate:
8067 -- S := Ada.Tags.Get_Offset_Index
8068 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
8069
8070 Conc_Typ_Stmts :=
8071 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
8072
8073 -- Generate:
8074 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
8075
8076 Append_To (Conc_Typ_Stmts,
8077 Make_Procedure_Call_Statement (Loc,
8078 Name =>
8079 New_Occurrence_Of (
8080 Find_Prim_Op (Etype (Etype (Obj)),
8081 Name_uDisp_Conditional_Select),
8082 Loc),
8083 Parameter_Associations =>
8084 New_List (
8085 New_Copy_Tree (Obj), -- <object>
8086 New_Occurrence_Of (S, Loc), -- S
8087 Make_Attribute_Reference (Loc, -- P'Address
8088 Prefix => New_Occurrence_Of (P, Loc),
8089 Attribute_Name => Name_Address),
8090 New_Occurrence_Of (C, Loc), -- C
8091 New_Occurrence_Of (B, Loc)))); -- B
8092
8093 -- Generate:
8094 -- if C = POK_Protected_Entry
8095 -- or else C = POK_Task_Entry
8096 -- then
8097 -- Param1 := P.Param1;
8098 -- ...
8099 -- ParamN := P.ParamN;
8100 -- end if;
8101
8102 Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
8103
8104 -- Generate the if statement only when the packed parameters need
8105 -- explicit assignments to their corresponding actuals.
8106
8107 if Present (Unpack) then
8108 Append_To (Conc_Typ_Stmts,
8109 Make_Implicit_If_Statement (N,
8110 Condition =>
8111 Make_Or_Else (Loc,
8112 Left_Opnd =>
8113 Make_Op_Eq (Loc,
8114 Left_Opnd =>
8115 New_Occurrence_Of (C, Loc),
8116 Right_Opnd =>
8117 New_Occurrence_Of (RTE (
8118 RE_POK_Protected_Entry), Loc)),
8119
8120 Right_Opnd =>
8121 Make_Op_Eq (Loc,
8122 Left_Opnd =>
8123 New_Occurrence_Of (C, Loc),
8124 Right_Opnd =>
8125 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
8126
8127 Then_Statements => Unpack));
8128 end if;
8129
8130 -- Generate:
8131 -- if B then
8132 -- if C = POK_Procedure
8133 -- or else C = POK_Protected_Procedure
8134 -- or else C = POK_Task_Procedure
8135 -- then
8136 -- <dispatching-call>
8137 -- end if;
8138 -- <normal-statements>
8139 -- else
8140 -- <else-statements>
8141 -- end if;
8142
8143 N_Stats := New_Copy_Separate_List (Statements (Alt));
8144
8145 Prepend_To (N_Stats,
8146 Make_Implicit_If_Statement (N,
8147 Condition =>
8148 Make_Or_Else (Loc,
8149 Left_Opnd =>
8150 Make_Op_Eq (Loc,
8151 Left_Opnd =>
8152 New_Occurrence_Of (C, Loc),
8153 Right_Opnd =>
8154 New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
8155
8156 Right_Opnd =>
8157 Make_Or_Else (Loc,
8158 Left_Opnd =>
8159 Make_Op_Eq (Loc,
8160 Left_Opnd =>
8161 New_Occurrence_Of (C, Loc),
8162 Right_Opnd =>
8163 New_Occurrence_Of (RTE (
8164 RE_POK_Protected_Procedure), Loc)),
8165
8166 Right_Opnd =>
8167 Make_Op_Eq (Loc,
8168 Left_Opnd =>
8169 New_Occurrence_Of (C, Loc),
8170 Right_Opnd =>
8171 New_Occurrence_Of (RTE (
8172 RE_POK_Task_Procedure), Loc)))),
8173
8174 Then_Statements =>
8175 New_List (Blk)));
8176
8177 Append_To (Conc_Typ_Stmts,
8178 Make_Implicit_If_Statement (N,
8179 Condition => New_Occurrence_Of (B, Loc),
8180 Then_Statements => N_Stats,
8181 Else_Statements => Else_Statements (N)));
8182
8183 -- Generate:
8184 -- <dispatching-call>;
8185 -- <triggering-statements>
8186
8187 Lim_Typ_Stmts := New_Copy_Separate_List (Statements (Alt));
8188 Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Blk));
8189
8190 -- Generate:
8191 -- if K = Ada.Tags.TK_Limited_Tagged
8192 -- or else K = Ada.Tags.TK_Tagged
8193 -- then
8194 -- Lim_Typ_Stmts
8195 -- else
8196 -- Conc_Typ_Stmts
8197 -- end if;
8198
8199 Append_To (Stmts,
8200 Make_Implicit_If_Statement (N,
8201 Condition => Build_Dispatching_Tag_Check (K, N),
8202 Then_Statements => Lim_Typ_Stmts,
8203 Else_Statements => Conc_Typ_Stmts));
8204
8205 Rewrite (N,
8206 Make_Block_Statement (Loc,
8207 Declarations =>
8208 Decls,
8209 Handled_Statement_Sequence =>
8210 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
8211
8212 -- As described above, the entry alternative is transformed into a
8213 -- block that contains the gnulli call, and possibly assignment
8214 -- statements for in-out parameters. The gnulli call may itself be
8215 -- rewritten into a transient block if some unconstrained parameters
8216 -- require it. We need to retrieve the call to complete its parameter
8217 -- list.
8218
8219 else
8220 Transient_Blk :=
8221 First_Real_Statement (Handled_Statement_Sequence (Blk));
8222
8223 if Present (Transient_Blk)
8224 and then Nkind (Transient_Blk) = N_Block_Statement
8225 then
8226 Blk := Transient_Blk;
8227 end if;
8228
8229 Stmts := Statements (Handled_Statement_Sequence (Blk));
8230 Stmt := First (Stmts);
8231 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
8232 Next (Stmt);
8233 end loop;
8234
8235 Call := Stmt;
8236 Params := Parameter_Associations (Call);
8237
8238 if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
8239
8240 -- Substitute Conditional_Entry_Call for Simple_Call parameter
8241
8242 Param := First (Params);
8243 while Present (Param)
8244 and then not Is_RTE (Etype (Param), RE_Call_Modes)
8245 loop
8246 Next (Param);
8247 end loop;
8248
8249 pragma Assert (Present (Param));
8250 Rewrite (Param,
8251 New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
8252
8253 Analyze (Param);
8254
8255 -- Find the Communication_Block parameter for the call to the
8256 -- Cancelled function.
8257
8258 Decl := First (Declarations (Blk));
8259 while Present (Decl)
8260 and then not Is_RTE (Etype (Object_Definition (Decl)),
8261 RE_Communication_Block)
8262 loop
8263 Next (Decl);
8264 end loop;
8265
8266 -- Add an if statement to execute the else part if the call
8267 -- does not succeed (as indicated by the Cancelled predicate).
8268
8269 Append_To (Stmts,
8270 Make_Implicit_If_Statement (N,
8271 Condition => Make_Function_Call (Loc,
8272 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
8273 Parameter_Associations => New_List (
8274 New_Occurrence_Of (Defining_Identifier (Decl), Loc))),
8275 Then_Statements => Else_Statements (N),
8276 Else_Statements => Statements (Alt)));
8277
8278 else
8279 B := Make_Defining_Identifier (Loc, Name_uB);
8280
8281 -- Insert declaration of B in declarations of existing block
8282
8283 if No (Declarations (Blk)) then
8284 Set_Declarations (Blk, New_List);
8285 end if;
8286
8287 Prepend_To (Declarations (Blk),
8288 Make_Object_Declaration (Loc,
8289 Defining_Identifier => B,
8290 Object_Definition =>
8291 New_Occurrence_Of (Standard_Boolean, Loc)));
8292
8293 -- Create new call statement
8294
8295 Append_To (Params,
8296 New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
8297 Append_To (Params, New_Occurrence_Of (B, Loc));
8298
8299 Rewrite (Call,
8300 Make_Procedure_Call_Statement (Loc,
8301 Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
8302 Parameter_Associations => Params));
8303
8304 -- Construct statement sequence for new block
8305
8306 Append_To (Stmts,
8307 Make_Implicit_If_Statement (N,
8308 Condition => New_Occurrence_Of (B, Loc),
8309 Then_Statements => Statements (Alt),
8310 Else_Statements => Else_Statements (N)));
8311 end if;
8312
8313 -- The result is the new block
8314
8315 Rewrite (N,
8316 Make_Block_Statement (Loc,
8317 Declarations => Declarations (Blk),
8318 Handled_Statement_Sequence =>
8319 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
8320 end if;
8321
8322 Analyze (N);
8323
8324 Reset_Scopes_To (N, Entity (Identifier (N)));
8325 end Expand_N_Conditional_Entry_Call;
8326
8327 ---------------------------------------
8328 -- Expand_N_Delay_Relative_Statement --
8329 ---------------------------------------
8330
8331 -- Delay statement is implemented as a procedure call to Delay_For
8332 -- defined in Ada.Calendar.Delays in order to reduce the overhead of
8333 -- simple delays imposed by the use of Protected Objects.
8334
8335 procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
8336 Loc : constant Source_Ptr := Sloc (N);
8337 Proc : Entity_Id;
8338
8339 begin
8340 -- Try to use Ada.Calendar.Delays.Delay_For if available.
8341
8342 if RTE_Available (RO_CA_Delay_For) then
8343 Proc := RTE (RO_CA_Delay_For);
8344
8345 -- Otherwise, use System.Relative_Delays.Delay_For and emit an error
8346 -- message if not available. This is the implementation used on
8347 -- restricted platforms when Ada.Calendar is not available.
8348
8349 else
8350 Proc := RTE (RO_RD_Delay_For);
8351 end if;
8352
8353 Rewrite (N,
8354 Make_Procedure_Call_Statement (Loc,
8355 Name => New_Occurrence_Of (Proc, Loc),
8356 Parameter_Associations => New_List (Expression (N))));
8357 Analyze (N);
8358 end Expand_N_Delay_Relative_Statement;
8359
8360 ------------------------------------
8361 -- Expand_N_Delay_Until_Statement --
8362 ------------------------------------
8363
8364 -- Delay Until statement is implemented as a procedure call to
8365 -- Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
8366
8367 procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
8368 Loc : constant Source_Ptr := Sloc (N);
8369 Typ : Entity_Id;
8370
8371 begin
8372 if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
8373 Typ := RTE (RO_CA_Delay_Until);
8374 else
8375 Typ := RTE (RO_RT_Delay_Until);
8376 end if;
8377
8378 Rewrite (N,
8379 Make_Procedure_Call_Statement (Loc,
8380 Name => New_Occurrence_Of (Typ, Loc),
8381 Parameter_Associations => New_List (Expression (N))));
8382
8383 Analyze (N);
8384 end Expand_N_Delay_Until_Statement;
8385
8386 -------------------------
8387 -- Expand_N_Entry_Body --
8388 -------------------------
8389
8390 procedure Expand_N_Entry_Body (N : Node_Id) is
8391 begin
8392 -- Associate discriminals with the next protected operation body to be
8393 -- expanded.
8394
8395 if Present (Next_Protected_Operation (N)) then
8396 Set_Discriminals (Parent (Current_Scope));
8397 end if;
8398 end Expand_N_Entry_Body;
8399
8400 -----------------------------------
8401 -- Expand_N_Entry_Call_Statement --
8402 -----------------------------------
8403
8404 -- An entry call is expanded into GNARLI calls to implement a simple entry
8405 -- call (see Build_Simple_Entry_Call).
8406
8407 procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
8408 Concval : Node_Id;
8409 Ename : Node_Id;
8410 Index : Node_Id;
8411
8412 begin
8413 if No_Run_Time_Mode then
8414 Error_Msg_CRT ("entry call", N);
8415 return;
8416 end if;
8417
8418 -- If this entry call is part of an asynchronous select, don't expand it
8419 -- here; it will be expanded with the select statement. Don't expand
8420 -- timed entry calls either, as they are translated into asynchronous
8421 -- entry calls.
8422
8423 -- ??? This whole approach is questionable; it may be better to go back
8424 -- to allowing the expansion to take place and then attempting to fix it
8425 -- up in Expand_N_Asynchronous_Select. The tricky part is figuring out
8426 -- whether the expanded call is on a task or protected entry.
8427
8428 if (Nkind (Parent (N)) /= N_Triggering_Alternative
8429 or else N /= Triggering_Statement (Parent (N)))
8430 and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
8431 or else N /= Entry_Call_Statement (Parent (N))
8432 or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
8433 then
8434 Extract_Entry (N, Concval, Ename, Index);
8435 Build_Simple_Entry_Call (N, Concval, Ename, Index);
8436 end if;
8437 end Expand_N_Entry_Call_Statement;
8438
8439 --------------------------------
8440 -- Expand_N_Entry_Declaration --
8441 --------------------------------
8442
8443 -- If there are parameters, then first, each of the formals is marked by
8444 -- setting Is_Entry_Formal. Next a record type is built which is used to
8445 -- hold the parameter values. The name of this record type is entryP where
8446 -- entry is the name of the entry, with an additional corresponding access
8447 -- type called entryPA. The record type has matching components for each
8448 -- formal (the component names are the same as the formal names). For
8449 -- elementary types, the component type matches the formal type. For
8450 -- composite types, an access type is declared (with the name formalA)
8451 -- which designates the formal type, and the type of the component is this
8452 -- access type. Finally the Entry_Component of each formal is set to
8453 -- reference the corresponding record component.
8454
8455 procedure Expand_N_Entry_Declaration (N : Node_Id) is
8456 Loc : constant Source_Ptr := Sloc (N);
8457 Entry_Ent : constant Entity_Id := Defining_Identifier (N);
8458 Components : List_Id;
8459 Formal : Node_Id;
8460 Ftype : Entity_Id;
8461 Last_Decl : Node_Id;
8462 Component : Entity_Id;
8463 Ctype : Entity_Id;
8464 Decl : Node_Id;
8465 Rec_Ent : Entity_Id;
8466 Acc_Ent : Entity_Id;
8467
8468 begin
8469 Formal := First_Formal (Entry_Ent);
8470 Last_Decl := N;
8471
8472 -- Most processing is done only if parameters are present
8473
8474 if Present (Formal) then
8475 Components := New_List;
8476
8477 -- Loop through formals
8478
8479 while Present (Formal) loop
8480 Set_Is_Entry_Formal (Formal);
8481 Component :=
8482 Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
8483 Set_Entry_Component (Formal, Component);
8484 Set_Entry_Formal (Component, Formal);
8485 Ftype := Etype (Formal);
8486
8487 -- Declare new access type and then append
8488
8489 Ctype := Make_Temporary (Loc, 'A');
8490 Set_Is_Param_Block_Component_Type (Ctype);
8491
8492 Decl :=
8493 Make_Full_Type_Declaration (Loc,
8494 Defining_Identifier => Ctype,
8495 Type_Definition =>
8496 Make_Access_To_Object_Definition (Loc,
8497 All_Present => True,
8498 Constant_Present => Ekind (Formal) = E_In_Parameter,
8499 Subtype_Indication => New_Occurrence_Of (Ftype, Loc)));
8500
8501 Insert_After (Last_Decl, Decl);
8502 Last_Decl := Decl;
8503
8504 Append_To (Components,
8505 Make_Component_Declaration (Loc,
8506 Defining_Identifier => Component,
8507 Component_Definition =>
8508 Make_Component_Definition (Loc,
8509 Aliased_Present => False,
8510 Subtype_Indication => New_Occurrence_Of (Ctype, Loc))));
8511
8512 Next_Formal_With_Extras (Formal);
8513 end loop;
8514
8515 -- Create the Entry_Parameter_Record declaration
8516
8517 Rec_Ent := Make_Temporary (Loc, 'P');
8518
8519 Decl :=
8520 Make_Full_Type_Declaration (Loc,
8521 Defining_Identifier => Rec_Ent,
8522 Type_Definition =>
8523 Make_Record_Definition (Loc,
8524 Component_List =>
8525 Make_Component_List (Loc,
8526 Component_Items => Components)));
8527
8528 Insert_After (Last_Decl, Decl);
8529 Last_Decl := Decl;
8530
8531 -- Construct and link in the corresponding access type
8532
8533 Acc_Ent := Make_Temporary (Loc, 'A');
8534
8535 Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
8536
8537 Decl :=
8538 Make_Full_Type_Declaration (Loc,
8539 Defining_Identifier => Acc_Ent,
8540 Type_Definition =>
8541 Make_Access_To_Object_Definition (Loc,
8542 All_Present => True,
8543 Subtype_Indication => New_Occurrence_Of (Rec_Ent, Loc)));
8544
8545 Insert_After (Last_Decl, Decl);
8546 end if;
8547 end Expand_N_Entry_Declaration;
8548
8549 -----------------------------
8550 -- Expand_N_Protected_Body --
8551 -----------------------------
8552
8553 -- Protected bodies are expanded to the completion of the subprograms
8554 -- created for the corresponding protected type. These are a protected and
8555 -- unprotected version of each protected subprogram in the object, a
8556 -- function to calculate each entry barrier, and a procedure to execute the
8557 -- sequence of statements of each protected entry body. For example, for
8558 -- protected type ptype:
8559
8560 -- function entB
8561 -- (O : System.Address;
8562 -- E : Protected_Entry_Index)
8563 -- return Boolean
8564 -- is
8565 -- <discriminant renamings>
8566 -- <private object renamings>
8567 -- begin
8568 -- return <barrier expression>;
8569 -- end entB;
8570
8571 -- procedure pprocN (_object : in out poV;...) is
8572 -- <discriminant renamings>
8573 -- <private object renamings>
8574 -- begin
8575 -- <sequence of statements>
8576 -- end pprocN;
8577
8578 -- procedure pprocP (_object : in out poV;...) is
8579 -- procedure _clean is
8580 -- Pn : Boolean;
8581 -- begin
8582 -- ptypeS (_object, Pn);
8583 -- Unlock (_object._object'Access);
8584 -- Abort_Undefer.all;
8585 -- end _clean;
8586
8587 -- begin
8588 -- Abort_Defer.all;
8589 -- Lock (_object._object'Access);
8590 -- pprocN (_object;...);
8591 -- at end
8592 -- _clean;
8593 -- end pproc;
8594
8595 -- function pfuncN (_object : poV;...) return Return_Type is
8596 -- <discriminant renamings>
8597 -- <private object renamings>
8598 -- begin
8599 -- <sequence of statements>
8600 -- end pfuncN;
8601
8602 -- function pfuncP (_object : poV) return Return_Type is
8603 -- procedure _clean is
8604 -- begin
8605 -- Unlock (_object._object'Access);
8606 -- Abort_Undefer.all;
8607 -- end _clean;
8608
8609 -- begin
8610 -- Abort_Defer.all;
8611 -- Lock (_object._object'Access);
8612 -- return pfuncN (_object);
8613
8614 -- at end
8615 -- _clean;
8616 -- end pfunc;
8617
8618 -- procedure entE
8619 -- (O : System.Address;
8620 -- P : System.Address;
8621 -- E : Protected_Entry_Index)
8622 -- is
8623 -- <discriminant renamings>
8624 -- <private object renamings>
8625 -- type poVP is access poV;
8626 -- _Object : ptVP := ptVP!(O);
8627
8628 -- begin
8629 -- begin
8630 -- <statement sequence>
8631 -- Complete_Entry_Body (_Object._Object);
8632 -- exception
8633 -- when all others =>
8634 -- Exceptional_Complete_Entry_Body (
8635 -- _Object._Object, Get_GNAT_Exception);
8636 -- end;
8637 -- end entE;
8638
8639 -- The type poV is the record created for the protected type to hold
8640 -- the state of the protected object.
8641
8642 procedure Expand_N_Protected_Body (N : Node_Id) is
8643 Loc : constant Source_Ptr := Sloc (N);
8644 Pid : constant Entity_Id := Corresponding_Spec (N);
8645
8646 Lock_Free_Active : constant Boolean := Uses_Lock_Free (Pid);
8647 -- This flag indicates whether the lock free implementation is active
8648
8649 Current_Node : Node_Id;
8650 Disp_Op_Body : Node_Id;
8651 New_Op_Body : Node_Id;
8652 Op_Body : Node_Id;
8653 Op_Decl : Node_Id;
8654 Op_Id : Entity_Id;
8655
8656 function Build_Dispatching_Subprogram_Body
8657 (N : Node_Id;
8658 Pid : Node_Id;
8659 Prot_Bod : Node_Id) return Node_Id;
8660 -- Build a dispatching version of the protected subprogram body. The
8661 -- newly generated subprogram contains a call to the original protected
8662 -- body. The following code is generated:
8663 --
8664 -- function <protected-function-name> (Param1 .. ParamN) return
8665 -- <return-type> is
8666 -- begin
8667 -- return <protected-function-name>P (Param1 .. ParamN);
8668 -- end <protected-function-name>;
8669 --
8670 -- or
8671 --
8672 -- procedure <protected-procedure-name> (Param1 .. ParamN) is
8673 -- begin
8674 -- <protected-procedure-name>P (Param1 .. ParamN);
8675 -- end <protected-procedure-name>
8676
8677 ---------------------------------------
8678 -- Build_Dispatching_Subprogram_Body --
8679 ---------------------------------------
8680
8681 function Build_Dispatching_Subprogram_Body
8682 (N : Node_Id;
8683 Pid : Node_Id;
8684 Prot_Bod : Node_Id) return Node_Id
8685 is
8686 Loc : constant Source_Ptr := Sloc (N);
8687 Actuals : List_Id;
8688 Formal : Node_Id;
8689 Spec : Node_Id;
8690 Stmts : List_Id;
8691
8692 begin
8693 -- Generate a specification without a letter suffix in order to
8694 -- override an interface function or procedure.
8695
8696 Spec := Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
8697
8698 -- The formal parameters become the actuals of the protected function
8699 -- or procedure call.
8700
8701 Actuals := New_List;
8702 Formal := First (Parameter_Specifications (Spec));
8703 while Present (Formal) loop
8704 Append_To (Actuals,
8705 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
8706 Next (Formal);
8707 end loop;
8708
8709 if Nkind (Spec) = N_Procedure_Specification then
8710 Stmts :=
8711 New_List (
8712 Make_Procedure_Call_Statement (Loc,
8713 Name =>
8714 New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
8715 Parameter_Associations => Actuals));
8716
8717 else
8718 pragma Assert (Nkind (Spec) = N_Function_Specification);
8719
8720 Stmts :=
8721 New_List (
8722 Make_Simple_Return_Statement (Loc,
8723 Expression =>
8724 Make_Function_Call (Loc,
8725 Name =>
8726 New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
8727 Parameter_Associations => Actuals)));
8728 end if;
8729
8730 return
8731 Make_Subprogram_Body (Loc,
8732 Declarations => Empty_List,
8733 Specification => Spec,
8734 Handled_Statement_Sequence =>
8735 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
8736 end Build_Dispatching_Subprogram_Body;
8737
8738 -- Start of processing for Expand_N_Protected_Body
8739
8740 begin
8741 if No_Run_Time_Mode then
8742 Error_Msg_CRT ("protected body", N);
8743 return;
8744 end if;
8745
8746 -- This is the proper body corresponding to a stub. The declarations
8747 -- must be inserted at the point of the stub, which in turn is in the
8748 -- declarative part of the parent unit.
8749
8750 if Nkind (Parent (N)) = N_Subunit then
8751 Current_Node := Corresponding_Stub (Parent (N));
8752 else
8753 Current_Node := N;
8754 end if;
8755
8756 Op_Body := First (Declarations (N));
8757
8758 -- The protected body is replaced with the bodies of its protected
8759 -- operations, and the declarations for internal objects that may
8760 -- have been created for entry family bounds.
8761
8762 Rewrite (N, Make_Null_Statement (Sloc (N)));
8763 Analyze (N);
8764
8765 while Present (Op_Body) loop
8766 case Nkind (Op_Body) is
8767 when N_Subprogram_Declaration =>
8768 null;
8769
8770 when N_Subprogram_Body =>
8771
8772 -- Do not create bodies for eliminated operations
8773
8774 if not Is_Eliminated (Defining_Entity (Op_Body))
8775 and then not Is_Eliminated (Corresponding_Spec (Op_Body))
8776 then
8777 if Lock_Free_Active then
8778 New_Op_Body :=
8779 Build_Lock_Free_Unprotected_Subprogram_Body
8780 (Op_Body, Pid);
8781 else
8782 New_Op_Body :=
8783 Build_Unprotected_Subprogram_Body (Op_Body, Pid);
8784 end if;
8785
8786 Insert_After (Current_Node, New_Op_Body);
8787 Current_Node := New_Op_Body;
8788 Analyze (New_Op_Body);
8789
8790 -- When the original protected body has nested subprograms,
8791 -- the new body also has them, so set the flag accordingly
8792 -- and reset the scopes of the top-level nested subprograms
8793 -- and other declaration entities so that they now refer to
8794 -- the new body's entity. (It would preferable to do this
8795 -- within Build_Protected_Sub_Specification, which is called
8796 -- from Build_Unprotected_Subprogram_Body, but the needed
8797 -- subprogram entity isn't available via Corresponding_Spec
8798 -- until after the above Analyze call.)
8799
8800 if Has_Nested_Subprogram (Corresponding_Spec (Op_Body)) then
8801 Set_Has_Nested_Subprogram
8802 (Corresponding_Spec (New_Op_Body));
8803
8804 Reset_Scopes_To
8805 (New_Op_Body, Corresponding_Spec (New_Op_Body));
8806 end if;
8807
8808 -- Build the corresponding protected operation. This is
8809 -- needed only if this is a public or private operation of
8810 -- the type.
8811
8812 -- Why do we need to test for Corresponding_Spec being
8813 -- present here when it's assumed to be set further above
8814 -- in the Is_Eliminated test???
8815
8816 if Present (Corresponding_Spec (Op_Body)) then
8817 Op_Decl :=
8818 Unit_Declaration_Node (Corresponding_Spec (Op_Body));
8819
8820 if Nkind (Parent (Op_Decl)) = N_Protected_Definition then
8821 if Lock_Free_Active then
8822 New_Op_Body :=
8823 Build_Lock_Free_Protected_Subprogram_Body
8824 (Op_Body, Pid, Specification (New_Op_Body));
8825 else
8826 New_Op_Body :=
8827 Build_Protected_Subprogram_Body (
8828 Op_Body, Pid, Specification (New_Op_Body));
8829 end if;
8830
8831 Insert_After (Current_Node, New_Op_Body);
8832 Analyze (New_Op_Body);
8833 Current_Node := New_Op_Body;
8834
8835 -- Generate an overriding primitive operation body for
8836 -- this subprogram if the protected type implements
8837 -- an interface.
8838
8839 if Ada_Version >= Ada_2005
8840 and then Present (Interfaces (
8841 Corresponding_Record_Type (Pid)))
8842 then
8843 Disp_Op_Body :=
8844 Build_Dispatching_Subprogram_Body (
8845 Op_Body, Pid, New_Op_Body);
8846
8847 Insert_After (Current_Node, Disp_Op_Body);
8848 Analyze (Disp_Op_Body);
8849
8850 Current_Node := Disp_Op_Body;
8851 end if;
8852 end if;
8853 end if;
8854 end if;
8855
8856 when N_Entry_Body =>
8857 Op_Id := Defining_Identifier (Op_Body);
8858 New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
8859
8860 Insert_After (Current_Node, New_Op_Body);
8861 Current_Node := New_Op_Body;
8862 Analyze (New_Op_Body);
8863
8864 when N_Implicit_Label_Declaration =>
8865 null;
8866
8867 when N_Call_Marker
8868 | N_Itype_Reference
8869 =>
8870 New_Op_Body := New_Copy (Op_Body);
8871 Insert_After (Current_Node, New_Op_Body);
8872 Current_Node := New_Op_Body;
8873
8874 when N_Freeze_Entity =>
8875 New_Op_Body := New_Copy (Op_Body);
8876
8877 if Present (Entity (Op_Body))
8878 and then Freeze_Node (Entity (Op_Body)) = Op_Body
8879 then
8880 Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
8881 end if;
8882
8883 Insert_After (Current_Node, New_Op_Body);
8884 Current_Node := New_Op_Body;
8885 Analyze (New_Op_Body);
8886
8887 when N_Pragma =>
8888 New_Op_Body := New_Copy (Op_Body);
8889 Insert_After (Current_Node, New_Op_Body);
8890 Current_Node := New_Op_Body;
8891 Analyze (New_Op_Body);
8892
8893 when N_Object_Declaration =>
8894 pragma Assert (not Comes_From_Source (Op_Body));
8895 New_Op_Body := New_Copy (Op_Body);
8896 Insert_After (Current_Node, New_Op_Body);
8897 Current_Node := New_Op_Body;
8898 Analyze (New_Op_Body);
8899
8900 when others =>
8901 raise Program_Error;
8902 end case;
8903
8904 Next (Op_Body);
8905 end loop;
8906
8907 -- Finally, create the body of the function that maps an entry index
8908 -- into the corresponding body index, except when there is no entry, or
8909 -- in a Ravenscar-like profile.
8910
8911 if Corresponding_Runtime_Package (Pid) =
8912 System_Tasking_Protected_Objects_Entries
8913 then
8914 New_Op_Body := Build_Find_Body_Index (Pid);
8915 Insert_After (Current_Node, New_Op_Body);
8916 Current_Node := New_Op_Body;
8917 Analyze (New_Op_Body);
8918 end if;
8919
8920 -- Ada 2005 (AI-345): Construct the primitive wrapper bodies after the
8921 -- protected body. At this point all wrapper specs have been created,
8922 -- frozen and included in the dispatch table for the protected type.
8923
8924 if Ada_Version >= Ada_2005 then
8925 Build_Wrapper_Bodies (Loc, Pid, Current_Node);
8926 end if;
8927 end Expand_N_Protected_Body;
8928
8929 -----------------------------------------
8930 -- Expand_N_Protected_Type_Declaration --
8931 -----------------------------------------
8932
8933 -- First we create a corresponding record type declaration used to
8934 -- represent values of this protected type.
8935 -- The general form of this type declaration is
8936
8937 -- type poV (discriminants) is record
8938 -- _Object : aliased <kind>Protection
8939 -- [(<entry count> [, <handler count>])];
8940 -- [entry_family : array (bounds) of Void;]
8941 -- <private data fields>
8942 -- end record;
8943
8944 -- The discriminants are present only if the corresponding protected type
8945 -- has discriminants, and they exactly mirror the protected type
8946 -- discriminants. The private data fields similarly mirror the private
8947 -- declarations of the protected type.
8948
8949 -- The Object field is always present. It contains RTS specific data used
8950 -- to control the protected object. It is declared as Aliased so that it
8951 -- can be passed as a pointer to the RTS. This allows the protected record
8952 -- to be referenced within RTS data structures. An appropriate Protection
8953 -- type and discriminant are generated.
8954
8955 -- The Service field is present for protected objects with entries. It
8956 -- contains sufficient information to allow the entry service procedure for
8957 -- this object to be called when the object is not known till runtime.
8958
8959 -- One entry_family component is present for each entry family in the
8960 -- task definition (see Expand_N_Task_Type_Declaration).
8961
8962 -- When a protected object is declared, an instance of the protected type
8963 -- value record is created. The elaboration of this declaration creates the
8964 -- correct bounds for the entry families, and also evaluates the priority
8965 -- expression if needed. The initialization routine for the protected type
8966 -- itself then calls Initialize_Protection with appropriate parameters to
8967 -- initialize the value of the Task_Id field. Install_Handlers may be also
8968 -- called if a pragma Attach_Handler applies.
8969
8970 -- Note: this record is passed to the subprograms created by the expansion
8971 -- of protected subprograms and entries. It is an in parameter to protected
8972 -- functions and an in out parameter to procedures and entry bodies. The
8973 -- Entity_Id for this created record type is placed in the
8974 -- Corresponding_Record_Type field of the associated protected type entity.
8975
8976 -- Next we create a procedure specifications for protected subprograms and
8977 -- entry bodies. For each protected subprograms two subprograms are
8978 -- created, an unprotected and a protected version. The unprotected version
8979 -- is called from within other operations of the same protected object.
8980
8981 -- We also build the call to register the procedure if a pragma
8982 -- Interrupt_Handler applies.
8983
8984 -- A single subprogram is created to service all entry bodies; it has an
8985 -- additional boolean out parameter indicating that the previous entry call
8986 -- made by the current task was serviced immediately, i.e. not by proxy.
8987 -- The O parameter contains a pointer to a record object of the type
8988 -- described above. An untyped interface is used here to allow this
8989 -- procedure to be called in places where the type of the object to be
8990 -- serviced is not known. This must be done, for example, when a call that
8991 -- may have been requeued is cancelled; the corresponding object must be
8992 -- serviced, but which object that is not known till runtime.
8993
8994 -- procedure ptypeS
8995 -- (O : System.Address; P : out Boolean);
8996 -- procedure pprocN (_object : in out poV);
8997 -- procedure pproc (_object : in out poV);
8998 -- function pfuncN (_object : poV);
8999 -- function pfunc (_object : poV);
9000 -- ...
9001
9002 -- Note that this must come after the record type declaration, since
9003 -- the specs refer to this type.
9004
9005 procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
9006 Discr_Map : constant Elist_Id := New_Elmt_List;
9007 Loc : constant Source_Ptr := Sloc (N);
9008 Prot_Typ : constant Entity_Id := Defining_Identifier (N);
9009
9010 Lock_Free_Active : constant Boolean := Uses_Lock_Free (Prot_Typ);
9011 -- This flag indicates whether the lock free implementation is active
9012
9013 Pdef : constant Node_Id := Protected_Definition (N);
9014 -- This contains two lists; one for visible and one for private decls
9015
9016 Current_Node : Node_Id := N;
9017 E_Count : Int;
9018 Entries_Aggr : Node_Id;
9019 Rec_Decl : Node_Id;
9020 Rec_Id : Entity_Id;
9021
9022 procedure Check_Inlining (Subp : Entity_Id);
9023 -- If the original operation has a pragma Inline, propagate the flag
9024 -- to the internal body, for possible inlining later on. The source
9025 -- operation is invisible to the back-end and is never actually called.
9026
9027 procedure Expand_Entry_Declaration (Decl : Node_Id);
9028 -- Create the entry barrier and the procedure body for entry declaration
9029 -- Decl. All generated subprograms are added to Entry_Bodies_Array.
9030
9031 function Static_Component_Size (Comp : Entity_Id) return Boolean;
9032 -- When compiling under the Ravenscar profile, private components must
9033 -- have a static size, or else a protected object will require heap
9034 -- allocation, violating the corresponding restriction. It is preferable
9035 -- to make this check here, because it provides a better error message
9036 -- than the back-end, which refers to the object as a whole.
9037
9038 procedure Register_Handler;
9039 -- For a protected operation that is an interrupt handler, add the
9040 -- freeze action that will register it as such.
9041
9042 procedure Replace_Access_Definition (Comp : Node_Id);
9043 -- If a private component of the type is an access to itself, this
9044 -- is not a reference to the current instance, but an access type out
9045 -- of which one might construct a list. If such a component exists, we
9046 -- create an incomplete type for the equivalent record type, and
9047 -- a named access type for it, that replaces the access definition
9048 -- of the original component. This is similar to what is done for
9049 -- records in Check_Anonymous_Access_Components, but simpler, because
9050 -- the corresponding record type has no previous declaration.
9051 -- This needs to be done only once, even if there are several such
9052 -- access components. The following entity stores the constructed
9053 -- access type.
9054
9055 Acc_T : Entity_Id := Empty;
9056
9057 --------------------
9058 -- Check_Inlining --
9059 --------------------
9060
9061 procedure Check_Inlining (Subp : Entity_Id) is
9062 begin
9063 if Is_Inlined (Subp) then
9064 Set_Is_Inlined (Protected_Body_Subprogram (Subp));
9065 Set_Is_Inlined (Subp, False);
9066 end if;
9067
9068 if Has_Pragma_No_Inline (Subp) then
9069 Set_Has_Pragma_No_Inline (Protected_Body_Subprogram (Subp));
9070 end if;
9071 end Check_Inlining;
9072
9073 ---------------------------
9074 -- Static_Component_Size --
9075 ---------------------------
9076
9077 function Static_Component_Size (Comp : Entity_Id) return Boolean is
9078 Typ : constant Entity_Id := Etype (Comp);
9079 C : Entity_Id;
9080
9081 begin
9082 if Is_Scalar_Type (Typ) then
9083 return True;
9084
9085 elsif Is_Array_Type (Typ) then
9086 return Compile_Time_Known_Bounds (Typ);
9087
9088 elsif Is_Record_Type (Typ) then
9089 C := First_Component (Typ);
9090 while Present (C) loop
9091 if not Static_Component_Size (C) then
9092 return False;
9093 end if;
9094
9095 Next_Component (C);
9096 end loop;
9097
9098 return True;
9099
9100 -- Any other type will be checked by the back-end
9101
9102 else
9103 return True;
9104 end if;
9105 end Static_Component_Size;
9106
9107 ------------------------------
9108 -- Expand_Entry_Declaration --
9109 ------------------------------
9110
9111 procedure Expand_Entry_Declaration (Decl : Node_Id) is
9112 Ent_Id : constant Entity_Id := Defining_Entity (Decl);
9113 Bar_Id : Entity_Id;
9114 Bod_Id : Entity_Id;
9115 Subp : Node_Id;
9116
9117 begin
9118 E_Count := E_Count + 1;
9119
9120 -- Create the protected body subprogram
9121
9122 Bod_Id :=
9123 Make_Defining_Identifier (Loc,
9124 Chars => Build_Selected_Name (Prot_Typ, Ent_Id, 'E'));
9125 Set_Protected_Body_Subprogram (Ent_Id, Bod_Id);
9126
9127 Subp :=
9128 Make_Subprogram_Declaration (Loc,
9129 Specification =>
9130 Build_Protected_Entry_Specification (Loc, Bod_Id, Ent_Id));
9131
9132 Insert_After (Current_Node, Subp);
9133 Current_Node := Subp;
9134
9135 Analyze (Subp);
9136
9137 -- Build a wrapper procedure to handle contract cases, preconditions,
9138 -- and postconditions.
9139
9140 Build_Contract_Wrapper (Ent_Id, N);
9141
9142 -- Create the barrier function
9143
9144 Bar_Id :=
9145 Make_Defining_Identifier (Loc,
9146 Chars => Build_Selected_Name (Prot_Typ, Ent_Id, 'B'));
9147 Set_Barrier_Function (Ent_Id, Bar_Id);
9148
9149 Subp :=
9150 Make_Subprogram_Declaration (Loc,
9151 Specification =>
9152 Build_Barrier_Function_Specification (Loc, Bar_Id));
9153 Set_Is_Entry_Barrier_Function (Subp);
9154
9155 Insert_After (Current_Node, Subp);
9156 Current_Node := Subp;
9157
9158 Analyze (Subp);
9159
9160 Set_Protected_Body_Subprogram (Bar_Id, Bar_Id);
9161 Set_Scope (Bar_Id, Scope (Ent_Id));
9162
9163 -- Collect pointers to the protected subprogram and the barrier
9164 -- of the current entry, for insertion into Entry_Bodies_Array.
9165
9166 Append_To (Expressions (Entries_Aggr),
9167 Make_Aggregate (Loc,
9168 Expressions => New_List (
9169 Make_Attribute_Reference (Loc,
9170 Prefix => New_Occurrence_Of (Bar_Id, Loc),
9171 Attribute_Name => Name_Unrestricted_Access),
9172 Make_Attribute_Reference (Loc,
9173 Prefix => New_Occurrence_Of (Bod_Id, Loc),
9174 Attribute_Name => Name_Unrestricted_Access))));
9175 end Expand_Entry_Declaration;
9176
9177 ----------------------
9178 -- Register_Handler --
9179 ----------------------
9180
9181 procedure Register_Handler is
9182
9183 -- All semantic checks already done in Sem_Prag
9184
9185 Prot_Proc : constant Entity_Id :=
9186 Defining_Unit_Name (Specification (Current_Node));
9187
9188 Proc_Address : constant Node_Id :=
9189 Make_Attribute_Reference (Loc,
9190 Prefix =>
9191 New_Occurrence_Of (Prot_Proc, Loc),
9192 Attribute_Name => Name_Address);
9193
9194 RTS_Call : constant Entity_Id :=
9195 Make_Procedure_Call_Statement (Loc,
9196 Name =>
9197 New_Occurrence_Of
9198 (RTE (RE_Register_Interrupt_Handler), Loc),
9199 Parameter_Associations => New_List (Proc_Address));
9200 begin
9201 Append_Freeze_Action (Prot_Proc, RTS_Call);
9202 end Register_Handler;
9203
9204 -------------------------------
9205 -- Replace_Access_Definition --
9206 -------------------------------
9207
9208 procedure Replace_Access_Definition (Comp : Node_Id) is
9209 Loc : constant Source_Ptr := Sloc (Comp);
9210 Inc_T : Node_Id;
9211 Inc_D : Node_Id;
9212 Acc_Def : Node_Id;
9213 Acc_D : Node_Id;
9214
9215 begin
9216 if No (Acc_T) then
9217 Inc_T := Make_Defining_Identifier (Loc, Chars (Rec_Id));
9218 Inc_D := Make_Incomplete_Type_Declaration (Loc, Inc_T);
9219 Acc_T := Make_Temporary (Loc, 'S');
9220 Acc_Def :=
9221 Make_Access_To_Object_Definition (Loc,
9222 Subtype_Indication => New_Occurrence_Of (Inc_T, Loc));
9223 Acc_D :=
9224 Make_Full_Type_Declaration (Loc,
9225 Defining_Identifier => Acc_T,
9226 Type_Definition => Acc_Def);
9227
9228 Insert_Before (Rec_Decl, Inc_D);
9229 Analyze (Inc_D);
9230
9231 Insert_Before (Rec_Decl, Acc_D);
9232 Analyze (Acc_D);
9233 end if;
9234
9235 Set_Access_Definition (Comp, Empty);
9236 Set_Subtype_Indication (Comp, New_Occurrence_Of (Acc_T, Loc));
9237 end Replace_Access_Definition;
9238
9239 -- Local variables
9240
9241 Body_Arr : Node_Id;
9242 Body_Id : Entity_Id;
9243 Cdecls : List_Id;
9244 Comp : Node_Id;
9245 Expr : Node_Id;
9246 New_Priv : Node_Id;
9247 Obj_Def : Node_Id;
9248 Object_Comp : Node_Id;
9249 Priv : Node_Id;
9250 Sub : Node_Id;
9251
9252 -- Start of processing for Expand_N_Protected_Type_Declaration
9253
9254 begin
9255 if Present (Corresponding_Record_Type (Prot_Typ)) then
9256 return;
9257 else
9258 Rec_Decl := Build_Corresponding_Record (N, Prot_Typ, Loc);
9259 Rec_Id := Defining_Identifier (Rec_Decl);
9260 end if;
9261
9262 Cdecls := Component_Items (Component_List (Type_Definition (Rec_Decl)));
9263
9264 Qualify_Entity_Names (N);
9265
9266 -- If the type has discriminants, their occurrences in the declaration
9267 -- have been replaced by the corresponding discriminals. For components
9268 -- that are constrained by discriminants, their homologues in the
9269 -- corresponding record type must refer to the discriminants of that
9270 -- record, so we must apply a new renaming to subtypes_indications:
9271
9272 -- protected discriminant => discriminal => record discriminant
9273
9274 -- This replacement is not applied to default expressions, for which
9275 -- the discriminal is correct.
9276
9277 if Has_Discriminants (Prot_Typ) then
9278 declare
9279 Disc : Entity_Id;
9280 Decl : Node_Id;
9281
9282 begin
9283 Disc := First_Discriminant (Prot_Typ);
9284 Decl := First (Discriminant_Specifications (Rec_Decl));
9285 while Present (Disc) loop
9286 Append_Elmt (Discriminal (Disc), Discr_Map);
9287 Append_Elmt (Defining_Identifier (Decl), Discr_Map);
9288 Next_Discriminant (Disc);
9289 Next (Decl);
9290 end loop;
9291 end;
9292 end if;
9293
9294 -- Fill in the component declarations
9295
9296 -- Add components for entry families. For each entry family, create an
9297 -- anonymous type declaration with the same size, and analyze the type.
9298
9299 Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ);
9300
9301 pragma Assert (Present (Pdef));
9302
9303 Insert_After (Current_Node, Rec_Decl);
9304 Current_Node := Rec_Decl;
9305
9306 -- Add private field components
9307
9308 if Present (Private_Declarations (Pdef)) then
9309 Priv := First (Private_Declarations (Pdef));
9310 while Present (Priv) loop
9311 if Nkind (Priv) = N_Component_Declaration then
9312 if not Static_Component_Size (Defining_Identifier (Priv)) then
9313
9314 -- When compiling for a restricted profile, the private
9315 -- components must have a static size. If not, this is an
9316 -- error for a single protected declaration, and rates a
9317 -- warning on a protected type declaration.
9318
9319 if not Comes_From_Source (Prot_Typ) then
9320
9321 -- It's ok to be checking this restriction at expansion
9322 -- time, because this is only for the restricted profile,
9323 -- which is not subject to strict RM conformance, so it
9324 -- is OK to miss this check in -gnatc mode.
9325
9326 Check_Restriction (No_Implicit_Heap_Allocations, Priv);
9327 Check_Restriction
9328 (No_Implicit_Protected_Object_Allocations, Priv);
9329
9330 elsif Restriction_Active (No_Implicit_Heap_Allocations) then
9331 if not Discriminated_Size (Defining_Identifier (Priv))
9332 then
9333 -- Any object of the type will be non-static
9334
9335 Error_Msg_N ("component has non-static size??", Priv);
9336 Error_Msg_NE
9337 ("\creation of protected object of type& will "
9338 & "violate restriction "
9339 & "No_Implicit_Heap_Allocations??", Priv, Prot_Typ);
9340 else
9341 -- Object will be non-static if discriminants are
9342
9343 Error_Msg_NE
9344 ("creation of protected object of type& with "
9345 & "non-static discriminants will violate "
9346 & "restriction No_Implicit_Heap_Allocations??",
9347 Priv, Prot_Typ);
9348 end if;
9349
9350 -- Likewise for No_Implicit_Protected_Object_Allocations
9351
9352 elsif Restriction_Active
9353 (No_Implicit_Protected_Object_Allocations)
9354 then
9355 if not Discriminated_Size (Defining_Identifier (Priv))
9356 then
9357 -- Any object of the type will be non-static
9358
9359 Error_Msg_N ("component has non-static size??", Priv);
9360 Error_Msg_NE
9361 ("\creation of protected object of type& will "
9362 & "violate restriction "
9363 & "No_Implicit_Protected_Object_Allocations??",
9364 Priv, Prot_Typ);
9365 else
9366 -- Object will be non-static if discriminants are
9367
9368 Error_Msg_NE
9369 ("creation of protected object of type& with "
9370 & "non-static discriminants will violate "
9371 & "restriction "
9372 & "No_Implicit_Protected_Object_Allocations??",
9373 Priv, Prot_Typ);
9374 end if;
9375 end if;
9376 end if;
9377
9378 -- The component definition consists of a subtype indication,
9379 -- or (in Ada 2005) an access definition. Make a copy of the
9380 -- proper definition.
9381
9382 declare
9383 Old_Comp : constant Node_Id := Component_Definition (Priv);
9384 Oent : constant Entity_Id := Defining_Identifier (Priv);
9385 Nent : constant Entity_Id :=
9386 Make_Defining_Identifier (Sloc (Oent),
9387 Chars => Chars (Oent));
9388 New_Comp : Node_Id;
9389
9390 begin
9391 if Present (Subtype_Indication (Old_Comp)) then
9392 New_Comp :=
9393 Make_Component_Definition (Sloc (Oent),
9394 Aliased_Present => False,
9395 Subtype_Indication =>
9396 New_Copy_Tree
9397 (Subtype_Indication (Old_Comp), Discr_Map));
9398 else
9399 New_Comp :=
9400 Make_Component_Definition (Sloc (Oent),
9401 Aliased_Present => False,
9402 Access_Definition =>
9403 New_Copy_Tree
9404 (Access_Definition (Old_Comp), Discr_Map));
9405
9406 -- A self-reference in the private part becomes a
9407 -- self-reference to the corresponding record.
9408
9409 if Entity (Subtype_Mark (Access_Definition (New_Comp)))
9410 = Prot_Typ
9411 then
9412 Replace_Access_Definition (New_Comp);
9413 end if;
9414 end if;
9415
9416 New_Priv :=
9417 Make_Component_Declaration (Loc,
9418 Defining_Identifier => Nent,
9419 Component_Definition => New_Comp,
9420 Expression => Expression (Priv));
9421
9422 Set_Has_Per_Object_Constraint (Nent,
9423 Has_Per_Object_Constraint (Oent));
9424
9425 Append_To (Cdecls, New_Priv);
9426 end;
9427
9428 elsif Nkind (Priv) = N_Subprogram_Declaration then
9429
9430 -- Make the unprotected version of the subprogram available
9431 -- for expansion of intra object calls. There is need for
9432 -- a protected version only if the subprogram is an interrupt
9433 -- handler, otherwise this operation can only be called from
9434 -- within the body.
9435
9436 Sub :=
9437 Make_Subprogram_Declaration (Loc,
9438 Specification =>
9439 Build_Protected_Sub_Specification
9440 (Priv, Prot_Typ, Unprotected_Mode));
9441
9442 Insert_After (Current_Node, Sub);
9443 Analyze (Sub);
9444
9445 Set_Protected_Body_Subprogram
9446 (Defining_Unit_Name (Specification (Priv)),
9447 Defining_Unit_Name (Specification (Sub)));
9448 Check_Inlining (Defining_Unit_Name (Specification (Priv)));
9449 Current_Node := Sub;
9450
9451 Sub :=
9452 Make_Subprogram_Declaration (Loc,
9453 Specification =>
9454 Build_Protected_Sub_Specification
9455 (Priv, Prot_Typ, Protected_Mode));
9456
9457 Insert_After (Current_Node, Sub);
9458 Analyze (Sub);
9459 Current_Node := Sub;
9460
9461 if Is_Interrupt_Handler
9462 (Defining_Unit_Name (Specification (Priv)))
9463 then
9464 if not Restricted_Profile then
9465 Register_Handler;
9466 end if;
9467 end if;
9468 end if;
9469
9470 Next (Priv);
9471 end loop;
9472 end if;
9473
9474 -- Except for the lock-free implementation, append the _Object field
9475 -- with the right type to the component list. We need to compute the
9476 -- number of entries, and in some cases the number of Attach_Handler
9477 -- pragmas.
9478
9479 if not Lock_Free_Active then
9480 declare
9481 Entry_Count_Expr : constant Node_Id :=
9482 Build_Entry_Count_Expression
9483 (Prot_Typ, Cdecls, Loc);
9484 Num_Attach_Handler : Nat := 0;
9485 Protection_Subtype : Node_Id;
9486 Ritem : Node_Id;
9487
9488 begin
9489 if Has_Attach_Handler (Prot_Typ) then
9490 Ritem := First_Rep_Item (Prot_Typ);
9491 while Present (Ritem) loop
9492 if Nkind (Ritem) = N_Pragma
9493 and then Pragma_Name (Ritem) = Name_Attach_Handler
9494 then
9495 Num_Attach_Handler := Num_Attach_Handler + 1;
9496 end if;
9497
9498 Next_Rep_Item (Ritem);
9499 end loop;
9500 end if;
9501
9502 -- Determine the proper protection type. There are two special
9503 -- cases: 1) when the protected type has dynamic interrupt
9504 -- handlers, and 2) when it has static handlers and we use a
9505 -- restricted profile.
9506
9507 if Has_Attach_Handler (Prot_Typ)
9508 and then not Restricted_Profile
9509 then
9510 Protection_Subtype :=
9511 Make_Subtype_Indication (Loc,
9512 Subtype_Mark =>
9513 New_Occurrence_Of
9514 (RTE (RE_Static_Interrupt_Protection), Loc),
9515 Constraint =>
9516 Make_Index_Or_Discriminant_Constraint (Loc,
9517 Constraints => New_List (
9518 Entry_Count_Expr,
9519 Make_Integer_Literal (Loc, Num_Attach_Handler))));
9520
9521 elsif Has_Interrupt_Handler (Prot_Typ)
9522 and then not Restriction_Active (No_Dynamic_Attachment)
9523 then
9524 Protection_Subtype :=
9525 Make_Subtype_Indication (Loc,
9526 Subtype_Mark =>
9527 New_Occurrence_Of
9528 (RTE (RE_Dynamic_Interrupt_Protection), Loc),
9529 Constraint =>
9530 Make_Index_Or_Discriminant_Constraint (Loc,
9531 Constraints => New_List (Entry_Count_Expr)));
9532
9533 else
9534 case Corresponding_Runtime_Package (Prot_Typ) is
9535 when System_Tasking_Protected_Objects_Entries =>
9536 Protection_Subtype :=
9537 Make_Subtype_Indication (Loc,
9538 Subtype_Mark =>
9539 New_Occurrence_Of
9540 (RTE (RE_Protection_Entries), Loc),
9541 Constraint =>
9542 Make_Index_Or_Discriminant_Constraint (Loc,
9543 Constraints => New_List (Entry_Count_Expr)));
9544
9545 when System_Tasking_Protected_Objects_Single_Entry =>
9546 Protection_Subtype :=
9547 New_Occurrence_Of (RTE (RE_Protection_Entry), Loc);
9548
9549 when System_Tasking_Protected_Objects =>
9550 Protection_Subtype :=
9551 New_Occurrence_Of (RTE (RE_Protection), Loc);
9552
9553 when others =>
9554 raise Program_Error;
9555 end case;
9556 end if;
9557
9558 Object_Comp :=
9559 Make_Component_Declaration (Loc,
9560 Defining_Identifier =>
9561 Make_Defining_Identifier (Loc, Name_uObject),
9562 Component_Definition =>
9563 Make_Component_Definition (Loc,
9564 Aliased_Present => True,
9565 Subtype_Indication => Protection_Subtype));
9566 end;
9567
9568 -- Put the _Object component after the private component so that it
9569 -- be finalized early as required by 9.4 (20)
9570
9571 Append_To (Cdecls, Object_Comp);
9572 end if;
9573
9574 -- Analyze the record declaration immediately after construction,
9575 -- because the initialization procedure is needed for single object
9576 -- declarations before the next entity is analyzed (the freeze call
9577 -- that generates this initialization procedure is found below).
9578
9579 Analyze (Rec_Decl, Suppress => All_Checks);
9580
9581 -- Ada 2005 (AI-345): Construct the primitive entry wrappers before
9582 -- the corresponding record is frozen. If any wrappers are generated,
9583 -- Current_Node is updated accordingly.
9584
9585 if Ada_Version >= Ada_2005 then
9586 Build_Wrapper_Specs (Loc, Prot_Typ, Current_Node);
9587 end if;
9588
9589 -- Collect pointers to entry bodies and their barriers, to be placed
9590 -- in the Entry_Bodies_Array for the type. For each entry/family we
9591 -- add an expression to the aggregate which is the initial value of
9592 -- this array. The array is declared after all protected subprograms.
9593
9594 if Has_Entries (Prot_Typ) then
9595 Entries_Aggr := Make_Aggregate (Loc, Expressions => New_List);
9596 else
9597 Entries_Aggr := Empty;
9598 end if;
9599
9600 -- Build two new procedure specifications for each protected subprogram;
9601 -- one to call from outside the object and one to call from inside.
9602 -- Build a barrier function and an entry body action procedure
9603 -- specification for each protected entry. Initialize the entry body
9604 -- array. If subprogram is flagged as eliminated, do not generate any
9605 -- internal operations.
9606
9607 E_Count := 0;
9608 Comp := First (Visible_Declarations (Pdef));
9609 while Present (Comp) loop
9610 if Nkind (Comp) = N_Subprogram_Declaration then
9611 Sub :=
9612 Make_Subprogram_Declaration (Loc,
9613 Specification =>
9614 Build_Protected_Sub_Specification
9615 (Comp, Prot_Typ, Unprotected_Mode));
9616
9617 Insert_After (Current_Node, Sub);
9618 Analyze (Sub);
9619
9620 Set_Protected_Body_Subprogram
9621 (Defining_Unit_Name (Specification (Comp)),
9622 Defining_Unit_Name (Specification (Sub)));
9623 Check_Inlining (Defining_Unit_Name (Specification (Comp)));
9624
9625 -- Make the protected version of the subprogram available for
9626 -- expansion of external calls.
9627
9628 Current_Node := Sub;
9629
9630 Sub :=
9631 Make_Subprogram_Declaration (Loc,
9632 Specification =>
9633 Build_Protected_Sub_Specification
9634 (Comp, Prot_Typ, Protected_Mode));
9635
9636 Insert_After (Current_Node, Sub);
9637 Analyze (Sub);
9638
9639 Current_Node := Sub;
9640
9641 -- Generate an overriding primitive operation specification for
9642 -- this subprogram if the protected type implements an interface
9643 -- and Build_Wrapper_Spec did not generate its wrapper.
9644
9645 if Ada_Version >= Ada_2005
9646 and then
9647 Present (Interfaces (Corresponding_Record_Type (Prot_Typ)))
9648 then
9649 declare
9650 Found : Boolean := False;
9651 Prim_Elmt : Elmt_Id;
9652 Prim_Op : Node_Id;
9653
9654 begin
9655 Prim_Elmt :=
9656 First_Elmt
9657 (Primitive_Operations
9658 (Corresponding_Record_Type (Prot_Typ)));
9659
9660 while Present (Prim_Elmt) loop
9661 Prim_Op := Node (Prim_Elmt);
9662
9663 if Is_Primitive_Wrapper (Prim_Op)
9664 and then Wrapped_Entity (Prim_Op) =
9665 Defining_Entity (Specification (Comp))
9666 then
9667 Found := True;
9668 exit;
9669 end if;
9670
9671 Next_Elmt (Prim_Elmt);
9672 end loop;
9673
9674 if not Found then
9675 Sub :=
9676 Make_Subprogram_Declaration (Loc,
9677 Specification =>
9678 Build_Protected_Sub_Specification
9679 (Comp, Prot_Typ, Dispatching_Mode));
9680
9681 Insert_After (Current_Node, Sub);
9682 Analyze (Sub);
9683
9684 Current_Node := Sub;
9685 end if;
9686 end;
9687 end if;
9688
9689 -- If a pragma Interrupt_Handler applies, build and add a call to
9690 -- Register_Interrupt_Handler to the freezing actions of the
9691 -- protected version (Current_Node) of the subprogram:
9692
9693 -- system.interrupts.register_interrupt_handler
9694 -- (prot_procP'address);
9695
9696 if not Restricted_Profile
9697 and then Is_Interrupt_Handler
9698 (Defining_Unit_Name (Specification (Comp)))
9699 then
9700 Register_Handler;
9701 end if;
9702
9703 elsif Nkind (Comp) = N_Entry_Declaration then
9704 Expand_Entry_Declaration (Comp);
9705 end if;
9706
9707 Next (Comp);
9708 end loop;
9709
9710 -- If there are some private entry declarations, expand it as if they
9711 -- were visible entries.
9712
9713 if Present (Private_Declarations (Pdef)) then
9714 Comp := First (Private_Declarations (Pdef));
9715 while Present (Comp) loop
9716 if Nkind (Comp) = N_Entry_Declaration then
9717 Expand_Entry_Declaration (Comp);
9718 end if;
9719
9720 Next (Comp);
9721 end loop;
9722 end if;
9723
9724 -- Create the declaration of an array object which contains the values
9725 -- of aspect/pragma Max_Queue_Length for all entries of the protected
9726 -- type. This object is later passed to the appropriate protected object
9727 -- initialization routine.
9728
9729 if Has_Entries (Prot_Typ)
9730 and then Corresponding_Runtime_Package (Prot_Typ) =
9731 System_Tasking_Protected_Objects_Entries
9732 then
9733 declare
9734 Count : Int;
9735 Item : Entity_Id;
9736 Max_Vals : Node_Id;
9737 Maxes : List_Id;
9738 Maxes_Id : Entity_Id;
9739 Need_Array : Boolean := False;
9740
9741 begin
9742 -- First check if there is any Max_Queue_Length pragma
9743
9744 Item := First_Entity (Prot_Typ);
9745 while Present (Item) loop
9746 if Is_Entry (Item) and then Has_Max_Queue_Length (Item) then
9747 Need_Array := True;
9748 exit;
9749 end if;
9750
9751 Next_Entity (Item);
9752 end loop;
9753
9754 -- Gather the Max_Queue_Length values of all entries in a list. A
9755 -- value of zero indicates that the entry has no limitation on its
9756 -- queue length.
9757
9758 if Need_Array then
9759 Count := 0;
9760 Item := First_Entity (Prot_Typ);
9761 Maxes := New_List;
9762 while Present (Item) loop
9763 if Is_Entry (Item) then
9764 Count := Count + 1;
9765 Append_To (Maxes,
9766 Make_Integer_Literal
9767 (Loc, Get_Max_Queue_Length (Item)));
9768 end if;
9769
9770 Next_Entity (Item);
9771 end loop;
9772
9773 -- Create the declaration of the array object. Generate:
9774
9775 -- Maxes_Id : aliased constant
9776 -- Protected_Entry_Queue_Max_Array
9777 -- (1 .. Count) := (..., ...);
9778
9779 Maxes_Id :=
9780 Make_Defining_Identifier (Loc,
9781 Chars => New_External_Name (Chars (Prot_Typ), 'B'));
9782
9783 Max_Vals :=
9784 Make_Object_Declaration (Loc,
9785 Defining_Identifier => Maxes_Id,
9786 Aliased_Present => True,
9787 Constant_Present => True,
9788 Object_Definition =>
9789 Make_Subtype_Indication (Loc,
9790 Subtype_Mark =>
9791 New_Occurrence_Of
9792 (RTE (RE_Protected_Entry_Queue_Max_Array), Loc),
9793 Constraint =>
9794 Make_Index_Or_Discriminant_Constraint (Loc,
9795 Constraints => New_List (
9796 Make_Range (Loc,
9797 Make_Integer_Literal (Loc, 1),
9798 Make_Integer_Literal (Loc, Count))))),
9799 Expression => Make_Aggregate (Loc, Maxes));
9800
9801 -- A pointer to this array will be placed in the corresponding
9802 -- record by its initialization procedure so this needs to be
9803 -- analyzed here.
9804
9805 Insert_After (Current_Node, Max_Vals);
9806 Current_Node := Max_Vals;
9807 Analyze (Max_Vals);
9808
9809 Set_Entry_Max_Queue_Lengths_Array (Prot_Typ, Maxes_Id);
9810 end if;
9811 end;
9812 end if;
9813
9814 -- Emit declaration for Entry_Bodies_Array, now that the addresses of
9815 -- all protected subprograms have been collected.
9816
9817 if Has_Entries (Prot_Typ) then
9818 Body_Id :=
9819 Make_Defining_Identifier (Sloc (Prot_Typ),
9820 Chars => New_External_Name (Chars (Prot_Typ), 'A'));
9821
9822 case Corresponding_Runtime_Package (Prot_Typ) is
9823 when System_Tasking_Protected_Objects_Entries =>
9824 Expr := Entries_Aggr;
9825 Obj_Def :=
9826 Make_Subtype_Indication (Loc,
9827 Subtype_Mark =>
9828 New_Occurrence_Of
9829 (RTE (RE_Protected_Entry_Body_Array), Loc),
9830 Constraint =>
9831 Make_Index_Or_Discriminant_Constraint (Loc,
9832 Constraints => New_List (
9833 Make_Range (Loc,
9834 Make_Integer_Literal (Loc, 1),
9835 Make_Integer_Literal (Loc, E_Count)))));
9836
9837 when System_Tasking_Protected_Objects_Single_Entry =>
9838 Expr := Remove_Head (Expressions (Entries_Aggr));
9839 Obj_Def := New_Occurrence_Of (RTE (RE_Entry_Body), Loc);
9840
9841 when others =>
9842 raise Program_Error;
9843 end case;
9844
9845 Body_Arr :=
9846 Make_Object_Declaration (Loc,
9847 Defining_Identifier => Body_Id,
9848 Aliased_Present => True,
9849 Constant_Present => True,
9850 Object_Definition => Obj_Def,
9851 Expression => Expr);
9852
9853 -- A pointer to this array will be placed in the corresponding record
9854 -- by its initialization procedure so this needs to be analyzed here.
9855
9856 Insert_After (Current_Node, Body_Arr);
9857 Current_Node := Body_Arr;
9858 Analyze (Body_Arr);
9859
9860 Set_Entry_Bodies_Array (Prot_Typ, Body_Id);
9861
9862 -- Finally, build the function that maps an entry index into the
9863 -- corresponding body. A pointer to this function is placed in each
9864 -- object of the type. Except for a ravenscar-like profile (no abort,
9865 -- no entry queue, 1 entry)
9866
9867 if Corresponding_Runtime_Package (Prot_Typ) =
9868 System_Tasking_Protected_Objects_Entries
9869 then
9870 Sub :=
9871 Make_Subprogram_Declaration (Loc,
9872 Specification => Build_Find_Body_Index_Spec (Prot_Typ));
9873
9874 Insert_After (Current_Node, Sub);
9875 Analyze (Sub);
9876 end if;
9877 end if;
9878 end Expand_N_Protected_Type_Declaration;
9879
9880 --------------------------------
9881 -- Expand_N_Requeue_Statement --
9882 --------------------------------
9883
9884 -- A nondispatching requeue statement is expanded into one of four GNARLI
9885 -- operations, depending on the source and destination (task or protected
9886 -- object). A dispatching requeue statement is expanded into a call to the
9887 -- predefined primitive _Disp_Requeue. In addition, code is generated to
9888 -- jump around the remainder of processing for the original entry and, if
9889 -- the destination is (different) protected object, to attempt to service
9890 -- it. The following illustrates the various cases:
9891
9892 -- procedure entE
9893 -- (O : System.Address;
9894 -- P : System.Address;
9895 -- E : Protected_Entry_Index)
9896 -- is
9897 -- <discriminant renamings>
9898 -- <private object renamings>
9899 -- type poVP is access poV;
9900 -- _object : ptVP := ptVP!(O);
9901
9902 -- begin
9903 -- begin
9904 -- <start of statement sequence for entry>
9905
9906 -- -- Requeue from one protected entry body to another protected
9907 -- -- entry.
9908
9909 -- Requeue_Protected_Entry (
9910 -- _object._object'Access,
9911 -- new._object'Access,
9912 -- E,
9913 -- Abort_Present);
9914 -- return;
9915
9916 -- <some more of the statement sequence for entry>
9917
9918 -- -- Requeue from an entry body to a task entry
9919
9920 -- Requeue_Protected_To_Task_Entry (
9921 -- New._task_id,
9922 -- E,
9923 -- Abort_Present);
9924 -- return;
9925
9926 -- <rest of statement sequence for entry>
9927 -- Complete_Entry_Body (_object._object);
9928
9929 -- exception
9930 -- when all others =>
9931 -- Exceptional_Complete_Entry_Body (
9932 -- _object._object, Get_GNAT_Exception);
9933 -- end;
9934 -- end entE;
9935
9936 -- Requeue of a task entry call to a task entry
9937
9938 -- Accept_Call (E, Ann);
9939 -- <start of statement sequence for accept statement>
9940 -- Requeue_Task_Entry (New._task_id, E, Abort_Present);
9941 -- goto Lnn;
9942 -- <rest of statement sequence for accept statement>
9943 -- <<Lnn>>
9944 -- Complete_Rendezvous;
9945
9946 -- exception
9947 -- when all others =>
9948 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9949
9950 -- Requeue of a task entry call to a protected entry
9951
9952 -- Accept_Call (E, Ann);
9953 -- <start of statement sequence for accept statement>
9954 -- Requeue_Task_To_Protected_Entry (
9955 -- new._object'Access,
9956 -- E,
9957 -- Abort_Present);
9958 -- newS (new, Pnn);
9959 -- goto Lnn;
9960 -- <rest of statement sequence for accept statement>
9961 -- <<Lnn>>
9962 -- Complete_Rendezvous;
9963
9964 -- exception
9965 -- when all others =>
9966 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9967
9968 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9969 -- marked by pragma Implemented (XXX, By_Entry).
9970
9971 -- The requeue is inside a protected entry:
9972
9973 -- procedure entE
9974 -- (O : System.Address;
9975 -- P : System.Address;
9976 -- E : Protected_Entry_Index)
9977 -- is
9978 -- <discriminant renamings>
9979 -- <private object renamings>
9980 -- type poVP is access poV;
9981 -- _object : ptVP := ptVP!(O);
9982
9983 -- begin
9984 -- begin
9985 -- <start of statement sequence for entry>
9986
9987 -- _Disp_Requeue
9988 -- (<interface class-wide object>,
9989 -- True,
9990 -- _object'Address,
9991 -- Ada.Tags.Get_Offset_Index
9992 -- (Tag (_object),
9993 -- <interface dispatch table index of target entry>),
9994 -- Abort_Present);
9995 -- return;
9996
9997 -- <rest of statement sequence for entry>
9998 -- Complete_Entry_Body (_object._object);
9999
10000 -- exception
10001 -- when all others =>
10002 -- Exceptional_Complete_Entry_Body (
10003 -- _object._object, Get_GNAT_Exception);
10004 -- end;
10005 -- end entE;
10006
10007 -- The requeue is inside a task entry:
10008
10009 -- Accept_Call (E, Ann);
10010 -- <start of statement sequence for accept statement>
10011 -- _Disp_Requeue
10012 -- (<interface class-wide object>,
10013 -- False,
10014 -- null,
10015 -- Ada.Tags.Get_Offset_Index
10016 -- (Tag (_object),
10017 -- <interface dispatch table index of target entrt>),
10018 -- Abort_Present);
10019 -- newS (new, Pnn);
10020 -- goto Lnn;
10021 -- <rest of statement sequence for accept statement>
10022 -- <<Lnn>>
10023 -- Complete_Rendezvous;
10024
10025 -- exception
10026 -- when all others =>
10027 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
10028
10029 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
10030 -- marked by pragma Implemented (XXX, By_Protected_Procedure). The requeue
10031 -- statement is replaced by a dispatching call with actual parameters taken
10032 -- from the inner-most accept statement or entry body.
10033
10034 -- Target.Primitive (Param1, ..., ParamN);
10035
10036 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
10037 -- marked by pragma Implemented (XXX, By_Any | Optional) or not marked
10038 -- at all.
10039
10040 -- declare
10041 -- S : constant Offset_Index :=
10042 -- Get_Offset_Index (Tag (Concval), DT_Position (Ename));
10043 -- C : constant Prim_Op_Kind := Get_Prim_Op_Kind (Tag (Concval), S);
10044
10045 -- begin
10046 -- if C = POK_Protected_Entry
10047 -- or else C = POK_Task_Entry
10048 -- then
10049 -- <statements for dispatching requeue>
10050
10051 -- elsif C = POK_Protected_Procedure then
10052 -- <dispatching call equivalent>
10053
10054 -- else
10055 -- raise Program_Error;
10056 -- end if;
10057 -- end;
10058
10059 procedure Expand_N_Requeue_Statement (N : Node_Id) is
10060 Loc : constant Source_Ptr := Sloc (N);
10061 Conc_Typ : Entity_Id;
10062 Concval : Node_Id;
10063 Ename : Node_Id;
10064 Enc_Subp : Entity_Id;
10065 Index : Node_Id;
10066 Old_Typ : Entity_Id;
10067
10068 function Build_Dispatching_Call_Equivalent return Node_Id;
10069 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
10070 -- the form Concval.Ename. It is statically known that Ename is allowed
10071 -- to be implemented by a protected procedure. Create a dispatching call
10072 -- equivalent of Concval.Ename taking the actual parameters from the
10073 -- inner-most accept statement or entry body.
10074
10075 function Build_Dispatching_Requeue return Node_Id;
10076 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
10077 -- the form Concval.Ename. It is statically known that Ename is allowed
10078 -- to be implemented by a protected or a task entry. Create a call to
10079 -- primitive _Disp_Requeue which handles the low-level actions.
10080
10081 function Build_Dispatching_Requeue_To_Any return Node_Id;
10082 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
10083 -- the form Concval.Ename. Ename is either marked by pragma Implemented
10084 -- (XXX, By_Any | Optional) or not marked at all. Create a block which
10085 -- determines at runtime whether Ename denotes an entry or a procedure
10086 -- and perform the appropriate kind of dispatching select.
10087
10088 function Build_Normal_Requeue return Node_Id;
10089 -- N denotes a nondispatching requeue statement to either a task or a
10090 -- protected entry. Build the appropriate runtime call to perform the
10091 -- action.
10092
10093 function Build_Skip_Statement (Search : Node_Id) return Node_Id;
10094 -- For a protected entry, create a return statement to skip the rest of
10095 -- the entry body. Otherwise, create a goto statement to skip the rest
10096 -- of a task accept statement. The lookup for the enclosing entry body
10097 -- or accept statement starts from Search.
10098
10099 ---------------------------------------
10100 -- Build_Dispatching_Call_Equivalent --
10101 ---------------------------------------
10102
10103 function Build_Dispatching_Call_Equivalent return Node_Id is
10104 Call_Ent : constant Entity_Id := Entity (Ename);
10105 Obj : constant Node_Id := Original_Node (Concval);
10106 Acc_Ent : Node_Id;
10107 Actuals : List_Id;
10108 Formal : Node_Id;
10109 Formals : List_Id;
10110
10111 begin
10112 -- Climb the parent chain looking for the inner-most entry body or
10113 -- accept statement.
10114
10115 Acc_Ent := N;
10116 while Present (Acc_Ent)
10117 and then Nkind (Acc_Ent) not in N_Accept_Statement | N_Entry_Body
10118 loop
10119 Acc_Ent := Parent (Acc_Ent);
10120 end loop;
10121
10122 -- A requeue statement should be housed inside an entry body or an
10123 -- accept statement at some level. If this is not the case, then the
10124 -- tree is malformed.
10125
10126 pragma Assert (Present (Acc_Ent));
10127
10128 -- Recover the list of formal parameters
10129
10130 if Nkind (Acc_Ent) = N_Entry_Body then
10131 Acc_Ent := Entry_Body_Formal_Part (Acc_Ent);
10132 end if;
10133
10134 Formals := Parameter_Specifications (Acc_Ent);
10135
10136 -- Create the actual parameters for the dispatching call. These are
10137 -- simply copies of the entry body or accept statement formals in the
10138 -- same order as they appear.
10139
10140 Actuals := No_List;
10141
10142 if Present (Formals) then
10143 Actuals := New_List;
10144 Formal := First (Formals);
10145 while Present (Formal) loop
10146 Append_To (Actuals,
10147 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
10148 Next (Formal);
10149 end loop;
10150 end if;
10151
10152 -- Generate:
10153 -- Obj.Call_Ent (Actuals);
10154
10155 return
10156 Make_Procedure_Call_Statement (Loc,
10157 Name =>
10158 Make_Selected_Component (Loc,
10159 Prefix => Make_Identifier (Loc, Chars (Obj)),
10160 Selector_Name => Make_Identifier (Loc, Chars (Call_Ent))),
10161
10162 Parameter_Associations => Actuals);
10163 end Build_Dispatching_Call_Equivalent;
10164
10165 -------------------------------
10166 -- Build_Dispatching_Requeue --
10167 -------------------------------
10168
10169 function Build_Dispatching_Requeue return Node_Id is
10170 Params : constant List_Id := New_List;
10171
10172 begin
10173 -- Process the "with abort" parameter
10174
10175 Prepend_To (Params,
10176 New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
10177
10178 -- Process the entry wrapper's position in the primary dispatch
10179 -- table parameter. Generate:
10180
10181 -- Ada.Tags.Get_Entry_Index
10182 -- (T => To_Tag_Ptr (Obj'Address).all,
10183 -- Position =>
10184 -- Ada.Tags.Get_Offset_Index
10185 -- (Ada.Tags.Tag (Concval),
10186 -- <interface dispatch table position of Ename>));
10187
10188 -- Note that Obj'Address is recursively expanded into a call to
10189 -- Base_Address (Obj).
10190
10191 if Tagged_Type_Expansion then
10192 Prepend_To (Params,
10193 Make_Function_Call (Loc,
10194 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
10195 Parameter_Associations => New_List (
10196
10197 Make_Explicit_Dereference (Loc,
10198 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
10199 Make_Attribute_Reference (Loc,
10200 Prefix => New_Copy_Tree (Concval),
10201 Attribute_Name => Name_Address))),
10202
10203 Make_Function_Call (Loc,
10204 Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
10205 Parameter_Associations => New_List (
10206 Unchecked_Convert_To (RTE (RE_Tag), Concval),
10207 Make_Integer_Literal (Loc,
10208 DT_Position (Entity (Ename))))))));
10209
10210 -- VM targets
10211
10212 else
10213 Prepend_To (Params,
10214 Make_Function_Call (Loc,
10215 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
10216 Parameter_Associations => New_List (
10217
10218 Make_Attribute_Reference (Loc,
10219 Prefix => Concval,
10220 Attribute_Name => Name_Tag),
10221
10222 Make_Function_Call (Loc,
10223 Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
10224
10225 Parameter_Associations => New_List (
10226
10227 -- Obj_Tag
10228
10229 Make_Attribute_Reference (Loc,
10230 Prefix => Concval,
10231 Attribute_Name => Name_Tag),
10232
10233 -- Tag_Typ
10234
10235 Make_Attribute_Reference (Loc,
10236 Prefix => New_Occurrence_Of (Etype (Concval), Loc),
10237 Attribute_Name => Name_Tag),
10238
10239 -- Position
10240
10241 Make_Integer_Literal (Loc,
10242 DT_Position (Entity (Ename))))))));
10243 end if;
10244
10245 -- Specific actuals for protected to XXX requeue
10246
10247 if Is_Protected_Type (Old_Typ) then
10248 Prepend_To (Params,
10249 Make_Attribute_Reference (Loc, -- _object'Address
10250 Prefix =>
10251 Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
10252 Attribute_Name => Name_Address));
10253
10254 Prepend_To (Params, -- True
10255 New_Occurrence_Of (Standard_True, Loc));
10256
10257 -- Specific actuals for task to XXX requeue
10258
10259 else
10260 pragma Assert (Is_Task_Type (Old_Typ));
10261
10262 Prepend_To (Params, -- null
10263 New_Occurrence_Of (RTE (RE_Null_Address), Loc));
10264
10265 Prepend_To (Params, -- False
10266 New_Occurrence_Of (Standard_False, Loc));
10267 end if;
10268
10269 -- Add the object parameter
10270
10271 Prepend_To (Params, New_Copy_Tree (Concval));
10272
10273 -- Generate:
10274 -- _Disp_Requeue (<Params>);
10275
10276 -- Find entity for Disp_Requeue operation, which belongs to
10277 -- the type and may not be directly visible.
10278
10279 declare
10280 Elmt : Elmt_Id;
10281 Op : Entity_Id := Empty;
10282
10283 begin
10284 Elmt := First_Elmt (Primitive_Operations (Etype (Conc_Typ)));
10285 while Present (Elmt) loop
10286 Op := Node (Elmt);
10287 exit when Chars (Op) = Name_uDisp_Requeue;
10288 Next_Elmt (Elmt);
10289 end loop;
10290
10291 pragma Assert (Present (Op));
10292
10293 return
10294 Make_Procedure_Call_Statement (Loc,
10295 Name => New_Occurrence_Of (Op, Loc),
10296 Parameter_Associations => Params);
10297 end;
10298 end Build_Dispatching_Requeue;
10299
10300 --------------------------------------
10301 -- Build_Dispatching_Requeue_To_Any --
10302 --------------------------------------
10303
10304 function Build_Dispatching_Requeue_To_Any return Node_Id is
10305 Call_Ent : constant Entity_Id := Entity (Ename);
10306 Obj : constant Node_Id := Original_Node (Concval);
10307 Skip : constant Node_Id := Build_Skip_Statement (N);
10308 C : Entity_Id;
10309 Decls : List_Id;
10310 S : Entity_Id;
10311 Stmts : List_Id;
10312
10313 begin
10314 Decls := New_List;
10315 Stmts := New_List;
10316
10317 -- Dispatch table slot processing, generate:
10318 -- S : Integer;
10319
10320 S := Build_S (Loc, Decls);
10321
10322 -- Call kind processing, generate:
10323 -- C : Ada.Tags.Prim_Op_Kind;
10324
10325 C := Build_C (Loc, Decls);
10326
10327 -- Generate:
10328 -- S := Ada.Tags.Get_Offset_Index
10329 -- (Ada.Tags.Tag (Obj), DT_Position (Call_Ent));
10330
10331 Append_To (Stmts, Build_S_Assignment (Loc, S, Obj, Call_Ent));
10332
10333 -- Generate:
10334 -- _Disp_Get_Prim_Op_Kind (Obj, S, C);
10335
10336 Append_To (Stmts,
10337 Make_Procedure_Call_Statement (Loc,
10338 Name =>
10339 New_Occurrence_Of (
10340 Find_Prim_Op (Etype (Etype (Obj)),
10341 Name_uDisp_Get_Prim_Op_Kind),
10342 Loc),
10343 Parameter_Associations => New_List (
10344 New_Copy_Tree (Obj),
10345 New_Occurrence_Of (S, Loc),
10346 New_Occurrence_Of (C, Loc))));
10347
10348 Append_To (Stmts,
10349
10350 -- if C = POK_Protected_Entry
10351 -- or else C = POK_Task_Entry
10352 -- then
10353
10354 Make_Implicit_If_Statement (N,
10355 Condition =>
10356 Make_Op_Or (Loc,
10357 Left_Opnd =>
10358 Make_Op_Eq (Loc,
10359 Left_Opnd =>
10360 New_Occurrence_Of (C, Loc),
10361 Right_Opnd =>
10362 New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
10363
10364 Right_Opnd =>
10365 Make_Op_Eq (Loc,
10366 Left_Opnd =>
10367 New_Occurrence_Of (C, Loc),
10368 Right_Opnd =>
10369 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
10370
10371 -- Dispatching requeue equivalent
10372
10373 Then_Statements => New_List (
10374 Build_Dispatching_Requeue,
10375 Skip),
10376
10377 -- elsif C = POK_Protected_Procedure then
10378
10379 Elsif_Parts => New_List (
10380 Make_Elsif_Part (Loc,
10381 Condition =>
10382 Make_Op_Eq (Loc,
10383 Left_Opnd =>
10384 New_Occurrence_Of (C, Loc),
10385 Right_Opnd =>
10386 New_Occurrence_Of (
10387 RTE (RE_POK_Protected_Procedure), Loc)),
10388
10389 -- Dispatching call equivalent
10390
10391 Then_Statements => New_List (
10392 Build_Dispatching_Call_Equivalent))),
10393
10394 -- else
10395 -- raise Program_Error;
10396 -- end if;
10397
10398 Else_Statements => New_List (
10399 Make_Raise_Program_Error (Loc,
10400 Reason => PE_Explicit_Raise))));
10401
10402 -- Wrap everything into a block
10403
10404 return
10405 Make_Block_Statement (Loc,
10406 Declarations => Decls,
10407 Handled_Statement_Sequence =>
10408 Make_Handled_Sequence_Of_Statements (Loc,
10409 Statements => Stmts));
10410 end Build_Dispatching_Requeue_To_Any;
10411
10412 --------------------------
10413 -- Build_Normal_Requeue --
10414 --------------------------
10415
10416 function Build_Normal_Requeue return Node_Id is
10417 Params : constant List_Id := New_List;
10418 Param : Node_Id;
10419 RT_Call : Node_Id;
10420
10421 begin
10422 -- Process the "with abort" parameter
10423
10424 Prepend_To (Params,
10425 New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
10426
10427 -- Add the index expression to the parameters. It is common among all
10428 -- four cases.
10429
10430 Prepend_To (Params,
10431 Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
10432
10433 if Is_Protected_Type (Old_Typ) then
10434 declare
10435 Self_Param : Node_Id;
10436
10437 begin
10438 Self_Param :=
10439 Make_Attribute_Reference (Loc,
10440 Prefix =>
10441 Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
10442 Attribute_Name =>
10443 Name_Unchecked_Access);
10444
10445 -- Protected to protected requeue
10446
10447 if Is_Protected_Type (Conc_Typ) then
10448 RT_Call :=
10449 New_Occurrence_Of (
10450 RTE (RE_Requeue_Protected_Entry), Loc);
10451
10452 Param :=
10453 Make_Attribute_Reference (Loc,
10454 Prefix =>
10455 Concurrent_Ref (Concval),
10456 Attribute_Name =>
10457 Name_Unchecked_Access);
10458
10459 -- Protected to task requeue
10460
10461 else pragma Assert (Is_Task_Type (Conc_Typ));
10462 RT_Call :=
10463 New_Occurrence_Of (
10464 RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
10465
10466 Param := Concurrent_Ref (Concval);
10467 end if;
10468
10469 Prepend_To (Params, Param);
10470 Prepend_To (Params, Self_Param);
10471 end;
10472
10473 else pragma Assert (Is_Task_Type (Old_Typ));
10474
10475 -- Task to protected requeue
10476
10477 if Is_Protected_Type (Conc_Typ) then
10478 RT_Call :=
10479 New_Occurrence_Of (
10480 RTE (RE_Requeue_Task_To_Protected_Entry), Loc);
10481
10482 Param :=
10483 Make_Attribute_Reference (Loc,
10484 Prefix =>
10485 Concurrent_Ref (Concval),
10486 Attribute_Name =>
10487 Name_Unchecked_Access);
10488
10489 -- Task to task requeue
10490
10491 else pragma Assert (Is_Task_Type (Conc_Typ));
10492 RT_Call :=
10493 New_Occurrence_Of (RTE (RE_Requeue_Task_Entry), Loc);
10494
10495 Param := Concurrent_Ref (Concval);
10496 end if;
10497
10498 Prepend_To (Params, Param);
10499 end if;
10500
10501 return
10502 Make_Procedure_Call_Statement (Loc,
10503 Name => RT_Call,
10504 Parameter_Associations => Params);
10505 end Build_Normal_Requeue;
10506
10507 --------------------------
10508 -- Build_Skip_Statement --
10509 --------------------------
10510
10511 function Build_Skip_Statement (Search : Node_Id) return Node_Id is
10512 Skip_Stmt : Node_Id;
10513
10514 begin
10515 -- Build a return statement to skip the rest of the entire body
10516
10517 if Is_Protected_Type (Old_Typ) then
10518 Skip_Stmt := Make_Simple_Return_Statement (Loc);
10519
10520 -- If the requeue is within a task, find the end label of the
10521 -- enclosing accept statement and create a goto statement to it.
10522
10523 else
10524 declare
10525 Acc : Node_Id;
10526 Label : Node_Id;
10527
10528 begin
10529 -- Climb the parent chain looking for the enclosing accept
10530 -- statement.
10531
10532 Acc := Parent (Search);
10533 while Present (Acc)
10534 and then Nkind (Acc) /= N_Accept_Statement
10535 loop
10536 Acc := Parent (Acc);
10537 end loop;
10538
10539 -- The last statement is the second label used for completing
10540 -- the rendezvous the usual way. The label we are looking for
10541 -- is right before it.
10542
10543 Label :=
10544 Prev (Last (Statements (Handled_Statement_Sequence (Acc))));
10545
10546 pragma Assert (Nkind (Label) = N_Label);
10547
10548 -- Generate a goto statement to skip the rest of the accept
10549
10550 Skip_Stmt :=
10551 Make_Goto_Statement (Loc,
10552 Name =>
10553 New_Occurrence_Of (Entity (Identifier (Label)), Loc));
10554 end;
10555 end if;
10556
10557 Set_Analyzed (Skip_Stmt);
10558
10559 return Skip_Stmt;
10560 end Build_Skip_Statement;
10561
10562 -- Start of processing for Expand_N_Requeue_Statement
10563
10564 begin
10565 -- Extract the components of the entry call
10566
10567 Extract_Entry (N, Concval, Ename, Index);
10568 Conc_Typ := Etype (Concval);
10569
10570 -- Examine the scope stack in order to find nearest enclosing concurrent
10571 -- type. This will constitute our invocation source.
10572
10573 Old_Typ := Current_Scope;
10574 while Present (Old_Typ)
10575 and then not Is_Concurrent_Type (Old_Typ)
10576 loop
10577 Old_Typ := Scope (Old_Typ);
10578 end loop;
10579
10580 -- Obtain the innermost enclosing callable construct for use in
10581 -- generating a dynamic accessibility check.
10582
10583 Enc_Subp := Current_Scope;
10584
10585 if Ekind (Enc_Subp) not in Entry_Kind | Subprogram_Kind then
10586 Enc_Subp := Enclosing_Subprogram (Enc_Subp);
10587 end if;
10588
10589 -- Generate a dynamic accessibility check on the target object
10590
10591 Insert_Before_And_Analyze (N,
10592 Make_Raise_Program_Error (Loc,
10593 Condition =>
10594 Make_Op_Gt (Loc,
10595 Left_Opnd => Accessibility_Level (Name (N), Dynamic_Level),
10596 Right_Opnd => Make_Integer_Literal (Loc,
10597 Scope_Depth (Enc_Subp))),
10598 Reason => PE_Accessibility_Check_Failed));
10599
10600 -- Ada 2012 (AI05-0030): We have a dispatching requeue of the form
10601 -- Concval.Ename where the type of Concval is class-wide concurrent
10602 -- interface.
10603
10604 if Ada_Version >= Ada_2012
10605 and then Present (Concval)
10606 and then Is_Class_Wide_Type (Conc_Typ)
10607 and then Is_Concurrent_Interface (Conc_Typ)
10608 then
10609 declare
10610 Has_Impl : Boolean := False;
10611 Impl_Kind : Name_Id := No_Name;
10612
10613 begin
10614 -- Check whether the Ename is flagged by pragma Implemented
10615
10616 if Has_Rep_Pragma (Entity (Ename), Name_Implemented) then
10617 Has_Impl := True;
10618 Impl_Kind := Implementation_Kind (Entity (Ename));
10619 end if;
10620
10621 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10622 -- an entry. Create a call to predefined primitive _Disp_Requeue.
10623
10624 if Has_Impl and then Impl_Kind = Name_By_Entry then
10625 Rewrite (N, Build_Dispatching_Requeue);
10626 Analyze (N);
10627 Insert_After (N, Build_Skip_Statement (N));
10628
10629 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10630 -- a protected procedure. In this case the requeue is transformed
10631 -- into a dispatching call.
10632
10633 elsif Has_Impl
10634 and then Impl_Kind = Name_By_Protected_Procedure
10635 then
10636 Rewrite (N, Build_Dispatching_Call_Equivalent);
10637 Analyze (N);
10638
10639 -- The procedure_or_entry_NAME's implementation kind is either
10640 -- By_Any, Optional, or pragma Implemented was not applied at all.
10641 -- In this case a runtime test determines whether Ename denotes an
10642 -- entry or a protected procedure and performs the appropriate
10643 -- call.
10644
10645 else
10646 Rewrite (N, Build_Dispatching_Requeue_To_Any);
10647 Analyze (N);
10648 end if;
10649 end;
10650
10651 -- Processing for regular (nondispatching) requeues
10652
10653 else
10654 Rewrite (N, Build_Normal_Requeue);
10655 Analyze (N);
10656 Insert_After (N, Build_Skip_Statement (N));
10657 end if;
10658 end Expand_N_Requeue_Statement;
10659
10660 -------------------------------
10661 -- Expand_N_Selective_Accept --
10662 -------------------------------
10663
10664 procedure Expand_N_Selective_Accept (N : Node_Id) is
10665 Loc : constant Source_Ptr := Sloc (N);
10666 Alts : constant List_Id := Select_Alternatives (N);
10667
10668 -- Note: in the below declarations a lot of new lists are allocated
10669 -- unconditionally which may well not end up being used. That's not
10670 -- a good idea since it wastes space gratuitously ???
10671
10672 Accept_Case : List_Id;
10673 Accept_List : constant List_Id := New_List;
10674
10675 Alt : Node_Id;
10676 Alt_List : constant List_Id := New_List;
10677 Alt_Stats : List_Id;
10678 Ann : Entity_Id := Empty;
10679
10680 Check_Guard : Boolean := True;
10681
10682 Decls : constant List_Id := New_List;
10683 Stats : constant List_Id := New_List;
10684 Body_List : constant List_Id := New_List;
10685 Trailing_List : constant List_Id := New_List;
10686
10687 Choices : List_Id;
10688 Else_Present : Boolean := False;
10689 Terminate_Alt : Node_Id := Empty;
10690 Select_Mode : Node_Id;
10691
10692 Delay_Case : List_Id;
10693 Delay_Count : Integer := 0;
10694 Delay_Val : Entity_Id;
10695 Delay_Index : Entity_Id;
10696 Delay_Min : Entity_Id;
10697 Delay_Num : Pos := 1;
10698 Delay_Alt_List : List_Id := New_List;
10699 Delay_List : constant List_Id := New_List;
10700 D : Entity_Id;
10701 M : Entity_Id;
10702
10703 First_Delay : Boolean := True;
10704 Guard_Open : Entity_Id;
10705
10706 End_Lab : Node_Id;
10707 Index : Pos := 1;
10708 Lab : Node_Id;
10709 Num_Alts : Nat;
10710 Num_Accept : Nat := 0;
10711 Proc : Node_Id;
10712 Time_Type : Entity_Id := Empty;
10713 Select_Call : Node_Id;
10714
10715 Qnam : constant Entity_Id :=
10716 Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
10717
10718 Xnam : constant Entity_Id :=
10719 Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
10720
10721 -----------------------
10722 -- Local subprograms --
10723 -----------------------
10724
10725 function Accept_Or_Raise return List_Id;
10726 -- For the rare case where delay alternatives all have guards, and
10727 -- all of them are closed, it is still possible that there were open
10728 -- accept alternatives with no callers. We must reexamine the
10729 -- Accept_List, and execute a selective wait with no else if some
10730 -- accept is open. If none, we raise program_error.
10731
10732 procedure Add_Accept (Alt : Node_Id);
10733 -- Process a single accept statement in a select alternative. Build
10734 -- procedure for body of accept, and add entry to dispatch table with
10735 -- expression for guard, in preparation for call to run time select.
10736
10737 function Make_And_Declare_Label (Num : Int) return Node_Id;
10738 -- Manufacture a label using Num as a serial number and declare it.
10739 -- The declaration is appended to Decls. The label marks the trailing
10740 -- statements of an accept or delay alternative.
10741
10742 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
10743 -- Build call to Selective_Wait runtime routine
10744
10745 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
10746 -- Add code to compare value of delay with previous values, and
10747 -- generate case entry for trailing statements.
10748
10749 procedure Process_Accept_Alternative
10750 (Alt : Node_Id;
10751 Index : Int;
10752 Proc : Node_Id);
10753 -- Add code to call corresponding procedure, and branch to
10754 -- trailing statements, if any.
10755
10756 ---------------------
10757 -- Accept_Or_Raise --
10758 ---------------------
10759
10760 function Accept_Or_Raise return List_Id is
10761 Cond : Node_Id;
10762 Stats : List_Id;
10763 J : constant Entity_Id := Make_Temporary (Loc, 'J');
10764
10765 begin
10766 -- We generate the following:
10767
10768 -- for J in q'range loop
10769 -- if q(J).S /=null_task_entry then
10770 -- selective_wait (simple_mode,...);
10771 -- done := True;
10772 -- exit;
10773 -- end if;
10774 -- end loop;
10775 --
10776 -- if no rendez_vous then
10777 -- raise program_error;
10778 -- end if;
10779
10780 -- Note that the code needs to know that the selector name
10781 -- in an Accept_Alternative is named S.
10782
10783 Cond := Make_Op_Ne (Loc,
10784 Left_Opnd =>
10785 Make_Selected_Component (Loc,
10786 Prefix =>
10787 Make_Indexed_Component (Loc,
10788 Prefix => New_Occurrence_Of (Qnam, Loc),
10789 Expressions => New_List (New_Occurrence_Of (J, Loc))),
10790 Selector_Name => Make_Identifier (Loc, Name_S)),
10791 Right_Opnd =>
10792 New_Occurrence_Of (RTE (RE_Null_Task_Entry), Loc));
10793
10794 Stats := New_List (
10795 Make_Implicit_Loop_Statement (N,
10796 Iteration_Scheme =>
10797 Make_Iteration_Scheme (Loc,
10798 Loop_Parameter_Specification =>
10799 Make_Loop_Parameter_Specification (Loc,
10800 Defining_Identifier => J,
10801 Discrete_Subtype_Definition =>
10802 Make_Attribute_Reference (Loc,
10803 Prefix => New_Occurrence_Of (Qnam, Loc),
10804 Attribute_Name => Name_Range,
10805 Expressions => New_List (
10806 Make_Integer_Literal (Loc, 1))))),
10807
10808 Statements => New_List (
10809 Make_Implicit_If_Statement (N,
10810 Condition => Cond,
10811 Then_Statements => New_List (
10812 Make_Select_Call (
10813 New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)),
10814 Make_Exit_Statement (Loc))))));
10815
10816 Append_To (Stats,
10817 Make_Raise_Program_Error (Loc,
10818 Condition => Make_Op_Eq (Loc,
10819 Left_Opnd => New_Occurrence_Of (Xnam, Loc),
10820 Right_Opnd =>
10821 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
10822 Reason => PE_All_Guards_Closed));
10823
10824 return Stats;
10825 end Accept_Or_Raise;
10826
10827 ----------------
10828 -- Add_Accept --
10829 ----------------
10830
10831 procedure Add_Accept (Alt : Node_Id) is
10832 Acc_Stm : constant Node_Id := Accept_Statement (Alt);
10833 Ename : constant Node_Id := Entry_Direct_Name (Acc_Stm);
10834 Eloc : constant Source_Ptr := Sloc (Ename);
10835 Eent : constant Entity_Id := Entity (Ename);
10836 Index : constant Node_Id := Entry_Index (Acc_Stm);
10837
10838 Call : Node_Id;
10839 Expr : Node_Id;
10840 Null_Body : Node_Id;
10841 PB_Ent : Entity_Id;
10842 Proc_Body : Node_Id;
10843
10844 -- Start of processing for Add_Accept
10845
10846 begin
10847 if No (Ann) then
10848 Ann := Node (Last_Elmt (Accept_Address (Eent)));
10849 end if;
10850
10851 if Present (Condition (Alt)) then
10852 Expr :=
10853 Make_If_Expression (Eloc, New_List (
10854 Condition (Alt),
10855 Entry_Index_Expression (Eloc, Eent, Index, Scope (Eent)),
10856 New_Occurrence_Of (RTE (RE_Null_Task_Entry), Eloc)));
10857 else
10858 Expr := Entry_Index_Expression (Eloc, Eent, Index, Scope (Eent));
10859 end if;
10860
10861 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
10862 Null_Body := New_Occurrence_Of (Standard_False, Eloc);
10863
10864 -- Always add call to Abort_Undefer when generating code, since
10865 -- this is what the runtime expects (abort deferred in
10866 -- Selective_Wait). In CodePeer mode this only confuses the
10867 -- analysis with unknown calls, so don't do it.
10868
10869 if not CodePeer_Mode then
10870 Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
10871 Insert_Before
10872 (First (Statements (Handled_Statement_Sequence
10873 (Accept_Statement (Alt)))),
10874 Call);
10875 Analyze (Call);
10876 end if;
10877
10878 PB_Ent :=
10879 Make_Defining_Identifier (Eloc,
10880 New_External_Name (Chars (Ename), 'A', Num_Accept));
10881
10882 -- Link the acceptor to the original receiving entry
10883
10884 Set_Ekind (PB_Ent, E_Procedure);
10885 Set_Receiving_Entry (PB_Ent, Eent);
10886
10887 if Comes_From_Source (Alt) then
10888 Set_Debug_Info_Needed (PB_Ent);
10889 end if;
10890
10891 Proc_Body :=
10892 Make_Subprogram_Body (Eloc,
10893 Specification =>
10894 Make_Procedure_Specification (Eloc,
10895 Defining_Unit_Name => PB_Ent),
10896 Declarations => Declarations (Acc_Stm),
10897 Handled_Statement_Sequence =>
10898 Build_Accept_Body (Accept_Statement (Alt)));
10899
10900 Reset_Scopes_To (Proc_Body, PB_Ent);
10901
10902 -- During the analysis of the body of the accept statement, any
10903 -- zero cost exception handler records were collected in the
10904 -- Accept_Handler_Records field of the N_Accept_Alternative node.
10905 -- This is where we move them to where they belong, namely the
10906 -- newly created procedure.
10907
10908 Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
10909 Append (Proc_Body, Body_List);
10910
10911 else
10912 Null_Body := New_Occurrence_Of (Standard_True, Eloc);
10913
10914 -- if accept statement has declarations, insert above, given that
10915 -- we are not creating a body for the accept.
10916
10917 if Present (Declarations (Acc_Stm)) then
10918 Insert_Actions (N, Declarations (Acc_Stm));
10919 end if;
10920 end if;
10921
10922 Append_To (Accept_List,
10923 Make_Aggregate (Eloc, Expressions => New_List (Null_Body, Expr)));
10924
10925 Num_Accept := Num_Accept + 1;
10926 end Add_Accept;
10927
10928 ----------------------------
10929 -- Make_And_Declare_Label --
10930 ----------------------------
10931
10932 function Make_And_Declare_Label (Num : Int) return Node_Id is
10933 Lab_Id : Node_Id;
10934
10935 begin
10936 Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
10937 Lab :=
10938 Make_Label (Loc, Lab_Id);
10939
10940 Append_To (Decls,
10941 Make_Implicit_Label_Declaration (Loc,
10942 Defining_Identifier =>
10943 Make_Defining_Identifier (Loc, Chars (Lab_Id)),
10944 Label_Construct => Lab));
10945
10946 return Lab;
10947 end Make_And_Declare_Label;
10948
10949 ----------------------
10950 -- Make_Select_Call --
10951 ----------------------
10952
10953 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
10954 Params : constant List_Id := New_List;
10955
10956 begin
10957 Append_To (Params,
10958 Make_Attribute_Reference (Loc,
10959 Prefix => New_Occurrence_Of (Qnam, Loc),
10960 Attribute_Name => Name_Unchecked_Access));
10961 Append_To (Params, Select_Mode);
10962 Append_To (Params, New_Occurrence_Of (Ann, Loc));
10963 Append_To (Params, New_Occurrence_Of (Xnam, Loc));
10964
10965 return
10966 Make_Procedure_Call_Statement (Loc,
10967 Name => New_Occurrence_Of (RTE (RE_Selective_Wait), Loc),
10968 Parameter_Associations => Params);
10969 end Make_Select_Call;
10970
10971 --------------------------------
10972 -- Process_Accept_Alternative --
10973 --------------------------------
10974
10975 procedure Process_Accept_Alternative
10976 (Alt : Node_Id;
10977 Index : Int;
10978 Proc : Node_Id)
10979 is
10980 Astmt : constant Node_Id := Accept_Statement (Alt);
10981 Alt_Stats : List_Id;
10982
10983 begin
10984 Adjust_Condition (Condition (Alt));
10985
10986 -- Accept with body
10987
10988 if Present (Handled_Statement_Sequence (Astmt)) then
10989 Alt_Stats :=
10990 New_List (
10991 Make_Procedure_Call_Statement (Sloc (Proc),
10992 Name =>
10993 New_Occurrence_Of
10994 (Defining_Unit_Name (Specification (Proc)),
10995 Sloc (Proc))));
10996
10997 -- Accept with no body (followed by trailing statements)
10998
10999 else
11000 declare
11001 Entry_Id : constant Entity_Id :=
11002 Entity (Entry_Direct_Name (Accept_Statement (Alt)));
11003 begin
11004 -- Ada 2020 (AI12-0279)
11005
11006 if Has_Yield_Aspect (Entry_Id)
11007 and then RTE_Available (RE_Yield)
11008 then
11009 Alt_Stats :=
11010 New_List (
11011 Make_Procedure_Call_Statement (Sloc (Proc),
11012 New_Occurrence_Of (RTE (RE_Yield), Sloc (Proc))));
11013 else
11014 Alt_Stats := Empty_List;
11015 end if;
11016 end;
11017 end if;
11018
11019 Ensure_Statement_Present (Sloc (Astmt), Alt);
11020
11021 -- After the call, if any, branch to trailing statements, if any.
11022 -- We create a label for each, as well as the corresponding label
11023 -- declaration.
11024
11025 if not Is_Empty_List (Statements (Alt)) then
11026 Lab := Make_And_Declare_Label (Index);
11027 Append (Lab, Trailing_List);
11028 Append_List (Statements (Alt), Trailing_List);
11029 Append_To (Trailing_List,
11030 Make_Goto_Statement (Loc,
11031 Name => New_Copy (Identifier (End_Lab))));
11032
11033 else
11034 Lab := End_Lab;
11035 end if;
11036
11037 Append_To (Alt_Stats,
11038 Make_Goto_Statement (Loc, Name => New_Copy (Identifier (Lab))));
11039
11040 Append_To (Alt_List,
11041 Make_Case_Statement_Alternative (Loc,
11042 Discrete_Choices => New_List (Make_Integer_Literal (Loc, Index)),
11043 Statements => Alt_Stats));
11044 end Process_Accept_Alternative;
11045
11046 -------------------------------
11047 -- Process_Delay_Alternative --
11048 -------------------------------
11049
11050 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
11051 Dloc : constant Source_Ptr := Sloc (Delay_Statement (Alt));
11052 Cond : Node_Id;
11053 Delay_Alt : List_Id;
11054
11055 begin
11056 -- Deal with C/Fortran boolean as delay condition
11057
11058 Adjust_Condition (Condition (Alt));
11059
11060 -- Determine the smallest specified delay
11061
11062 -- for each delay alternative generate:
11063
11064 -- if guard-expression then
11065 -- Delay_Val := delay-expression;
11066 -- Guard_Open := True;
11067 -- if Delay_Val < Delay_Min then
11068 -- Delay_Min := Delay_Val;
11069 -- Delay_Index := Index;
11070 -- end if;
11071 -- end if;
11072
11073 -- The enclosing if-statement is omitted if there is no guard
11074
11075 if Delay_Count = 1 or else First_Delay then
11076 First_Delay := False;
11077
11078 Delay_Alt := New_List (
11079 Make_Assignment_Statement (Loc,
11080 Name => New_Occurrence_Of (Delay_Min, Loc),
11081 Expression => Expression (Delay_Statement (Alt))));
11082
11083 if Delay_Count > 1 then
11084 Append_To (Delay_Alt,
11085 Make_Assignment_Statement (Loc,
11086 Name => New_Occurrence_Of (Delay_Index, Loc),
11087 Expression => Make_Integer_Literal (Loc, Index)));
11088 end if;
11089
11090 else
11091 Delay_Alt := New_List (
11092 Make_Assignment_Statement (Loc,
11093 Name => New_Occurrence_Of (Delay_Val, Loc),
11094 Expression => Expression (Delay_Statement (Alt))));
11095
11096 if Time_Type = Standard_Duration then
11097 Cond :=
11098 Make_Op_Lt (Loc,
11099 Left_Opnd => New_Occurrence_Of (Delay_Val, Loc),
11100 Right_Opnd => New_Occurrence_Of (Delay_Min, Loc));
11101
11102 else
11103 -- The scope of the time type must define a comparison
11104 -- operator. The scope itself may not be visible, so we
11105 -- construct a node with entity information to insure that
11106 -- semantic analysis can find the proper operator.
11107
11108 Cond :=
11109 Make_Function_Call (Loc,
11110 Name => Make_Selected_Component (Loc,
11111 Prefix =>
11112 New_Occurrence_Of (Scope (Time_Type), Loc),
11113 Selector_Name =>
11114 Make_Operator_Symbol (Loc,
11115 Chars => Name_Op_Lt,
11116 Strval => No_String)),
11117 Parameter_Associations =>
11118 New_List (
11119 New_Occurrence_Of (Delay_Val, Loc),
11120 New_Occurrence_Of (Delay_Min, Loc)));
11121
11122 Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
11123 end if;
11124
11125 Append_To (Delay_Alt,
11126 Make_Implicit_If_Statement (N,
11127 Condition => Cond,
11128 Then_Statements => New_List (
11129 Make_Assignment_Statement (Loc,
11130 Name => New_Occurrence_Of (Delay_Min, Loc),
11131 Expression => New_Occurrence_Of (Delay_Val, Loc)),
11132
11133 Make_Assignment_Statement (Loc,
11134 Name => New_Occurrence_Of (Delay_Index, Loc),
11135 Expression => Make_Integer_Literal (Loc, Index)))));
11136 end if;
11137
11138 if Check_Guard then
11139 Append_To (Delay_Alt,
11140 Make_Assignment_Statement (Loc,
11141 Name => New_Occurrence_Of (Guard_Open, Loc),
11142 Expression => New_Occurrence_Of (Standard_True, Loc)));
11143 end if;
11144
11145 if Present (Condition (Alt)) then
11146 Delay_Alt := New_List (
11147 Make_Implicit_If_Statement (N,
11148 Condition => Condition (Alt),
11149 Then_Statements => Delay_Alt));
11150 end if;
11151
11152 Append_List (Delay_Alt, Delay_List);
11153
11154 Ensure_Statement_Present (Dloc, Alt);
11155
11156 -- If the delay alternative has a statement part, add choice to the
11157 -- case statements for delays.
11158
11159 if not Is_Empty_List (Statements (Alt)) then
11160
11161 if Delay_Count = 1 then
11162 Append_List (Statements (Alt), Delay_Alt_List);
11163
11164 else
11165 Append_To (Delay_Alt_List,
11166 Make_Case_Statement_Alternative (Loc,
11167 Discrete_Choices => New_List (
11168 Make_Integer_Literal (Loc, Index)),
11169 Statements => Statements (Alt)));
11170 end if;
11171
11172 elsif Delay_Count = 1 then
11173
11174 -- If the single delay has no trailing statements, add a branch
11175 -- to the exit label to the selective wait.
11176
11177 Delay_Alt_List := New_List (
11178 Make_Goto_Statement (Loc,
11179 Name => New_Copy (Identifier (End_Lab))));
11180
11181 end if;
11182 end Process_Delay_Alternative;
11183
11184 -- Start of processing for Expand_N_Selective_Accept
11185
11186 begin
11187 Process_Statements_For_Controlled_Objects (N);
11188
11189 -- First insert some declarations before the select. The first is:
11190
11191 -- Ann : Address
11192
11193 -- This variable holds the parameters passed to the accept body. This
11194 -- declaration has already been inserted by the time we get here by
11195 -- a call to Expand_Accept_Declarations made from the semantics when
11196 -- processing the first accept statement contained in the select. We
11197 -- can find this entity as Accept_Address (E), where E is any of the
11198 -- entries references by contained accept statements.
11199
11200 -- The first step is to scan the list of Selective_Accept_Statements
11201 -- to find this entity, and also count the number of accepts, and
11202 -- determine if terminated, delay or else is present:
11203
11204 Num_Alts := 0;
11205
11206 Alt := First (Alts);
11207 while Present (Alt) loop
11208 Process_Statements_For_Controlled_Objects (Alt);
11209
11210 if Nkind (Alt) = N_Accept_Alternative then
11211 Add_Accept (Alt);
11212
11213 elsif Nkind (Alt) = N_Delay_Alternative then
11214 Delay_Count := Delay_Count + 1;
11215
11216 -- If the delays are relative delays, the delay expressions have
11217 -- type Standard_Duration. Otherwise they must have some time type
11218 -- recognized by GNAT.
11219
11220 if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
11221 Time_Type := Standard_Duration;
11222 else
11223 Time_Type := Etype (Expression (Delay_Statement (Alt)));
11224
11225 if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
11226 or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
11227 then
11228 null;
11229 else
11230 -- Move this check to sem???
11231 Error_Msg_NE (
11232 "& is not a time type (RM 9.6(6))",
11233 Expression (Delay_Statement (Alt)), Time_Type);
11234 Time_Type := Standard_Duration;
11235 Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
11236 end if;
11237 end if;
11238
11239 if No (Condition (Alt)) then
11240
11241 -- This guard will always be open
11242
11243 Check_Guard := False;
11244 end if;
11245
11246 elsif Nkind (Alt) = N_Terminate_Alternative then
11247 Adjust_Condition (Condition (Alt));
11248 Terminate_Alt := Alt;
11249 end if;
11250
11251 Num_Alts := Num_Alts + 1;
11252 Next (Alt);
11253 end loop;
11254
11255 Else_Present := Present (Else_Statements (N));
11256
11257 -- At the same time (see procedure Add_Accept) we build the accept list:
11258
11259 -- Qnn : Accept_List (1 .. num-select) := (
11260 -- (null-body, entry-index),
11261 -- (null-body, entry-index),
11262 -- ..
11263 -- (null_body, entry-index));
11264
11265 -- In the above declaration, null-body is True if the corresponding
11266 -- accept has no body, and false otherwise. The entry is either the
11267 -- entry index expression if there is no guard, or if a guard is
11268 -- present, then an if expression of the form:
11269
11270 -- (if guard then entry-index else Null_Task_Entry)
11271
11272 -- If a guard is statically known to be false, the entry can simply
11273 -- be omitted from the accept list.
11274
11275 Append_To (Decls,
11276 Make_Object_Declaration (Loc,
11277 Defining_Identifier => Qnam,
11278 Object_Definition => New_Occurrence_Of (RTE (RE_Accept_List), Loc),
11279 Aliased_Present => True,
11280 Expression =>
11281 Make_Qualified_Expression (Loc,
11282 Subtype_Mark =>
11283 New_Occurrence_Of (RTE (RE_Accept_List), Loc),
11284 Expression =>
11285 Make_Aggregate (Loc, Expressions => Accept_List))));
11286
11287 -- Then we declare the variable that holds the index for the accept
11288 -- that will be selected for service:
11289
11290 -- Xnn : Select_Index;
11291
11292 Append_To (Decls,
11293 Make_Object_Declaration (Loc,
11294 Defining_Identifier => Xnam,
11295 Object_Definition =>
11296 New_Occurrence_Of (RTE (RE_Select_Index), Loc),
11297 Expression =>
11298 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)));
11299
11300 -- After this follow procedure declarations for each accept body
11301
11302 -- procedure Pnn is
11303 -- begin
11304 -- ...
11305 -- end;
11306
11307 -- where the ... are statements from the corresponding procedure body.
11308 -- No parameters are involved, since the parameters are passed via Ann
11309 -- and the parameter references have already been expanded to be direct
11310 -- references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
11311 -- any embedded tasking statements (which would normally be illegal in
11312 -- procedures), have been converted to calls to the tasking runtime so
11313 -- there is no problem in putting them into procedures.
11314
11315 -- The original accept statement has been expanded into a block in
11316 -- the same fashion as for simple accepts (see Build_Accept_Body).
11317
11318 -- Note: we don't really need to build these procedures for the case
11319 -- where no delay statement is present, but it is just as easy to
11320 -- build them unconditionally, and not significantly inefficient,
11321 -- since if they are short they will be inlined anyway.
11322
11323 -- The procedure declarations have been assembled in Body_List
11324
11325 -- If delays are present, we must compute the required delay.
11326 -- We first generate the declarations:
11327
11328 -- Delay_Index : Boolean := 0;
11329 -- Delay_Min : Some_Time_Type.Time;
11330 -- Delay_Val : Some_Time_Type.Time;
11331
11332 -- Delay_Index will be set to the index of the minimum delay, i.e. the
11333 -- active delay that is actually chosen as the basis for the possible
11334 -- delay if an immediate rendez-vous is not possible.
11335
11336 -- In the most common case there is a single delay statement, and this
11337 -- is handled specially.
11338
11339 if Delay_Count > 0 then
11340
11341 -- Generate the required declarations
11342
11343 Delay_Val :=
11344 Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
11345 Delay_Index :=
11346 Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
11347 Delay_Min :=
11348 Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
11349
11350 pragma Assert (Present (Time_Type));
11351
11352 Append_To (Decls,
11353 Make_Object_Declaration (Loc,
11354 Defining_Identifier => Delay_Val,
11355 Object_Definition => New_Occurrence_Of (Time_Type, Loc)));
11356
11357 Append_To (Decls,
11358 Make_Object_Declaration (Loc,
11359 Defining_Identifier => Delay_Index,
11360 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
11361 Expression => Make_Integer_Literal (Loc, 0)));
11362
11363 Append_To (Decls,
11364 Make_Object_Declaration (Loc,
11365 Defining_Identifier => Delay_Min,
11366 Object_Definition => New_Occurrence_Of (Time_Type, Loc),
11367 Expression =>
11368 Unchecked_Convert_To (Time_Type,
11369 Make_Attribute_Reference (Loc,
11370 Prefix =>
11371 New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
11372 Attribute_Name => Name_Last))));
11373
11374 -- Create Duration and Delay_Mode objects used for passing a delay
11375 -- value to RTS
11376
11377 D := Make_Temporary (Loc, 'D');
11378 M := Make_Temporary (Loc, 'M');
11379
11380 declare
11381 Discr : Entity_Id;
11382
11383 begin
11384 -- Note that these values are defined in s-osprim.ads and must
11385 -- be kept in sync:
11386 --
11387 -- Relative : constant := 0;
11388 -- Absolute_Calendar : constant := 1;
11389 -- Absolute_RT : constant := 2;
11390
11391 if Time_Type = Standard_Duration then
11392 Discr := Make_Integer_Literal (Loc, 0);
11393
11394 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11395 Discr := Make_Integer_Literal (Loc, 1);
11396
11397 else
11398 pragma Assert
11399 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11400 Discr := Make_Integer_Literal (Loc, 2);
11401 end if;
11402
11403 Append_To (Decls,
11404 Make_Object_Declaration (Loc,
11405 Defining_Identifier => D,
11406 Object_Definition =>
11407 New_Occurrence_Of (Standard_Duration, Loc)));
11408
11409 Append_To (Decls,
11410 Make_Object_Declaration (Loc,
11411 Defining_Identifier => M,
11412 Object_Definition =>
11413 New_Occurrence_Of (Standard_Integer, Loc),
11414 Expression => Discr));
11415 end;
11416
11417 if Check_Guard then
11418 Guard_Open :=
11419 Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
11420
11421 Append_To (Decls,
11422 Make_Object_Declaration (Loc,
11423 Defining_Identifier => Guard_Open,
11424 Object_Definition =>
11425 New_Occurrence_Of (Standard_Boolean, Loc),
11426 Expression =>
11427 New_Occurrence_Of (Standard_False, Loc)));
11428 end if;
11429
11430 -- Delay_Count is zero, don't need M and D set (suppress warning)
11431
11432 else
11433 M := Empty;
11434 D := Empty;
11435 end if;
11436
11437 if Present (Terminate_Alt) then
11438
11439 -- If the terminate alternative guard is False, use
11440 -- Simple_Mode; otherwise use Terminate_Mode.
11441
11442 if Present (Condition (Terminate_Alt)) then
11443 Select_Mode := Make_If_Expression (Loc,
11444 New_List (Condition (Terminate_Alt),
11445 New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc),
11446 New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)));
11447 else
11448 Select_Mode := New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc);
11449 end if;
11450
11451 elsif Else_Present or Delay_Count > 0 then
11452 Select_Mode := New_Occurrence_Of (RTE (RE_Else_Mode), Loc);
11453
11454 else
11455 Select_Mode := New_Occurrence_Of (RTE (RE_Simple_Mode), Loc);
11456 end if;
11457
11458 Select_Call := Make_Select_Call (Select_Mode);
11459 Append (Select_Call, Stats);
11460
11461 -- Now generate code to act on the result. There is an entry
11462 -- in this case for each accept statement with a non-null body,
11463 -- followed by a branch to the statements that follow the Accept.
11464 -- In the absence of delay alternatives, we generate:
11465
11466 -- case X is
11467 -- when No_Rendezvous => -- omitted if simple mode
11468 -- goto Lab0;
11469
11470 -- when 1 =>
11471 -- P1n;
11472 -- goto Lab1;
11473
11474 -- when 2 =>
11475 -- P2n;
11476 -- goto Lab2;
11477
11478 -- when others =>
11479 -- goto Exit;
11480 -- end case;
11481 --
11482 -- Lab0: Else_Statements;
11483 -- goto exit;
11484
11485 -- Lab1: Trailing_Statements1;
11486 -- goto Exit;
11487 --
11488 -- Lab2: Trailing_Statements2;
11489 -- goto Exit;
11490 -- ...
11491 -- Exit:
11492
11493 -- Generate label for common exit
11494
11495 End_Lab := Make_And_Declare_Label (Num_Alts + 1);
11496
11497 -- First entry is the default case, when no rendezvous is possible
11498
11499 Choices := New_List (New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc));
11500
11501 if Else_Present then
11502
11503 -- If no rendezvous is possible, the else part is executed
11504
11505 Lab := Make_And_Declare_Label (0);
11506 Alt_Stats := New_List (
11507 Make_Goto_Statement (Loc,
11508 Name => New_Copy (Identifier (Lab))));
11509
11510 Append (Lab, Trailing_List);
11511 Append_List (Else_Statements (N), Trailing_List);
11512 Append_To (Trailing_List,
11513 Make_Goto_Statement (Loc,
11514 Name => New_Copy (Identifier (End_Lab))));
11515 else
11516 Alt_Stats := New_List (
11517 Make_Goto_Statement (Loc,
11518 Name => New_Copy (Identifier (End_Lab))));
11519 end if;
11520
11521 Append_To (Alt_List,
11522 Make_Case_Statement_Alternative (Loc,
11523 Discrete_Choices => Choices,
11524 Statements => Alt_Stats));
11525
11526 -- We make use of the fact that Accept_Index is an integer type, and
11527 -- generate successive literals for entries for each accept. Only those
11528 -- for which there is a body or trailing statements get a case entry.
11529
11530 Alt := First (Select_Alternatives (N));
11531 Proc := First (Body_List);
11532 while Present (Alt) loop
11533
11534 if Nkind (Alt) = N_Accept_Alternative then
11535 Process_Accept_Alternative (Alt, Index, Proc);
11536 Index := Index + 1;
11537
11538 if Present
11539 (Handled_Statement_Sequence (Accept_Statement (Alt)))
11540 then
11541 Next (Proc);
11542 end if;
11543
11544 elsif Nkind (Alt) = N_Delay_Alternative then
11545 Process_Delay_Alternative (Alt, Delay_Num);
11546 Delay_Num := Delay_Num + 1;
11547 end if;
11548
11549 Next (Alt);
11550 end loop;
11551
11552 -- An others choice is always added to the main case, as well
11553 -- as the delay case (to satisfy the compiler).
11554
11555 Append_To (Alt_List,
11556 Make_Case_Statement_Alternative (Loc,
11557 Discrete_Choices =>
11558 New_List (Make_Others_Choice (Loc)),
11559 Statements =>
11560 New_List (Make_Goto_Statement (Loc,
11561 Name => New_Copy (Identifier (End_Lab))))));
11562
11563 Accept_Case := New_List (
11564 Make_Case_Statement (Loc,
11565 Expression => New_Occurrence_Of (Xnam, Loc),
11566 Alternatives => Alt_List));
11567
11568 Append_List (Trailing_List, Accept_Case);
11569 Append_List (Body_List, Decls);
11570
11571 -- Construct case statement for trailing statements of delay
11572 -- alternatives, if there are several of them.
11573
11574 if Delay_Count > 1 then
11575 Append_To (Delay_Alt_List,
11576 Make_Case_Statement_Alternative (Loc,
11577 Discrete_Choices =>
11578 New_List (Make_Others_Choice (Loc)),
11579 Statements =>
11580 New_List (Make_Null_Statement (Loc))));
11581
11582 Delay_Case := New_List (
11583 Make_Case_Statement (Loc,
11584 Expression => New_Occurrence_Of (Delay_Index, Loc),
11585 Alternatives => Delay_Alt_List));
11586 else
11587 Delay_Case := Delay_Alt_List;
11588 end if;
11589
11590 -- If there are no delay alternatives, we append the case statement
11591 -- to the statement list.
11592
11593 if Delay_Count = 0 then
11594 Append_List (Accept_Case, Stats);
11595
11596 -- Delay alternatives present
11597
11598 else
11599 -- If delay alternatives are present we generate:
11600
11601 -- find minimum delay.
11602 -- DX := minimum delay;
11603 -- M := <delay mode>;
11604 -- Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
11605 -- DX, MX, X);
11606 --
11607 -- if X = No_Rendezvous then
11608 -- case statement for delay statements.
11609 -- else
11610 -- case statement for accept alternatives.
11611 -- end if;
11612
11613 declare
11614 Cases : Node_Id;
11615 Stmt : Node_Id;
11616 Parms : List_Id;
11617 Parm : Node_Id;
11618 Conv : Node_Id;
11619
11620 begin
11621 -- The type of the delay expression is known to be legal
11622
11623 if Time_Type = Standard_Duration then
11624 Conv := New_Occurrence_Of (Delay_Min, Loc);
11625
11626 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11627 Conv := Make_Function_Call (Loc,
11628 New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
11629 New_List (New_Occurrence_Of (Delay_Min, Loc)));
11630
11631 else
11632 pragma Assert
11633 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11634
11635 Conv := Make_Function_Call (Loc,
11636 New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
11637 New_List (New_Occurrence_Of (Delay_Min, Loc)));
11638 end if;
11639
11640 Stmt := Make_Assignment_Statement (Loc,
11641 Name => New_Occurrence_Of (D, Loc),
11642 Expression => Conv);
11643
11644 -- Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
11645
11646 Parms := Parameter_Associations (Select_Call);
11647
11648 Parm := First (Parms);
11649 while Present (Parm) and then Parm /= Select_Mode loop
11650 Next (Parm);
11651 end loop;
11652
11653 pragma Assert (Present (Parm));
11654 Rewrite (Parm, New_Occurrence_Of (RTE (RE_Delay_Mode), Loc));
11655 Analyze (Parm);
11656
11657 -- Prepare two new parameters of Duration and Delay_Mode type
11658 -- which represent the value and the mode of the minimum delay.
11659
11660 Next (Parm);
11661 Insert_After (Parm, New_Occurrence_Of (M, Loc));
11662 Insert_After (Parm, New_Occurrence_Of (D, Loc));
11663
11664 -- Create a call to RTS
11665
11666 Rewrite (Select_Call,
11667 Make_Procedure_Call_Statement (Loc,
11668 Name => New_Occurrence_Of (RTE (RE_Timed_Selective_Wait), Loc),
11669 Parameter_Associations => Parms));
11670
11671 -- This new call should follow the calculation of the minimum
11672 -- delay.
11673
11674 Insert_List_Before (Select_Call, Delay_List);
11675
11676 if Check_Guard then
11677 Stmt :=
11678 Make_Implicit_If_Statement (N,
11679 Condition => New_Occurrence_Of (Guard_Open, Loc),
11680 Then_Statements => New_List (
11681 New_Copy_Tree (Stmt),
11682 New_Copy_Tree (Select_Call)),
11683 Else_Statements => Accept_Or_Raise);
11684 Rewrite (Select_Call, Stmt);
11685 else
11686 Insert_Before (Select_Call, Stmt);
11687 end if;
11688
11689 Cases :=
11690 Make_Implicit_If_Statement (N,
11691 Condition => Make_Op_Eq (Loc,
11692 Left_Opnd => New_Occurrence_Of (Xnam, Loc),
11693 Right_Opnd =>
11694 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
11695
11696 Then_Statements => Delay_Case,
11697 Else_Statements => Accept_Case);
11698
11699 Append (Cases, Stats);
11700 end;
11701 end if;
11702
11703 Append (End_Lab, Stats);
11704
11705 -- Replace accept statement with appropriate block
11706
11707 Rewrite (N,
11708 Make_Block_Statement (Loc,
11709 Declarations => Decls,
11710 Handled_Statement_Sequence =>
11711 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stats)));
11712 Analyze (N);
11713
11714 -- Note: have to worry more about abort deferral in above code ???
11715
11716 -- Final step is to unstack the Accept_Address entries for all accept
11717 -- statements appearing in accept alternatives in the select statement
11718
11719 Alt := First (Alts);
11720 while Present (Alt) loop
11721 if Nkind (Alt) = N_Accept_Alternative then
11722 Remove_Last_Elmt (Accept_Address
11723 (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
11724 end if;
11725
11726 Next (Alt);
11727 end loop;
11728 end Expand_N_Selective_Accept;
11729
11730 -------------------------------------------
11731 -- Expand_N_Single_Protected_Declaration --
11732 -------------------------------------------
11733
11734 -- A single protected declaration should never be present after semantic
11735 -- analysis because it is transformed into a protected type declaration
11736 -- and an accompanying anonymous object. This routine ensures that the
11737 -- transformation takes place.
11738
11739 procedure Expand_N_Single_Protected_Declaration (N : Node_Id) is
11740 begin
11741 raise Program_Error;
11742 end Expand_N_Single_Protected_Declaration;
11743
11744 --------------------------------------
11745 -- Expand_N_Single_Task_Declaration --
11746 --------------------------------------
11747
11748 -- A single task declaration should never be present after semantic
11749 -- analysis because it is transformed into a task type declaration and
11750 -- an accompanying anonymous object. This routine ensures that the
11751 -- transformation takes place.
11752
11753 procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
11754 begin
11755 raise Program_Error;
11756 end Expand_N_Single_Task_Declaration;
11757
11758 ------------------------
11759 -- Expand_N_Task_Body --
11760 ------------------------
11761
11762 -- Given a task body
11763
11764 -- task body tname is
11765 -- <declarations>
11766 -- begin
11767 -- <statements>
11768 -- end x;
11769
11770 -- This expansion routine converts it into a procedure and sets the
11771 -- elaboration flag for the procedure to true, to represent the fact
11772 -- that the task body is now elaborated:
11773
11774 -- procedure tnameB (_Task : access tnameV) is
11775 -- discriminal : dtype renames _Task.discriminant;
11776
11777 -- procedure _clean is
11778 -- begin
11779 -- Abort_Defer.all;
11780 -- Complete_Task;
11781 -- Abort_Undefer.all;
11782 -- return;
11783 -- end _clean;
11784
11785 -- begin
11786 -- Abort_Undefer.all;
11787 -- <declarations>
11788 -- System.Task_Stages.Complete_Activation;
11789 -- <statements>
11790 -- at end
11791 -- _clean;
11792 -- end tnameB;
11793
11794 -- tnameE := True;
11795
11796 -- In addition, if the task body is an activator, then a call to activate
11797 -- tasks is added at the start of the statements, before the call to
11798 -- Complete_Activation, and if in addition the task is a master then it
11799 -- must be established as a master. These calls are inserted and analyzed
11800 -- in Expand_Cleanup_Actions, when the Handled_Sequence_Of_Statements is
11801 -- expanded.
11802
11803 -- There is one discriminal declaration line generated for each
11804 -- discriminant that is present to provide an easy reference point for
11805 -- discriminant references inside the body (see Exp_Ch2.Expand_Name).
11806
11807 -- Note on relationship to GNARLI definition. In the GNARLI definition,
11808 -- task body procedures have a profile (Arg : System.Address). That is
11809 -- needed because GNARLI has to use the same access-to-subprogram type
11810 -- for all task types. We depend here on knowing that in GNAT, passing
11811 -- an address argument by value is identical to passing a record value
11812 -- by access (in either case a single pointer is passed), so even though
11813 -- this procedure has the wrong profile. In fact it's all OK, since the
11814 -- callings sequence is identical.
11815
11816 procedure Expand_N_Task_Body (N : Node_Id) is
11817 Loc : constant Source_Ptr := Sloc (N);
11818 Ttyp : constant Entity_Id := Corresponding_Spec (N);
11819 Call : Node_Id;
11820 New_N : Node_Id;
11821
11822 Insert_Nod : Node_Id;
11823 -- Used to determine the proper location of wrapper body insertions
11824
11825 begin
11826 -- if no task body procedure, means we had an error in configurable
11827 -- run-time mode, and there is no point in proceeding further.
11828
11829 if No (Task_Body_Procedure (Ttyp)) then
11830 return;
11831 end if;
11832
11833 -- Add renaming declarations for discriminals and a declaration for the
11834 -- entry family index (if applicable).
11835
11836 Install_Private_Data_Declarations
11837 (Loc, Task_Body_Procedure (Ttyp), Ttyp, N, Declarations (N));
11838
11839 -- Add a call to Abort_Undefer at the very beginning of the task
11840 -- body since this body is called with abort still deferred.
11841
11842 if Abort_Allowed then
11843 Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
11844 Insert_Before
11845 (First (Statements (Handled_Statement_Sequence (N))), Call);
11846 Analyze (Call);
11847 end if;
11848
11849 -- The statement part has already been protected with an at_end and
11850 -- cleanup actions. The call to Complete_Activation must be placed
11851 -- at the head of the sequence of statements of that block. The
11852 -- declarations have been merged in this sequence of statements but
11853 -- the first real statement is accessible from the First_Real_Statement
11854 -- field (which was set for exactly this purpose).
11855
11856 if Restricted_Profile then
11857 Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
11858 else
11859 Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
11860 end if;
11861
11862 Insert_Before
11863 (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
11864 Analyze (Call);
11865
11866 New_N :=
11867 Make_Subprogram_Body (Loc,
11868 Specification => Build_Task_Proc_Specification (Ttyp),
11869 Declarations => Declarations (N),
11870 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
11871 Set_Is_Task_Body_Procedure (New_N);
11872
11873 -- If the task contains generic instantiations, cleanup actions are
11874 -- delayed until after instantiation. Transfer the activation chain to
11875 -- the subprogram, to insure that the activation call is properly
11876 -- generated. It the task body contains inner tasks, indicate that the
11877 -- subprogram is a task master.
11878
11879 if Delay_Cleanups (Ttyp) then
11880 Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
11881 Set_Is_Task_Master (New_N, Is_Task_Master (N));
11882 end if;
11883
11884 Rewrite (N, New_N);
11885 Analyze (N);
11886
11887 -- Set elaboration flag immediately after task body. If the body is a
11888 -- subunit, the flag is set in the declarative part containing the stub.
11889
11890 if Nkind (Parent (N)) /= N_Subunit then
11891 Insert_After (N,
11892 Make_Assignment_Statement (Loc,
11893 Name =>
11894 Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
11895 Expression => New_Occurrence_Of (Standard_True, Loc)));
11896 end if;
11897
11898 -- Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
11899 -- the task body. At this point all wrapper specs have been created,
11900 -- frozen and included in the dispatch table for the task type.
11901
11902 if Ada_Version >= Ada_2005 then
11903 if Nkind (Parent (N)) = N_Subunit then
11904 Insert_Nod := Corresponding_Stub (Parent (N));
11905 else
11906 Insert_Nod := N;
11907 end if;
11908
11909 Build_Wrapper_Bodies (Loc, Ttyp, Insert_Nod);
11910 end if;
11911 end Expand_N_Task_Body;
11912
11913 ------------------------------------
11914 -- Expand_N_Task_Type_Declaration --
11915 ------------------------------------
11916
11917 -- We have several things to do. First we must create a Boolean flag used
11918 -- to mark if the body is elaborated yet. This variable gets set to True
11919 -- when the body of the task is elaborated (we can't rely on the normal
11920 -- ABE mechanism for the task body, since we need to pass an access to
11921 -- this elaboration boolean to the runtime routines).
11922
11923 -- taskE : aliased Boolean := False;
11924
11925 -- Next a variable is declared to hold the task stack size (either the
11926 -- default : Unspecified_Size, or a value that is set by a pragma
11927 -- Storage_Size). If the value of the pragma Storage_Size is static, then
11928 -- the variable is initialized with this value:
11929
11930 -- taskZ : Size_Type := Unspecified_Size;
11931 -- or
11932 -- taskZ : Size_Type := Size_Type (size_expression);
11933
11934 -- Note: No variable is needed to hold the task relative deadline since
11935 -- its value would never be static because the parameter is of a private
11936 -- type (Ada.Real_Time.Time_Span).
11937
11938 -- Next we create a corresponding record type declaration used to represent
11939 -- values of this task. The general form of this type declaration is
11940
11941 -- type taskV (discriminants) is record
11942 -- _Task_Id : Task_Id;
11943 -- entry_family : array (bounds) of Void;
11944 -- _Priority : Integer := priority_expression;
11945 -- _Size : Size_Type := size_expression;
11946 -- _Secondary_Stack_Size : Size_Type := size_expression;
11947 -- _Task_Info : Task_Info_Type := task_info_expression;
11948 -- _CPU : Integer := cpu_range_expression;
11949 -- _Relative_Deadline : Time_Span := time_span_expression;
11950 -- _Domain : Dispatching_Domain := dd_expression;
11951 -- end record;
11952
11953 -- The discriminants are present only if the corresponding task type has
11954 -- discriminants, and they exactly mirror the task type discriminants.
11955
11956 -- The Id field is always present. It contains the Task_Id value, as set by
11957 -- the call to Create_Task. Note that although the task is limited, the
11958 -- task value record type is not limited, so there is no problem in passing
11959 -- this field as an out parameter to Create_Task.
11960
11961 -- One entry_family component is present for each entry family in the task
11962 -- definition. The bounds correspond to the bounds of the entry family
11963 -- (which may depend on discriminants). The element type is void, since we
11964 -- only need the bounds information for determining the entry index. Note
11965 -- that the use of an anonymous array would normally be illegal in this
11966 -- context, but this is a parser check, and the semantics is quite prepared
11967 -- to handle such a case.
11968
11969 -- The _Size field is present only if a Storage_Size pragma appears in the
11970 -- task definition. The expression captures the argument that was present
11971 -- in the pragma, and is used to override the task stack size otherwise
11972 -- associated with the task type.
11973
11974 -- The _Secondary_Stack_Size field is present only the task entity has a
11975 -- Secondary_Stack_Size rep item. It will be filled at the freeze point,
11976 -- when the record init proc is built, to capture the expression of the
11977 -- rep item (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot
11978 -- be filled here since aspect evaluations are delayed till the freeze
11979 -- point.
11980
11981 -- The _Priority field is present only if the task entity has a Priority or
11982 -- Interrupt_Priority rep item (pragma, aspect specification or attribute
11983 -- definition clause). It will be filled at the freeze point, when the
11984 -- record init proc is built, to capture the expression of the rep item
11985 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11986 -- here since aspect evaluations are delayed till the freeze point.
11987
11988 -- The _Task_Info field is present only if a Task_Info pragma appears in
11989 -- the task definition. The expression captures the argument that was
11990 -- present in the pragma, and is used to provide the Task_Image parameter
11991 -- to the call to Create_Task.
11992
11993 -- The _CPU field is present only if the task entity has a CPU rep item
11994 -- (pragma, aspect specification or attribute definition clause). It will
11995 -- be filled at the freeze point, when the record init proc is built, to
11996 -- capture the expression of the rep item (see Build_Record_Init_Proc in
11997 -- Exp_Ch3). Note that it cannot be filled here since aspect evaluations
11998 -- are delayed till the freeze point.
11999
12000 -- The _Relative_Deadline field is present only if a Relative_Deadline
12001 -- pragma appears in the task definition. The expression captures the
12002 -- argument that was present in the pragma, and is used to provide the
12003 -- Relative_Deadline parameter to the call to Create_Task.
12004
12005 -- The _Domain field is present only if the task entity has a
12006 -- Dispatching_Domain rep item (pragma, aspect specification or attribute
12007 -- definition clause). It will be filled at the freeze point, when the
12008 -- record init proc is built, to capture the expression of the rep item
12009 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
12010 -- here since aspect evaluations are delayed till the freeze point.
12011
12012 -- When a task is declared, an instance of the task value record is
12013 -- created. The elaboration of this declaration creates the correct bounds
12014 -- for the entry families, and also evaluates the size, priority, and
12015 -- task_Info expressions if needed. The initialization routine for the task
12016 -- type itself then calls Create_Task with appropriate parameters to
12017 -- initialize the value of the Task_Id field.
12018
12019 -- Note: the address of this record is passed as the "Discriminants"
12020 -- parameter for Create_Task. Since Create_Task merely passes this onto the
12021 -- body procedure, it does not matter that it does not quite match the
12022 -- GNARLI model of what is being passed (the record contains more than just
12023 -- the discriminants, but the discriminants can be found from the record
12024 -- value).
12025
12026 -- The Entity_Id for this created record type is placed in the
12027 -- Corresponding_Record_Type field of the associated task type entity.
12028
12029 -- Next we create a procedure specification for the task body procedure:
12030
12031 -- procedure taskB (_Task : access taskV);
12032
12033 -- Note that this must come after the record type declaration, since
12034 -- the spec refers to this type. It turns out that the initialization
12035 -- procedure for the value type references the task body spec, but that's
12036 -- fine, since it won't be generated till the freeze point for the type,
12037 -- which is certainly after the task body spec declaration.
12038
12039 -- Finally, we set the task index value field of the entry attribute in
12040 -- the case of a simple entry.
12041
12042 procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
12043 Loc : constant Source_Ptr := Sloc (N);
12044 TaskId : constant Entity_Id := Defining_Identifier (N);
12045 Tasktyp : constant Entity_Id := Etype (Defining_Identifier (N));
12046 Tasknm : constant Name_Id := Chars (Tasktyp);
12047 Taskdef : constant Node_Id := Task_Definition (N);
12048
12049 Body_Decl : Node_Id;
12050 Cdecls : List_Id;
12051 Decl_Stack : Node_Id;
12052 Decl_SS : Node_Id;
12053 Elab_Decl : Node_Id;
12054 Ent_Stack : Entity_Id;
12055 Proc_Spec : Node_Id;
12056 Rec_Decl : Node_Id;
12057 Rec_Ent : Entity_Id;
12058 Size_Decl : Entity_Id;
12059 Task_Size : Node_Id;
12060
12061 function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id;
12062 -- Searches the task definition T for the first occurrence of the pragma
12063 -- Relative Deadline. The caller has ensured that the pragma is present
12064 -- in the task definition. Note that this routine cannot be implemented
12065 -- with the Rep Item chain mechanism since Relative_Deadline pragmas are
12066 -- not chained because their expansion into a procedure call statement
12067 -- would cause a break in the chain.
12068
12069 ----------------------------------
12070 -- Get_Relative_Deadline_Pragma --
12071 ----------------------------------
12072
12073 function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id is
12074 N : Node_Id;
12075
12076 begin
12077 N := First (Visible_Declarations (T));
12078 while Present (N) loop
12079 if Nkind (N) = N_Pragma
12080 and then Pragma_Name (N) = Name_Relative_Deadline
12081 then
12082 return N;
12083 end if;
12084
12085 Next (N);
12086 end loop;
12087
12088 N := First (Private_Declarations (T));
12089 while Present (N) loop
12090 if Nkind (N) = N_Pragma
12091 and then Pragma_Name (N) = Name_Relative_Deadline
12092 then
12093 return N;
12094 end if;
12095
12096 Next (N);
12097 end loop;
12098
12099 raise Program_Error;
12100 end Get_Relative_Deadline_Pragma;
12101
12102 -- Start of processing for Expand_N_Task_Type_Declaration
12103
12104 begin
12105 -- If already expanded, nothing to do
12106
12107 if Present (Corresponding_Record_Type (Tasktyp)) then
12108 return;
12109 end if;
12110
12111 -- Here we will do the expansion
12112
12113 Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
12114
12115 Rec_Ent := Defining_Identifier (Rec_Decl);
12116 Cdecls := Component_Items (Component_List
12117 (Type_Definition (Rec_Decl)));
12118
12119 Qualify_Entity_Names (N);
12120
12121 -- First create the elaboration variable
12122
12123 Elab_Decl :=
12124 Make_Object_Declaration (Loc,
12125 Defining_Identifier =>
12126 Make_Defining_Identifier (Sloc (Tasktyp),
12127 Chars => New_External_Name (Tasknm, 'E')),
12128 Aliased_Present => True,
12129 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
12130 Expression => New_Occurrence_Of (Standard_False, Loc));
12131
12132 Insert_After (N, Elab_Decl);
12133
12134 -- Next create the declaration of the size variable (tasknmZ)
12135
12136 Set_Storage_Size_Variable (Tasktyp,
12137 Make_Defining_Identifier (Sloc (Tasktyp),
12138 Chars => New_External_Name (Tasknm, 'Z')));
12139
12140 if Present (Taskdef)
12141 and then Has_Storage_Size_Pragma (Taskdef)
12142 and then
12143 Is_OK_Static_Expression
12144 (Expression
12145 (First (Pragma_Argument_Associations
12146 (Get_Rep_Pragma (TaskId, Name_Storage_Size)))))
12147 then
12148 Size_Decl :=
12149 Make_Object_Declaration (Loc,
12150 Defining_Identifier => Storage_Size_Variable (Tasktyp),
12151 Object_Definition =>
12152 New_Occurrence_Of (RTE (RE_Size_Type), Loc),
12153 Expression =>
12154 Convert_To (RTE (RE_Size_Type),
12155 Relocate_Node
12156 (Expression (First (Pragma_Argument_Associations
12157 (Get_Rep_Pragma
12158 (TaskId, Name_Storage_Size)))))));
12159
12160 else
12161 Size_Decl :=
12162 Make_Object_Declaration (Loc,
12163 Defining_Identifier => Storage_Size_Variable (Tasktyp),
12164 Object_Definition =>
12165 New_Occurrence_Of (RTE (RE_Size_Type), Loc),
12166 Expression =>
12167 New_Occurrence_Of (RTE (RE_Unspecified_Size), Loc));
12168 end if;
12169
12170 Insert_After (Elab_Decl, Size_Decl);
12171
12172 -- Next build the rest of the corresponding record declaration. This is
12173 -- done last, since the corresponding record initialization procedure
12174 -- will reference the previously created entities.
12175
12176 -- Fill in the component declarations -- first the _Task_Id field
12177
12178 Append_To (Cdecls,
12179 Make_Component_Declaration (Loc,
12180 Defining_Identifier =>
12181 Make_Defining_Identifier (Loc, Name_uTask_Id),
12182 Component_Definition =>
12183 Make_Component_Definition (Loc,
12184 Aliased_Present => False,
12185 Subtype_Indication => New_Occurrence_Of (RTE (RO_ST_Task_Id),
12186 Loc))));
12187
12188 -- Declare static ATCB (that is, created by the expander) if we are
12189 -- using the Restricted run time.
12190
12191 if Restricted_Profile then
12192 Append_To (Cdecls,
12193 Make_Component_Declaration (Loc,
12194 Defining_Identifier =>
12195 Make_Defining_Identifier (Loc, Name_uATCB),
12196
12197 Component_Definition =>
12198 Make_Component_Definition (Loc,
12199 Aliased_Present => True,
12200 Subtype_Indication => Make_Subtype_Indication (Loc,
12201 Subtype_Mark =>
12202 New_Occurrence_Of (RTE (RE_Ada_Task_Control_Block), Loc),
12203
12204 Constraint =>
12205 Make_Index_Or_Discriminant_Constraint (Loc,
12206 Constraints =>
12207 New_List (Make_Integer_Literal (Loc, 0)))))));
12208
12209 end if;
12210
12211 -- Declare static stack (that is, created by the expander) if we are
12212 -- using the Restricted run time on a bare board configuration.
12213
12214 if Restricted_Profile and then Preallocated_Stacks_On_Target then
12215
12216 -- First we need to extract the appropriate stack size
12217
12218 Ent_Stack := Make_Defining_Identifier (Loc, Name_uStack);
12219
12220 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
12221 declare
12222 Expr_N : constant Node_Id :=
12223 Expression (First (
12224 Pragma_Argument_Associations (
12225 Get_Rep_Pragma (TaskId, Name_Storage_Size))));
12226 Etyp : constant Entity_Id := Etype (Expr_N);
12227 P : constant Node_Id := Parent (Expr_N);
12228
12229 begin
12230 -- The stack is defined inside the corresponding record.
12231 -- Therefore if the size of the stack is set by means of
12232 -- a discriminant, we must reference the discriminant of the
12233 -- corresponding record type.
12234
12235 if Nkind (Expr_N) in N_Has_Entity
12236 and then Present (Discriminal_Link (Entity (Expr_N)))
12237 then
12238 Task_Size :=
12239 New_Occurrence_Of
12240 (CR_Discriminant (Discriminal_Link (Entity (Expr_N))),
12241 Loc);
12242 Set_Parent (Task_Size, P);
12243 Set_Etype (Task_Size, Etyp);
12244 Set_Analyzed (Task_Size);
12245
12246 else
12247 Task_Size := New_Copy_Tree (Expr_N);
12248 end if;
12249 end;
12250
12251 else
12252 Task_Size :=
12253 New_Occurrence_Of (RTE (RE_Default_Stack_Size), Loc);
12254 end if;
12255
12256 Decl_Stack := Make_Component_Declaration (Loc,
12257 Defining_Identifier => Ent_Stack,
12258
12259 Component_Definition =>
12260 Make_Component_Definition (Loc,
12261 Aliased_Present => True,
12262 Subtype_Indication => Make_Subtype_Indication (Loc,
12263 Subtype_Mark =>
12264 New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
12265
12266 Constraint =>
12267 Make_Index_Or_Discriminant_Constraint (Loc,
12268 Constraints => New_List (Make_Range (Loc,
12269 Low_Bound => Make_Integer_Literal (Loc, 1),
12270 High_Bound => Convert_To (RTE (RE_Storage_Offset),
12271 Task_Size)))))));
12272
12273 Append_To (Cdecls, Decl_Stack);
12274
12275 -- The appropriate alignment for the stack is ensured by the run-time
12276 -- code in charge of task creation.
12277
12278 end if;
12279
12280 -- Declare a static secondary stack if the conditions for a statically
12281 -- generated stack are met.
12282
12283 if Create_Secondary_Stack_For_Task (TaskId) then
12284 declare
12285 Size_Expr : constant Node_Id :=
12286 Expression (First (
12287 Pragma_Argument_Associations (
12288 Get_Rep_Pragma (TaskId,
12289 Name_Secondary_Stack_Size))));
12290
12291 Stack_Size : Node_Id;
12292
12293 begin
12294 -- The secondary stack is defined inside the corresponding
12295 -- record. Therefore if the size of the stack is set by means
12296 -- of a discriminant, we must reference the discriminant of the
12297 -- corresponding record type.
12298
12299 if Nkind (Size_Expr) in N_Has_Entity
12300 and then Present (Discriminal_Link (Entity (Size_Expr)))
12301 then
12302 Stack_Size :=
12303 New_Occurrence_Of
12304 (CR_Discriminant (Discriminal_Link (Entity (Size_Expr))),
12305 Loc);
12306 Set_Parent (Stack_Size, Parent (Size_Expr));
12307 Set_Etype (Stack_Size, Etype (Size_Expr));
12308 Set_Analyzed (Stack_Size);
12309
12310 else
12311 Stack_Size := New_Copy_Tree (Size_Expr);
12312 end if;
12313
12314 -- Create the secondary stack for the task
12315
12316 Decl_SS :=
12317 Make_Component_Declaration (Loc,
12318 Defining_Identifier =>
12319 Make_Defining_Identifier (Loc, Name_uSecondary_Stack),
12320 Component_Definition =>
12321 Make_Component_Definition (Loc,
12322 Aliased_Present => True,
12323 Subtype_Indication =>
12324 Make_Subtype_Indication (Loc,
12325 Subtype_Mark =>
12326 New_Occurrence_Of (RTE (RE_SS_Stack), Loc),
12327 Constraint =>
12328 Make_Index_Or_Discriminant_Constraint (Loc,
12329 Constraints => New_List (
12330 Convert_To (RTE (RE_Size_Type),
12331 Stack_Size))))));
12332
12333 Append_To (Cdecls, Decl_SS);
12334 end;
12335 end if;
12336
12337 -- Add components for entry families
12338
12339 Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
12340
12341 -- Add the _Priority component if a Interrupt_Priority or Priority rep
12342 -- item is present.
12343
12344 if Has_Rep_Item (TaskId, Name_Priority, Check_Parents => False) then
12345 Append_To (Cdecls,
12346 Make_Component_Declaration (Loc,
12347 Defining_Identifier =>
12348 Make_Defining_Identifier (Loc, Name_uPriority),
12349 Component_Definition =>
12350 Make_Component_Definition (Loc,
12351 Aliased_Present => False,
12352 Subtype_Indication =>
12353 New_Occurrence_Of (Standard_Integer, Loc))));
12354 end if;
12355
12356 -- Add the _Size component if a Storage_Size pragma is present
12357
12358 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
12359 Append_To (Cdecls,
12360 Make_Component_Declaration (Loc,
12361 Defining_Identifier =>
12362 Make_Defining_Identifier (Loc, Name_uSize),
12363
12364 Component_Definition =>
12365 Make_Component_Definition (Loc,
12366 Aliased_Present => False,
12367 Subtype_Indication =>
12368 New_Occurrence_Of (RTE (RE_Size_Type), Loc)),
12369
12370 Expression =>
12371 Convert_To (RTE (RE_Size_Type),
12372 New_Copy_Tree (
12373 Expression (First (
12374 Pragma_Argument_Associations (
12375 Get_Rep_Pragma (TaskId, Name_Storage_Size))))))));
12376 end if;
12377
12378 -- Add the _Secondary_Stack_Size component if a Secondary_Stack_Size
12379 -- pragma is present.
12380
12381 if Has_Rep_Pragma
12382 (TaskId, Name_Secondary_Stack_Size, Check_Parents => False)
12383 then
12384 Append_To (Cdecls,
12385 Make_Component_Declaration (Loc,
12386 Defining_Identifier =>
12387 Make_Defining_Identifier (Loc, Name_uSecondary_Stack_Size),
12388
12389 Component_Definition =>
12390 Make_Component_Definition (Loc,
12391 Aliased_Present => False,
12392 Subtype_Indication =>
12393 New_Occurrence_Of (RTE (RE_Size_Type), Loc))));
12394 end if;
12395
12396 -- Add the _Task_Info component if a Task_Info pragma is present
12397
12398 if Has_Rep_Pragma (TaskId, Name_Task_Info, Check_Parents => False) then
12399 Append_To (Cdecls,
12400 Make_Component_Declaration (Loc,
12401 Defining_Identifier =>
12402 Make_Defining_Identifier (Loc, Name_uTask_Info),
12403
12404 Component_Definition =>
12405 Make_Component_Definition (Loc,
12406 Aliased_Present => False,
12407 Subtype_Indication =>
12408 New_Occurrence_Of (RTE (RE_Task_Info_Type), Loc)),
12409
12410 Expression => New_Copy (
12411 Expression (First (
12412 Pragma_Argument_Associations (
12413 Get_Rep_Pragma
12414 (TaskId, Name_Task_Info, Check_Parents => False)))))));
12415 end if;
12416
12417 -- Add the _CPU component if a CPU rep item is present
12418
12419 if Has_Rep_Item (TaskId, Name_CPU, Check_Parents => False) then
12420 Append_To (Cdecls,
12421 Make_Component_Declaration (Loc,
12422 Defining_Identifier =>
12423 Make_Defining_Identifier (Loc, Name_uCPU),
12424
12425 Component_Definition =>
12426 Make_Component_Definition (Loc,
12427 Aliased_Present => False,
12428 Subtype_Indication =>
12429 New_Occurrence_Of (RTE (RE_CPU_Range), Loc))));
12430 end if;
12431
12432 -- Add the _Relative_Deadline component if a Relative_Deadline pragma is
12433 -- present. If we are using a restricted run time this component will
12434 -- not be added (deadlines are not allowed by the Ravenscar profile),
12435 -- unless the task dispatching policy is EDF (for GNAT_Ravenscar_EDF
12436 -- profile).
12437
12438 if (not Restricted_Profile or else Task_Dispatching_Policy = 'E')
12439 and then Present (Taskdef)
12440 and then Has_Relative_Deadline_Pragma (Taskdef)
12441 then
12442 Append_To (Cdecls,
12443 Make_Component_Declaration (Loc,
12444 Defining_Identifier =>
12445 Make_Defining_Identifier (Loc, Name_uRelative_Deadline),
12446
12447 Component_Definition =>
12448 Make_Component_Definition (Loc,
12449 Aliased_Present => False,
12450 Subtype_Indication =>
12451 New_Occurrence_Of (RTE (RE_Time_Span), Loc)),
12452
12453 Expression =>
12454 Convert_To (RTE (RE_Time_Span),
12455 New_Copy_Tree (
12456 Expression (First (
12457 Pragma_Argument_Associations (
12458 Get_Relative_Deadline_Pragma (Taskdef))))))));
12459 end if;
12460
12461 -- Add the _Dispatching_Domain component if a Dispatching_Domain rep
12462 -- item is present. If we are using a restricted run time this component
12463 -- will not be added (dispatching domains are not allowed by the
12464 -- Ravenscar profile).
12465
12466 if not Restricted_Profile
12467 and then
12468 Has_Rep_Item
12469 (TaskId, Name_Dispatching_Domain, Check_Parents => False)
12470 then
12471 Append_To (Cdecls,
12472 Make_Component_Declaration (Loc,
12473 Defining_Identifier =>
12474 Make_Defining_Identifier (Loc, Name_uDispatching_Domain),
12475
12476 Component_Definition =>
12477 Make_Component_Definition (Loc,
12478 Aliased_Present => False,
12479 Subtype_Indication =>
12480 New_Occurrence_Of
12481 (RTE (RE_Dispatching_Domain_Access), Loc))));
12482 end if;
12483
12484 Insert_After (Size_Decl, Rec_Decl);
12485
12486 -- Analyze the record declaration immediately after construction,
12487 -- because the initialization procedure is needed for single task
12488 -- declarations before the next entity is analyzed.
12489
12490 Analyze (Rec_Decl);
12491
12492 -- Create the declaration of the task body procedure
12493
12494 Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
12495 Body_Decl :=
12496 Make_Subprogram_Declaration (Loc,
12497 Specification => Proc_Spec);
12498 Set_Is_Task_Body_Procedure (Body_Decl);
12499
12500 Insert_After (Rec_Decl, Body_Decl);
12501
12502 -- The subprogram does not comes from source, so we have to indicate the
12503 -- need for debugging information explicitly.
12504
12505 if Comes_From_Source (Original_Node (N)) then
12506 Set_Debug_Info_Needed (Defining_Entity (Proc_Spec));
12507 end if;
12508
12509 -- Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
12510 -- the corresponding record has been frozen.
12511
12512 if Ada_Version >= Ada_2005 then
12513 Build_Wrapper_Specs (Loc, Tasktyp, Rec_Decl);
12514 end if;
12515
12516 -- Ada 2005 (AI-345): We must defer freezing to allow further
12517 -- declaration of primitive subprograms covering task interfaces
12518
12519 if Ada_Version <= Ada_95 then
12520
12521 -- Now we can freeze the corresponding record. This needs manually
12522 -- freezing, since it is really part of the task type, and the task
12523 -- type is frozen at this stage. We of course need the initialization
12524 -- procedure for this corresponding record type and we won't get it
12525 -- in time if we don't freeze now.
12526
12527 declare
12528 L : constant List_Id := Freeze_Entity (Rec_Ent, N);
12529 begin
12530 if Is_Non_Empty_List (L) then
12531 Insert_List_After (Body_Decl, L);
12532 end if;
12533 end;
12534 end if;
12535
12536 -- Complete the expansion of access types to the current task type, if
12537 -- any were declared.
12538
12539 Expand_Previous_Access_Type (Tasktyp);
12540
12541 -- Create wrappers for entries that have contract cases, preconditions
12542 -- and postconditions.
12543
12544 declare
12545 Ent : Entity_Id;
12546
12547 begin
12548 Ent := First_Entity (Tasktyp);
12549 while Present (Ent) loop
12550 if Ekind (Ent) in E_Entry | E_Entry_Family then
12551 Build_Contract_Wrapper (Ent, N);
12552 end if;
12553
12554 Next_Entity (Ent);
12555 end loop;
12556 end;
12557 end Expand_N_Task_Type_Declaration;
12558
12559 -------------------------------
12560 -- Expand_N_Timed_Entry_Call --
12561 -------------------------------
12562
12563 -- A timed entry call in normal case is not implemented using ATC mechanism
12564 -- anymore for efficiency reason.
12565
12566 -- select
12567 -- T.E;
12568 -- S1;
12569 -- or
12570 -- delay D;
12571 -- S2;
12572 -- end select;
12573
12574 -- is expanded as follows:
12575
12576 -- 1) When T.E is a task entry_call;
12577
12578 -- declare
12579 -- B : Boolean;
12580 -- X : Task_Entry_Index := <entry index>;
12581 -- DX : Duration := To_Duration (D);
12582 -- M : Delay_Mode := <discriminant>;
12583 -- P : parms := (parm, parm, parm);
12584
12585 -- begin
12586 -- Timed_Protected_Entry_Call
12587 -- (<acceptor-task>, X, P'Address, DX, M, B);
12588 -- if B then
12589 -- S1;
12590 -- else
12591 -- S2;
12592 -- end if;
12593 -- end;
12594
12595 -- 2) When T.E is a protected entry_call;
12596
12597 -- declare
12598 -- B : Boolean;
12599 -- X : Protected_Entry_Index := <entry index>;
12600 -- DX : Duration := To_Duration (D);
12601 -- M : Delay_Mode := <discriminant>;
12602 -- P : parms := (parm, parm, parm);
12603
12604 -- begin
12605 -- Timed_Protected_Entry_Call
12606 -- (<object>'unchecked_access, X, P'Address, DX, M, B);
12607 -- if B then
12608 -- S1;
12609 -- else
12610 -- S2;
12611 -- end if;
12612 -- end;
12613
12614 -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call, there
12615 -- is no delay and the triggering statements are executed. We first
12616 -- determine the kind of the triggering call and then execute a
12617 -- synchronized operation or a direct call.
12618
12619 -- declare
12620 -- B : Boolean := False;
12621 -- C : Ada.Tags.Prim_Op_Kind;
12622 -- DX : Duration := To_Duration (D)
12623 -- K : Ada.Tags.Tagged_Kind :=
12624 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
12625 -- M : Integer :=...;
12626 -- P : Parameters := (Param1 .. ParamN);
12627 -- S : Integer;
12628
12629 -- begin
12630 -- if K = Ada.Tags.TK_Limited_Tagged
12631 -- or else K = Ada.Tags.TK_Tagged
12632 -- then
12633 -- <dispatching-call>;
12634 -- B := True;
12635
12636 -- else
12637 -- S :=
12638 -- Ada.Tags.Get_Offset_Index
12639 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
12640
12641 -- _Disp_Timed_Select (<object>, S, P'Address, DX, M, C, B);
12642
12643 -- if C = POK_Protected_Entry
12644 -- or else C = POK_Task_Entry
12645 -- then
12646 -- Param1 := P.Param1;
12647 -- ...
12648 -- ParamN := P.ParamN;
12649 -- end if;
12650
12651 -- if B then
12652 -- if C = POK_Procedure
12653 -- or else C = POK_Protected_Procedure
12654 -- or else C = POK_Task_Procedure
12655 -- then
12656 -- <dispatching-call>;
12657 -- end if;
12658 -- end if;
12659 -- end if;
12660
12661 -- if B then
12662 -- <triggering-statements>
12663 -- else
12664 -- <timed-statements>
12665 -- end if;
12666 -- end;
12667
12668 -- The triggering statement and the sequence of timed statements have not
12669 -- been analyzed yet (see Analyzed_Timed_Entry_Call), but they may contain
12670 -- global references if within an instantiation.
12671
12672 procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
12673 Actuals : List_Id;
12674 Blk_Typ : Entity_Id;
12675 Call : Node_Id;
12676 Call_Ent : Entity_Id;
12677 Conc_Typ_Stmts : List_Id;
12678 Concval : Node_Id := Empty; -- init to avoid warning
12679 D_Alt : constant Node_Id := Delay_Alternative (N);
12680 D_Conv : Node_Id;
12681 D_Disc : Node_Id;
12682 D_Stat : Node_Id := Delay_Statement (D_Alt);
12683 D_Stats : List_Id;
12684 D_Type : Entity_Id;
12685 Decls : List_Id;
12686 Dummy : Node_Id;
12687 E_Alt : constant Node_Id := Entry_Call_Alternative (N);
12688 E_Call : Node_Id := Entry_Call_Statement (E_Alt);
12689 E_Stats : List_Id;
12690 Ename : Node_Id;
12691 Formals : List_Id;
12692 Index : Node_Id;
12693 Is_Disp_Select : Boolean;
12694 Lim_Typ_Stmts : List_Id;
12695 Loc : constant Source_Ptr := Sloc (D_Stat);
12696 N_Stats : List_Id;
12697 Obj : Entity_Id;
12698 Param : Node_Id;
12699 Params : List_Id;
12700 Stmt : Node_Id;
12701 Stmts : List_Id;
12702 Unpack : List_Id;
12703
12704 B : Entity_Id; -- Call status flag
12705 C : Entity_Id; -- Call kind
12706 D : Entity_Id; -- Delay
12707 K : Entity_Id; -- Tagged kind
12708 M : Entity_Id; -- Delay mode
12709 P : Entity_Id; -- Parameter block
12710 S : Entity_Id; -- Primitive operation slot
12711
12712 -- Start of processing for Expand_N_Timed_Entry_Call
12713
12714 begin
12715 -- Under the Ravenscar profile, timed entry calls are excluded. An error
12716 -- was already reported on spec, so do not attempt to expand the call.
12717
12718 if Restriction_Active (No_Select_Statements) then
12719 return;
12720 end if;
12721
12722 Process_Statements_For_Controlled_Objects (E_Alt);
12723 Process_Statements_For_Controlled_Objects (D_Alt);
12724
12725 Ensure_Statement_Present (Sloc (D_Stat), D_Alt);
12726
12727 -- Retrieve E_Stats and D_Stats now because the finalization machinery
12728 -- may wrap them in blocks.
12729
12730 E_Stats := Statements (E_Alt);
12731 D_Stats := Statements (D_Alt);
12732
12733 -- The arguments in the call may require dynamic allocation, and the
12734 -- call statement may have been transformed into a block. The block
12735 -- may contain additional declarations for internal entities, and the
12736 -- original call is found by sequential search.
12737
12738 if Nkind (E_Call) = N_Block_Statement then
12739 E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
12740 while Nkind (E_Call) not in
12741 N_Procedure_Call_Statement | N_Entry_Call_Statement
12742 loop
12743 Next (E_Call);
12744 end loop;
12745 end if;
12746
12747 Is_Disp_Select :=
12748 Ada_Version >= Ada_2005
12749 and then Nkind (E_Call) = N_Procedure_Call_Statement;
12750
12751 if Is_Disp_Select then
12752 Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
12753 Decls := New_List;
12754
12755 Stmts := New_List;
12756
12757 -- Generate:
12758 -- B : Boolean := False;
12759
12760 B := Build_B (Loc, Decls);
12761
12762 -- Generate:
12763 -- C : Ada.Tags.Prim_Op_Kind;
12764
12765 C := Build_C (Loc, Decls);
12766
12767 -- Because the analysis of all statements was disabled, manually
12768 -- analyze the delay statement.
12769
12770 Analyze (D_Stat);
12771 D_Stat := Original_Node (D_Stat);
12772
12773 else
12774 -- Build an entry call using Simple_Entry_Call
12775
12776 Extract_Entry (E_Call, Concval, Ename, Index);
12777 Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
12778
12779 Decls := Declarations (E_Call);
12780 Stmts := Statements (Handled_Statement_Sequence (E_Call));
12781
12782 if No (Decls) then
12783 Decls := New_List;
12784 end if;
12785
12786 -- Generate:
12787 -- B : Boolean;
12788
12789 B := Make_Defining_Identifier (Loc, Name_uB);
12790
12791 Prepend_To (Decls,
12792 Make_Object_Declaration (Loc,
12793 Defining_Identifier => B,
12794 Object_Definition =>
12795 New_Occurrence_Of (Standard_Boolean, Loc)));
12796 end if;
12797
12798 -- Duration and mode processing
12799
12800 D_Type := Base_Type (Etype (Expression (D_Stat)));
12801
12802 -- Use the type of the delay expression (Calendar or Real_Time) to
12803 -- generate the appropriate conversion.
12804
12805 if Nkind (D_Stat) = N_Delay_Relative_Statement then
12806 D_Disc := Make_Integer_Literal (Loc, 0);
12807 D_Conv := Relocate_Node (Expression (D_Stat));
12808
12809 elsif Is_RTE (D_Type, RO_CA_Time) then
12810 D_Disc := Make_Integer_Literal (Loc, 1);
12811 D_Conv :=
12812 Make_Function_Call (Loc,
12813 Name => New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
12814 Parameter_Associations =>
12815 New_List (New_Copy (Expression (D_Stat))));
12816
12817 else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
12818 D_Disc := Make_Integer_Literal (Loc, 2);
12819 D_Conv :=
12820 Make_Function_Call (Loc,
12821 Name => New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
12822 Parameter_Associations =>
12823 New_List (New_Copy (Expression (D_Stat))));
12824 end if;
12825
12826 D := Make_Temporary (Loc, 'D');
12827
12828 -- Generate:
12829 -- D : Duration;
12830
12831 Append_To (Decls,
12832 Make_Object_Declaration (Loc,
12833 Defining_Identifier => D,
12834 Object_Definition => New_Occurrence_Of (Standard_Duration, Loc)));
12835
12836 M := Make_Temporary (Loc, 'M');
12837
12838 -- Generate:
12839 -- M : Integer := (0 | 1 | 2);
12840
12841 Append_To (Decls,
12842 Make_Object_Declaration (Loc,
12843 Defining_Identifier => M,
12844 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
12845 Expression => D_Disc));
12846
12847 -- Parameter block processing
12848
12849 -- Manually create the parameter block for dispatching calls. In the
12850 -- case of entries, the block has already been created during the call
12851 -- to Build_Simple_Entry_Call.
12852
12853 if Is_Disp_Select then
12854
12855 -- Compute the delay at this stage because the evaluation of its
12856 -- expression must not occur earlier (see ACVC C97302A).
12857
12858 Append_To (Stmts,
12859 Make_Assignment_Statement (Loc,
12860 Name => New_Occurrence_Of (D, Loc),
12861 Expression => D_Conv));
12862
12863 -- Tagged kind processing, generate:
12864 -- K : Ada.Tags.Tagged_Kind :=
12865 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag <object>));
12866
12867 K := Build_K (Loc, Decls, Obj);
12868
12869 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
12870 P :=
12871 Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
12872
12873 -- Dispatch table slot processing, generate:
12874 -- S : Integer;
12875
12876 S := Build_S (Loc, Decls);
12877
12878 -- Generate:
12879 -- S := Ada.Tags.Get_Offset_Index
12880 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
12881
12882 Conc_Typ_Stmts :=
12883 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
12884
12885 -- Generate:
12886 -- _Disp_Timed_Select (<object>, S, P'Address, D, M, C, B);
12887
12888 -- where Obj is the controlling formal parameter, S is the dispatch
12889 -- table slot number of the dispatching operation, P is the wrapped
12890 -- parameter block, D is the duration, M is the duration mode, C is
12891 -- the call kind and B is the call status.
12892
12893 Params := New_List;
12894
12895 Append_To (Params, New_Copy_Tree (Obj));
12896 Append_To (Params, New_Occurrence_Of (S, Loc));
12897 Append_To (Params,
12898 Make_Attribute_Reference (Loc,
12899 Prefix => New_Occurrence_Of (P, Loc),
12900 Attribute_Name => Name_Address));
12901 Append_To (Params, New_Occurrence_Of (D, Loc));
12902 Append_To (Params, New_Occurrence_Of (M, Loc));
12903 Append_To (Params, New_Occurrence_Of (C, Loc));
12904 Append_To (Params, New_Occurrence_Of (B, Loc));
12905
12906 Append_To (Conc_Typ_Stmts,
12907 Make_Procedure_Call_Statement (Loc,
12908 Name =>
12909 New_Occurrence_Of
12910 (Find_Prim_Op
12911 (Etype (Etype (Obj)), Name_uDisp_Timed_Select), Loc),
12912 Parameter_Associations => Params));
12913
12914 -- Generate:
12915 -- if C = POK_Protected_Entry
12916 -- or else C = POK_Task_Entry
12917 -- then
12918 -- Param1 := P.Param1;
12919 -- ...
12920 -- ParamN := P.ParamN;
12921 -- end if;
12922
12923 Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
12924
12925 -- Generate the if statement only when the packed parameters need
12926 -- explicit assignments to their corresponding actuals.
12927
12928 if Present (Unpack) then
12929 Append_To (Conc_Typ_Stmts,
12930 Make_Implicit_If_Statement (N,
12931
12932 Condition =>
12933 Make_Or_Else (Loc,
12934 Left_Opnd =>
12935 Make_Op_Eq (Loc,
12936 Left_Opnd => New_Occurrence_Of (C, Loc),
12937 Right_Opnd =>
12938 New_Occurrence_Of
12939 (RTE (RE_POK_Protected_Entry), Loc)),
12940
12941 Right_Opnd =>
12942 Make_Op_Eq (Loc,
12943 Left_Opnd => New_Occurrence_Of (C, Loc),
12944 Right_Opnd =>
12945 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
12946
12947 Then_Statements => Unpack));
12948 end if;
12949
12950 -- Generate:
12951
12952 -- if B then
12953 -- if C = POK_Procedure
12954 -- or else C = POK_Protected_Procedure
12955 -- or else C = POK_Task_Procedure
12956 -- then
12957 -- <dispatching-call>
12958 -- end if;
12959 -- end if;
12960
12961 N_Stats := New_List (
12962 Make_Implicit_If_Statement (N,
12963 Condition =>
12964 Make_Or_Else (Loc,
12965 Left_Opnd =>
12966 Make_Op_Eq (Loc,
12967 Left_Opnd => New_Occurrence_Of (C, Loc),
12968 Right_Opnd =>
12969 New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
12970
12971 Right_Opnd =>
12972 Make_Or_Else (Loc,
12973 Left_Opnd =>
12974 Make_Op_Eq (Loc,
12975 Left_Opnd => New_Occurrence_Of (C, Loc),
12976 Right_Opnd =>
12977 New_Occurrence_Of (RTE (
12978 RE_POK_Protected_Procedure), Loc)),
12979 Right_Opnd =>
12980 Make_Op_Eq (Loc,
12981 Left_Opnd => New_Occurrence_Of (C, Loc),
12982 Right_Opnd =>
12983 New_Occurrence_Of
12984 (RTE (RE_POK_Task_Procedure), Loc)))),
12985
12986 Then_Statements => New_List (E_Call)));
12987
12988 Append_To (Conc_Typ_Stmts,
12989 Make_Implicit_If_Statement (N,
12990 Condition => New_Occurrence_Of (B, Loc),
12991 Then_Statements => N_Stats));
12992
12993 -- Generate:
12994 -- <dispatching-call>;
12995 -- B := True;
12996
12997 Lim_Typ_Stmts :=
12998 New_List (New_Copy_Tree (E_Call),
12999 Make_Assignment_Statement (Loc,
13000 Name => New_Occurrence_Of (B, Loc),
13001 Expression => New_Occurrence_Of (Standard_True, Loc)));
13002
13003 -- Generate:
13004 -- if K = Ada.Tags.TK_Limited_Tagged
13005 -- or else K = Ada.Tags.TK_Tagged
13006 -- then
13007 -- Lim_Typ_Stmts
13008 -- else
13009 -- Conc_Typ_Stmts
13010 -- end if;
13011
13012 Append_To (Stmts,
13013 Make_Implicit_If_Statement (N,
13014 Condition => Build_Dispatching_Tag_Check (K, N),
13015 Then_Statements => Lim_Typ_Stmts,
13016 Else_Statements => Conc_Typ_Stmts));
13017
13018 -- Generate:
13019
13020 -- if B then
13021 -- <triggering-statements>
13022 -- else
13023 -- <timed-statements>
13024 -- end if;
13025
13026 Append_To (Stmts,
13027 Make_Implicit_If_Statement (N,
13028 Condition => New_Occurrence_Of (B, Loc),
13029 Then_Statements => E_Stats,
13030 Else_Statements => D_Stats));
13031
13032 else
13033 -- Simple case of a nondispatching trigger. Skip assignments to
13034 -- temporaries created for in-out parameters.
13035
13036 -- This makes unwarranted assumptions about the shape of the expanded
13037 -- tree for the call, and should be cleaned up ???
13038
13039 Stmt := First (Stmts);
13040 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
13041 Next (Stmt);
13042 end loop;
13043
13044 -- Compute the delay at this stage because the evaluation of
13045 -- its expression must not occur earlier (see ACVC C97302A).
13046
13047 Insert_Before (Stmt,
13048 Make_Assignment_Statement (Loc,
13049 Name => New_Occurrence_Of (D, Loc),
13050 Expression => D_Conv));
13051
13052 Call := Stmt;
13053 Params := Parameter_Associations (Call);
13054
13055 -- For a protected type, we build a Timed_Protected_Entry_Call
13056
13057 if Is_Protected_Type (Etype (Concval)) then
13058
13059 -- Create a new call statement
13060
13061 Param := First (Params);
13062 while Present (Param)
13063 and then not Is_RTE (Etype (Param), RE_Call_Modes)
13064 loop
13065 Next (Param);
13066 end loop;
13067
13068 Dummy := Remove_Next (Next (Param));
13069
13070 -- Remove garbage is following the Cancel_Param if present
13071
13072 Dummy := Next (Param);
13073
13074 -- Remove the mode of the Protected_Entry_Call call, then remove
13075 -- the Communication_Block of the Protected_Entry_Call call, and
13076 -- finally add Duration and a Delay_Mode parameter
13077
13078 pragma Assert (Present (Param));
13079 Rewrite (Param, New_Occurrence_Of (D, Loc));
13080
13081 Rewrite (Dummy, New_Occurrence_Of (M, Loc));
13082
13083 -- Add a Boolean flag for successful entry call
13084
13085 Append_To (Params, New_Occurrence_Of (B, Loc));
13086
13087 case Corresponding_Runtime_Package (Etype (Concval)) is
13088 when System_Tasking_Protected_Objects_Entries =>
13089 Rewrite (Call,
13090 Make_Procedure_Call_Statement (Loc,
13091 Name =>
13092 New_Occurrence_Of
13093 (RTE (RE_Timed_Protected_Entry_Call), Loc),
13094 Parameter_Associations => Params));
13095
13096 when others =>
13097 raise Program_Error;
13098 end case;
13099
13100 -- For the task case, build a Timed_Task_Entry_Call
13101
13102 else
13103 -- Create a new call statement
13104
13105 Append_To (Params, New_Occurrence_Of (D, Loc));
13106 Append_To (Params, New_Occurrence_Of (M, Loc));
13107 Append_To (Params, New_Occurrence_Of (B, Loc));
13108
13109 Rewrite (Call,
13110 Make_Procedure_Call_Statement (Loc,
13111 Name =>
13112 New_Occurrence_Of (RTE (RE_Timed_Task_Entry_Call), Loc),
13113 Parameter_Associations => Params));
13114 end if;
13115
13116 Append_To (Stmts,
13117 Make_Implicit_If_Statement (N,
13118 Condition => New_Occurrence_Of (B, Loc),
13119 Then_Statements => E_Stats,
13120 Else_Statements => D_Stats));
13121 end if;
13122
13123 Rewrite (N,
13124 Make_Block_Statement (Loc,
13125 Declarations => Decls,
13126 Handled_Statement_Sequence =>
13127 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
13128
13129 Analyze (N);
13130
13131 -- Some items in Decls used to be in the N_Block in E_Call that is
13132 -- constructed in Expand_Entry_Call, and are now in the new Block
13133 -- into which N has been rewritten. Adjust their scopes to reflect that.
13134
13135 if Nkind (E_Call) = N_Block_Statement then
13136 Obj := First_Entity (Entity (Identifier (E_Call)));
13137 while Present (Obj) loop
13138 Set_Scope (Obj, Entity (Identifier (N)));
13139 Next_Entity (Obj);
13140 end loop;
13141 end if;
13142
13143 Reset_Scopes_To (N, Entity (Identifier (N)));
13144 end Expand_N_Timed_Entry_Call;
13145
13146 ----------------------------------------
13147 -- Expand_Protected_Body_Declarations --
13148 ----------------------------------------
13149
13150 procedure Expand_Protected_Body_Declarations
13151 (N : Node_Id;
13152 Spec_Id : Entity_Id)
13153 is
13154 begin
13155 if No_Run_Time_Mode then
13156 Error_Msg_CRT ("protected body", N);
13157 return;
13158
13159 elsif Expander_Active then
13160
13161 -- Associate discriminals with the first subprogram or entry body to
13162 -- be expanded.
13163
13164 if Present (First_Protected_Operation (Declarations (N))) then
13165 Set_Discriminals (Parent (Spec_Id));
13166 end if;
13167 end if;
13168 end Expand_Protected_Body_Declarations;
13169
13170 -------------------------
13171 -- External_Subprogram --
13172 -------------------------
13173
13174 function External_Subprogram (E : Entity_Id) return Entity_Id is
13175 Subp : constant Entity_Id := Protected_Body_Subprogram (E);
13176
13177 begin
13178 -- The internal and external subprograms follow each other on the entity
13179 -- chain. Note that previously private operations had no separate
13180 -- external subprogram. We now create one in all cases, because a
13181 -- private operation may actually appear in an external call, through
13182 -- a 'Access reference used for a callback.
13183
13184 -- If the operation is a function that returns an anonymous access type,
13185 -- the corresponding itype appears before the operation, and must be
13186 -- skipped.
13187
13188 -- This mechanism is fragile, there should be a real link between the
13189 -- two versions of the operation, but there is no place to put it ???
13190
13191 if Is_Access_Type (Next_Entity (Subp)) then
13192 return Next_Entity (Next_Entity (Subp));
13193 else
13194 return Next_Entity (Subp);
13195 end if;
13196 end External_Subprogram;
13197
13198 ------------------------------
13199 -- Extract_Dispatching_Call --
13200 ------------------------------
13201
13202 procedure Extract_Dispatching_Call
13203 (N : Node_Id;
13204 Call_Ent : out Entity_Id;
13205 Object : out Entity_Id;
13206 Actuals : out List_Id;
13207 Formals : out List_Id)
13208 is
13209 Call_Nam : Node_Id;
13210
13211 begin
13212 pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
13213
13214 if Present (Original_Node (N)) then
13215 Call_Nam := Name (Original_Node (N));
13216 else
13217 Call_Nam := Name (N);
13218 end if;
13219
13220 -- Retrieve the name of the dispatching procedure. It contains the
13221 -- dispatch table slot number.
13222
13223 loop
13224 case Nkind (Call_Nam) is
13225 when N_Identifier =>
13226 exit;
13227
13228 when N_Selected_Component =>
13229 Call_Nam := Selector_Name (Call_Nam);
13230
13231 when others =>
13232 raise Program_Error;
13233 end case;
13234 end loop;
13235
13236 Actuals := Parameter_Associations (N);
13237 Call_Ent := Entity (Call_Nam);
13238 Formals := Parameter_Specifications (Parent (Call_Ent));
13239 Object := First (Actuals);
13240
13241 if Present (Original_Node (Object)) then
13242 Object := Original_Node (Object);
13243 end if;
13244
13245 -- If the type of the dispatching object is an access type then return
13246 -- an explicit dereference of a copy of the object, and note that this
13247 -- is the controlling actual of the call.
13248
13249 if Is_Access_Type (Etype (Object)) then
13250 Object :=
13251 Make_Explicit_Dereference (Sloc (N), New_Copy_Tree (Object));
13252 Analyze (Object);
13253 Set_Is_Controlling_Actual (Object);
13254 end if;
13255 end Extract_Dispatching_Call;
13256
13257 -------------------
13258 -- Extract_Entry --
13259 -------------------
13260
13261 procedure Extract_Entry
13262 (N : Node_Id;
13263 Concval : out Node_Id;
13264 Ename : out Node_Id;
13265 Index : out Node_Id)
13266 is
13267 Nam : constant Node_Id := Name (N);
13268
13269 begin
13270 -- For a simple entry, the name is a selected component, with the
13271 -- prefix being the task value, and the selector being the entry.
13272
13273 if Nkind (Nam) = N_Selected_Component then
13274 Concval := Prefix (Nam);
13275 Ename := Selector_Name (Nam);
13276 Index := Empty;
13277
13278 -- For a member of an entry family, the name is an indexed component
13279 -- where the prefix is a selected component, whose prefix in turn is
13280 -- the task value, and whose selector is the entry family. The single
13281 -- expression in the expressions list of the indexed component is the
13282 -- subscript for the family.
13283
13284 else pragma Assert (Nkind (Nam) = N_Indexed_Component);
13285 Concval := Prefix (Prefix (Nam));
13286 Ename := Selector_Name (Prefix (Nam));
13287 Index := First (Expressions (Nam));
13288 end if;
13289
13290 -- Through indirection, the type may actually be a limited view of a
13291 -- concurrent type. When compiling a call, the non-limited view of the
13292 -- type is visible.
13293
13294 if From_Limited_With (Etype (Concval)) then
13295 Set_Etype (Concval, Non_Limited_View (Etype (Concval)));
13296 end if;
13297 end Extract_Entry;
13298
13299 -------------------
13300 -- Family_Offset --
13301 -------------------
13302
13303 function Family_Offset
13304 (Loc : Source_Ptr;
13305 Hi : Node_Id;
13306 Lo : Node_Id;
13307 Ttyp : Entity_Id;
13308 Cap : Boolean) return Node_Id
13309 is
13310 Ityp : Entity_Id;
13311 Real_Hi : Node_Id;
13312 Real_Lo : Node_Id;
13313
13314 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
13315 -- If one of the bounds is a reference to a discriminant, replace with
13316 -- corresponding discriminal of type. Within the body of a task retrieve
13317 -- the renamed discriminant by simple visibility, using its generated
13318 -- name. Within a protected object, find the original discriminant and
13319 -- replace it with the discriminal of the current protected operation.
13320
13321 ------------------------------
13322 -- Convert_Discriminant_Ref --
13323 ------------------------------
13324
13325 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
13326 Loc : constant Source_Ptr := Sloc (Bound);
13327 B : Node_Id;
13328 D : Entity_Id;
13329
13330 begin
13331 if Is_Entity_Name (Bound)
13332 and then Ekind (Entity (Bound)) = E_Discriminant
13333 then
13334 if Is_Task_Type (Ttyp) and then Has_Completion (Ttyp) then
13335 B := Make_Identifier (Loc, Chars (Entity (Bound)));
13336 Find_Direct_Name (B);
13337
13338 elsif Is_Protected_Type (Ttyp) then
13339 D := First_Discriminant (Ttyp);
13340 while Chars (D) /= Chars (Entity (Bound)) loop
13341 Next_Discriminant (D);
13342 end loop;
13343
13344 B := New_Occurrence_Of (Discriminal (D), Loc);
13345
13346 else
13347 B := New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
13348 end if;
13349
13350 elsif Nkind (Bound) = N_Attribute_Reference then
13351 return Bound;
13352
13353 else
13354 B := New_Copy_Tree (Bound);
13355 end if;
13356
13357 return
13358 Make_Attribute_Reference (Loc,
13359 Attribute_Name => Name_Pos,
13360 Prefix => New_Occurrence_Of (Etype (Bound), Loc),
13361 Expressions => New_List (B));
13362 end Convert_Discriminant_Ref;
13363
13364 -- Start of processing for Family_Offset
13365
13366 begin
13367 Real_Hi := Convert_Discriminant_Ref (Hi);
13368 Real_Lo := Convert_Discriminant_Ref (Lo);
13369
13370 if Cap then
13371 if Is_Task_Type (Ttyp) then
13372 Ityp := RTE (RE_Task_Entry_Index);
13373 else
13374 Ityp := RTE (RE_Protected_Entry_Index);
13375 end if;
13376
13377 Real_Hi :=
13378 Make_Attribute_Reference (Loc,
13379 Prefix => New_Occurrence_Of (Ityp, Loc),
13380 Attribute_Name => Name_Min,
13381 Expressions => New_List (
13382 Real_Hi,
13383 Make_Integer_Literal (Loc, Entry_Family_Bound - 1)));
13384
13385 Real_Lo :=
13386 Make_Attribute_Reference (Loc,
13387 Prefix => New_Occurrence_Of (Ityp, Loc),
13388 Attribute_Name => Name_Max,
13389 Expressions => New_List (
13390 Real_Lo,
13391 Make_Integer_Literal (Loc, -Entry_Family_Bound)));
13392 end if;
13393
13394 return Make_Op_Subtract (Loc, Real_Hi, Real_Lo);
13395 end Family_Offset;
13396
13397 -----------------
13398 -- Family_Size --
13399 -----------------
13400
13401 function Family_Size
13402 (Loc : Source_Ptr;
13403 Hi : Node_Id;
13404 Lo : Node_Id;
13405 Ttyp : Entity_Id;
13406 Cap : Boolean) return Node_Id
13407 is
13408 Ityp : Entity_Id;
13409
13410 begin
13411 if Is_Task_Type (Ttyp) then
13412 Ityp := RTE (RE_Task_Entry_Index);
13413 else
13414 Ityp := RTE (RE_Protected_Entry_Index);
13415 end if;
13416
13417 return
13418 Make_Attribute_Reference (Loc,
13419 Prefix => New_Occurrence_Of (Ityp, Loc),
13420 Attribute_Name => Name_Max,
13421 Expressions => New_List (
13422 Make_Op_Add (Loc,
13423 Left_Opnd => Family_Offset (Loc, Hi, Lo, Ttyp, Cap),
13424 Right_Opnd => Make_Integer_Literal (Loc, 1)),
13425 Make_Integer_Literal (Loc, 0)));
13426 end Family_Size;
13427
13428 ----------------------------
13429 -- Find_Enclosing_Context --
13430 ----------------------------
13431
13432 procedure Find_Enclosing_Context
13433 (N : Node_Id;
13434 Context : out Node_Id;
13435 Context_Id : out Entity_Id;
13436 Context_Decls : out List_Id)
13437 is
13438 begin
13439 -- Traverse the parent chain looking for an enclosing body, block,
13440 -- package or return statement.
13441
13442 Context := Parent (N);
13443 while Present (Context) loop
13444 if Nkind (Context) in N_Entry_Body
13445 | N_Extended_Return_Statement
13446 | N_Package_Body
13447 | N_Package_Declaration
13448 | N_Subprogram_Body
13449 | N_Task_Body
13450 then
13451 exit;
13452
13453 -- Do not consider block created to protect a list of statements with
13454 -- an Abort_Defer / Abort_Undefer_Direct pair.
13455
13456 elsif Nkind (Context) = N_Block_Statement
13457 and then not Is_Abort_Block (Context)
13458 then
13459 exit;
13460 end if;
13461
13462 Context := Parent (Context);
13463 end loop;
13464
13465 pragma Assert (Present (Context));
13466
13467 -- Extract the constituents of the context
13468
13469 if Nkind (Context) = N_Extended_Return_Statement then
13470 Context_Decls := Return_Object_Declarations (Context);
13471 Context_Id := Return_Statement_Entity (Context);
13472
13473 -- Package declarations and bodies use a common library-level activation
13474 -- chain or task master, therefore return the package declaration as the
13475 -- proper carrier for the appropriate flag.
13476
13477 elsif Nkind (Context) = N_Package_Body then
13478 Context_Decls := Declarations (Context);
13479 Context_Id := Corresponding_Spec (Context);
13480 Context := Parent (Context_Id);
13481
13482 if Nkind (Context) = N_Defining_Program_Unit_Name then
13483 Context := Parent (Parent (Context));
13484 else
13485 Context := Parent (Context);
13486 end if;
13487
13488 elsif Nkind (Context) = N_Package_Declaration then
13489 Context_Decls := Visible_Declarations (Specification (Context));
13490 Context_Id := Defining_Unit_Name (Specification (Context));
13491
13492 if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13493 Context_Id := Defining_Identifier (Context_Id);
13494 end if;
13495
13496 else
13497 if Nkind (Context) = N_Block_Statement then
13498 Context_Id := Entity (Identifier (Context));
13499
13500 if No (Declarations (Context)) then
13501 Set_Declarations (Context, New_List);
13502 end if;
13503
13504 elsif Nkind (Context) = N_Entry_Body then
13505 Context_Id := Defining_Identifier (Context);
13506
13507 elsif Nkind (Context) = N_Subprogram_Body then
13508 if Present (Corresponding_Spec (Context)) then
13509 Context_Id := Corresponding_Spec (Context);
13510 else
13511 Context_Id := Defining_Unit_Name (Specification (Context));
13512
13513 if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13514 Context_Id := Defining_Identifier (Context_Id);
13515 end if;
13516 end if;
13517
13518 elsif Nkind (Context) = N_Task_Body then
13519 Context_Id := Corresponding_Spec (Context);
13520
13521 else
13522 raise Program_Error;
13523 end if;
13524
13525 Context_Decls := Declarations (Context);
13526 end if;
13527
13528 pragma Assert (Present (Context_Id));
13529 pragma Assert (Present (Context_Decls));
13530 end Find_Enclosing_Context;
13531
13532 -----------------------
13533 -- Find_Master_Scope --
13534 -----------------------
13535
13536 function Find_Master_Scope (E : Entity_Id) return Entity_Id is
13537 S : Entity_Id;
13538
13539 begin
13540 -- In Ada 2005, the master is the innermost enclosing scope that is not
13541 -- transient. If the enclosing block is the rewriting of a call or the
13542 -- scope is an extended return statement this is valid master. The
13543 -- master in an extended return is only used within the return, and is
13544 -- subsequently overwritten in Move_Activation_Chain, but it must exist
13545 -- now before that overwriting occurs.
13546
13547 S := Scope (E);
13548
13549 if Ada_Version >= Ada_2005 then
13550 while Is_Internal (S) loop
13551 if Nkind (Parent (S)) = N_Block_Statement
13552 and then Has_Master_Entity (S)
13553 then
13554 exit;
13555
13556 elsif Ekind (S) = E_Return_Statement then
13557 exit;
13558
13559 else
13560 S := Scope (S);
13561 end if;
13562 end loop;
13563 end if;
13564
13565 return S;
13566 end Find_Master_Scope;
13567
13568 -------------------------------
13569 -- First_Protected_Operation --
13570 -------------------------------
13571
13572 function First_Protected_Operation (D : List_Id) return Node_Id is
13573 First_Op : Node_Id;
13574
13575 begin
13576 First_Op := First (D);
13577 while Present (First_Op)
13578 and then Nkind (First_Op) not in N_Subprogram_Body | N_Entry_Body
13579 loop
13580 Next (First_Op);
13581 end loop;
13582
13583 return First_Op;
13584 end First_Protected_Operation;
13585
13586 ---------------------------------------
13587 -- Install_Private_Data_Declarations --
13588 ---------------------------------------
13589
13590 procedure Install_Private_Data_Declarations
13591 (Loc : Source_Ptr;
13592 Spec_Id : Entity_Id;
13593 Conc_Typ : Entity_Id;
13594 Body_Nod : Node_Id;
13595 Decls : List_Id;
13596 Barrier : Boolean := False;
13597 Family : Boolean := False)
13598 is
13599 Is_Protected : constant Boolean := Is_Protected_Type (Conc_Typ);
13600 Decl : Node_Id;
13601 Def : Node_Id;
13602 Insert_Node : Node_Id := Empty;
13603 Obj_Ent : Entity_Id;
13604
13605 procedure Add (Decl : Node_Id);
13606 -- Add a single declaration after Insert_Node. If this is the first
13607 -- addition, Decl is added to the front of Decls and it becomes the
13608 -- insertion node.
13609
13610 function Replace_Bound (Bound : Node_Id) return Node_Id;
13611 -- The bounds of an entry index may depend on discriminants, create a
13612 -- reference to the corresponding prival. Otherwise return a duplicate
13613 -- of the original bound.
13614
13615 ---------
13616 -- Add --
13617 ---------
13618
13619 procedure Add (Decl : Node_Id) is
13620 begin
13621 if No (Insert_Node) then
13622 Prepend_To (Decls, Decl);
13623 else
13624 Insert_After (Insert_Node, Decl);
13625 end if;
13626
13627 Insert_Node := Decl;
13628 end Add;
13629
13630 -------------------
13631 -- Replace_Bound --
13632 -------------------
13633
13634 function Replace_Bound (Bound : Node_Id) return Node_Id is
13635 begin
13636 if Nkind (Bound) = N_Identifier
13637 and then Is_Discriminal (Entity (Bound))
13638 then
13639 return Make_Identifier (Loc, Chars (Entity (Bound)));
13640 else
13641 return Duplicate_Subexpr (Bound);
13642 end if;
13643 end Replace_Bound;
13644
13645 -- Start of processing for Install_Private_Data_Declarations
13646
13647 begin
13648 -- Step 1: Retrieve the concurrent object entity. Obj_Ent can denote
13649 -- formal parameter _O, _object or _task depending on the context.
13650
13651 Obj_Ent := Concurrent_Object (Spec_Id, Conc_Typ);
13652
13653 -- Special processing of _O for barrier functions, protected entries
13654 -- and families.
13655
13656 if Barrier
13657 or else
13658 (Is_Protected
13659 and then
13660 (Ekind (Spec_Id) = E_Entry
13661 or else Ekind (Spec_Id) = E_Entry_Family))
13662 then
13663 declare
13664 Conc_Rec : constant Entity_Id :=
13665 Corresponding_Record_Type (Conc_Typ);
13666 Typ_Id : constant Entity_Id :=
13667 Make_Defining_Identifier (Loc,
13668 New_External_Name (Chars (Conc_Rec), 'P'));
13669 begin
13670 -- Generate:
13671 -- type prot_typVP is access prot_typV;
13672
13673 Decl :=
13674 Make_Full_Type_Declaration (Loc,
13675 Defining_Identifier => Typ_Id,
13676 Type_Definition =>
13677 Make_Access_To_Object_Definition (Loc,
13678 Subtype_Indication =>
13679 New_Occurrence_Of (Conc_Rec, Loc)));
13680 Add (Decl);
13681
13682 -- Generate:
13683 -- _object : prot_typVP := prot_typV (_O);
13684
13685 Decl :=
13686 Make_Object_Declaration (Loc,
13687 Defining_Identifier =>
13688 Make_Defining_Identifier (Loc, Name_uObject),
13689 Object_Definition => New_Occurrence_Of (Typ_Id, Loc),
13690 Expression =>
13691 Unchecked_Convert_To (Typ_Id,
13692 New_Occurrence_Of (Obj_Ent, Loc)));
13693 Add (Decl);
13694
13695 -- Set the reference to the concurrent object
13696
13697 Obj_Ent := Defining_Identifier (Decl);
13698 end;
13699 end if;
13700
13701 -- Step 2: Create the Protection object and build its declaration for
13702 -- any protected entry (family) of subprogram. Note for the lock-free
13703 -- implementation, the Protection object is not needed anymore.
13704
13705 if Is_Protected and then not Uses_Lock_Free (Conc_Typ) then
13706 declare
13707 Prot_Ent : constant Entity_Id := Make_Temporary (Loc, 'R');
13708 Prot_Typ : RE_Id;
13709
13710 begin
13711 Set_Protection_Object (Spec_Id, Prot_Ent);
13712
13713 -- Determine the proper protection type
13714
13715 if Has_Attach_Handler (Conc_Typ)
13716 and then not Restricted_Profile
13717 then
13718 Prot_Typ := RE_Static_Interrupt_Protection;
13719
13720 elsif Has_Interrupt_Handler (Conc_Typ)
13721 and then not Restriction_Active (No_Dynamic_Attachment)
13722 then
13723 Prot_Typ := RE_Dynamic_Interrupt_Protection;
13724
13725 else
13726 case Corresponding_Runtime_Package (Conc_Typ) is
13727 when System_Tasking_Protected_Objects_Entries =>
13728 Prot_Typ := RE_Protection_Entries;
13729
13730 when System_Tasking_Protected_Objects_Single_Entry =>
13731 Prot_Typ := RE_Protection_Entry;
13732
13733 when System_Tasking_Protected_Objects =>
13734 Prot_Typ := RE_Protection;
13735
13736 when others =>
13737 raise Program_Error;
13738 end case;
13739 end if;
13740
13741 -- Generate:
13742 -- conc_typR : protection_typ renames _object._object;
13743
13744 Decl :=
13745 Make_Object_Renaming_Declaration (Loc,
13746 Defining_Identifier => Prot_Ent,
13747 Subtype_Mark =>
13748 New_Occurrence_Of (RTE (Prot_Typ), Loc),
13749 Name =>
13750 Make_Selected_Component (Loc,
13751 Prefix => New_Occurrence_Of (Obj_Ent, Loc),
13752 Selector_Name => Make_Identifier (Loc, Name_uObject)));
13753 Add (Decl);
13754 end;
13755 end if;
13756
13757 -- Step 3: Add discriminant renamings (if any)
13758
13759 if Has_Discriminants (Conc_Typ) then
13760 declare
13761 D : Entity_Id;
13762
13763 begin
13764 D := First_Discriminant (Conc_Typ);
13765 while Present (D) loop
13766
13767 -- Adjust the source location
13768
13769 Set_Sloc (Discriminal (D), Loc);
13770
13771 -- Generate:
13772 -- discr_name : discr_typ renames _object.discr_name;
13773 -- or
13774 -- discr_name : discr_typ renames _task.discr_name;
13775
13776 Decl :=
13777 Make_Object_Renaming_Declaration (Loc,
13778 Defining_Identifier => Discriminal (D),
13779 Subtype_Mark => New_Occurrence_Of (Etype (D), Loc),
13780 Name =>
13781 Make_Selected_Component (Loc,
13782 Prefix => New_Occurrence_Of (Obj_Ent, Loc),
13783 Selector_Name => Make_Identifier (Loc, Chars (D))));
13784 Add (Decl);
13785
13786 -- Set debug info needed on this renaming declaration even
13787 -- though it does not come from source, so that the debugger
13788 -- will get the right information for these generated names.
13789
13790 Set_Debug_Info_Needed (Discriminal (D));
13791
13792 Next_Discriminant (D);
13793 end loop;
13794 end;
13795 end if;
13796
13797 -- Step 4: Add private component renamings (if any)
13798
13799 if Is_Protected then
13800 Def := Protected_Definition (Parent (Conc_Typ));
13801
13802 if Present (Private_Declarations (Def)) then
13803 declare
13804 Comp : Node_Id;
13805 Comp_Id : Entity_Id;
13806 Decl_Id : Entity_Id;
13807
13808 begin
13809 Comp := First (Private_Declarations (Def));
13810 while Present (Comp) loop
13811 if Nkind (Comp) = N_Component_Declaration then
13812 Comp_Id := Defining_Identifier (Comp);
13813 Decl_Id :=
13814 Make_Defining_Identifier (Loc, Chars (Comp_Id));
13815
13816 -- Minimal decoration
13817
13818 if Ekind (Spec_Id) = E_Function then
13819 Set_Ekind (Decl_Id, E_Constant);
13820 else
13821 Set_Ekind (Decl_Id, E_Variable);
13822 end if;
13823
13824 Set_Prival (Comp_Id, Decl_Id);
13825 Set_Prival_Link (Decl_Id, Comp_Id);
13826 Set_Is_Aliased (Decl_Id, Is_Aliased (Comp_Id));
13827 Set_Is_Independent (Decl_Id, Is_Independent (Comp_Id));
13828
13829 -- Generate:
13830 -- comp_name : comp_typ renames _object.comp_name;
13831
13832 Decl :=
13833 Make_Object_Renaming_Declaration (Loc,
13834 Defining_Identifier => Decl_Id,
13835 Subtype_Mark =>
13836 New_Occurrence_Of (Etype (Comp_Id), Loc),
13837 Name =>
13838 Make_Selected_Component (Loc,
13839 Prefix =>
13840 New_Occurrence_Of (Obj_Ent, Loc),
13841 Selector_Name =>
13842 Make_Identifier (Loc, Chars (Comp_Id))));
13843 Add (Decl);
13844 end if;
13845
13846 Next (Comp);
13847 end loop;
13848 end;
13849 end if;
13850 end if;
13851
13852 -- Step 5: Add the declaration of the entry index and the associated
13853 -- type for barrier functions and entry families.
13854
13855 if (Barrier and Family) or else Ekind (Spec_Id) = E_Entry_Family then
13856 declare
13857 E : constant Entity_Id := Index_Object (Spec_Id);
13858 Index : constant Entity_Id :=
13859 Defining_Identifier
13860 (Entry_Index_Specification
13861 (Entry_Body_Formal_Part (Body_Nod)));
13862 Index_Con : constant Entity_Id :=
13863 Make_Defining_Identifier (Loc, Chars (Index));
13864 High : Node_Id;
13865 Index_Typ : Entity_Id;
13866 Low : Node_Id;
13867
13868 begin
13869 -- Minimal decoration
13870
13871 Set_Ekind (Index_Con, E_Constant);
13872 Set_Entry_Index_Constant (Index, Index_Con);
13873 Set_Discriminal_Link (Index_Con, Index);
13874
13875 -- Retrieve the bounds of the entry family
13876
13877 High := Type_High_Bound (Etype (Index));
13878 Low := Type_Low_Bound (Etype (Index));
13879
13880 -- In the simple case the entry family is given by a subtype mark
13881 -- and the index constant has the same type.
13882
13883 if Is_Entity_Name (Original_Node (
13884 Discrete_Subtype_Definition (Parent (Index))))
13885 then
13886 Index_Typ := Etype (Index);
13887
13888 -- Otherwise a new subtype declaration is required
13889
13890 else
13891 High := Replace_Bound (High);
13892 Low := Replace_Bound (Low);
13893
13894 Index_Typ := Make_Temporary (Loc, 'J');
13895
13896 -- Generate:
13897 -- subtype Jnn is <Etype of Index> range Low .. High;
13898
13899 Decl :=
13900 Make_Subtype_Declaration (Loc,
13901 Defining_Identifier => Index_Typ,
13902 Subtype_Indication =>
13903 Make_Subtype_Indication (Loc,
13904 Subtype_Mark =>
13905 New_Occurrence_Of (Base_Type (Etype (Index)), Loc),
13906 Constraint =>
13907 Make_Range_Constraint (Loc,
13908 Range_Expression =>
13909 Make_Range (Loc, Low, High))));
13910 Add (Decl);
13911 end if;
13912
13913 Set_Etype (Index_Con, Index_Typ);
13914
13915 -- Create the object which designates the index:
13916 -- J : constant Jnn :=
13917 -- Jnn'Val (_E - <index expr> + Jnn'Pos (Jnn'First));
13918 --
13919 -- where Jnn is the subtype created above or the original type of
13920 -- the index, _E is a formal of the protected body subprogram and
13921 -- <index expr> is the index of the first family member.
13922
13923 Decl :=
13924 Make_Object_Declaration (Loc,
13925 Defining_Identifier => Index_Con,
13926 Constant_Present => True,
13927 Object_Definition =>
13928 New_Occurrence_Of (Index_Typ, Loc),
13929
13930 Expression =>
13931 Make_Attribute_Reference (Loc,
13932 Prefix =>
13933 New_Occurrence_Of (Index_Typ, Loc),
13934 Attribute_Name => Name_Val,
13935
13936 Expressions => New_List (
13937
13938 Make_Op_Add (Loc,
13939 Left_Opnd =>
13940 Make_Op_Subtract (Loc,
13941 Left_Opnd => New_Occurrence_Of (E, Loc),
13942 Right_Opnd =>
13943 Entry_Index_Expression (Loc,
13944 Defining_Identifier (Body_Nod),
13945 Empty, Conc_Typ)),
13946
13947 Right_Opnd =>
13948 Make_Attribute_Reference (Loc,
13949 Prefix =>
13950 New_Occurrence_Of (Index_Typ, Loc),
13951 Attribute_Name => Name_Pos,
13952 Expressions => New_List (
13953 Make_Attribute_Reference (Loc,
13954 Prefix =>
13955 New_Occurrence_Of (Index_Typ, Loc),
13956 Attribute_Name => Name_First)))))));
13957 Add (Decl);
13958 end;
13959 end if;
13960 end Install_Private_Data_Declarations;
13961
13962 ---------------------------------
13963 -- Is_Potentially_Large_Family --
13964 ---------------------------------
13965
13966 function Is_Potentially_Large_Family
13967 (Base_Index : Entity_Id;
13968 Conctyp : Entity_Id;
13969 Lo : Node_Id;
13970 Hi : Node_Id) return Boolean
13971 is
13972 begin
13973 return Scope (Base_Index) = Standard_Standard
13974 and then Base_Index = Base_Type (Standard_Integer)
13975 and then Has_Defaulted_Discriminants (Conctyp)
13976 and then
13977 (Denotes_Discriminant (Lo, True)
13978 or else
13979 Denotes_Discriminant (Hi, True));
13980 end Is_Potentially_Large_Family;
13981
13982 -------------------------------------
13983 -- Is_Private_Primitive_Subprogram --
13984 -------------------------------------
13985
13986 function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean is
13987 begin
13988 return
13989 (Ekind (Id) = E_Function or else Ekind (Id) = E_Procedure)
13990 and then Is_Private_Primitive (Id);
13991 end Is_Private_Primitive_Subprogram;
13992
13993 ------------------
13994 -- Index_Object --
13995 ------------------
13996
13997 function Index_Object (Spec_Id : Entity_Id) return Entity_Id is
13998 Bod_Subp : constant Entity_Id := Protected_Body_Subprogram (Spec_Id);
13999 Formal : Entity_Id;
14000
14001 begin
14002 Formal := First_Formal (Bod_Subp);
14003 while Present (Formal) loop
14004
14005 -- Look for formal parameter _E
14006
14007 if Chars (Formal) = Name_uE then
14008 return Formal;
14009 end if;
14010
14011 Next_Formal (Formal);
14012 end loop;
14013
14014 -- A protected body subprogram should always have the parameter in
14015 -- question.
14016
14017 raise Program_Error;
14018 end Index_Object;
14019
14020 --------------------------------
14021 -- Make_Initialize_Protection --
14022 --------------------------------
14023
14024 function Make_Initialize_Protection
14025 (Protect_Rec : Entity_Id) return List_Id
14026 is
14027 Loc : constant Source_Ptr := Sloc (Protect_Rec);
14028 P_Arr : Entity_Id;
14029 Pdec : Node_Id;
14030 Ptyp : constant Node_Id :=
14031 Corresponding_Concurrent_Type (Protect_Rec);
14032 Args : List_Id;
14033 L : constant List_Id := New_List;
14034 Has_Entry : constant Boolean := Has_Entries (Ptyp);
14035 Prio_Type : Entity_Id;
14036 Prio_Var : Entity_Id := Empty;
14037 Restricted : constant Boolean := Restricted_Profile;
14038
14039 begin
14040 -- We may need two calls to properly initialize the object, one to
14041 -- Initialize_Protection, and possibly one to Install_Handlers if we
14042 -- have a pragma Attach_Handler.
14043
14044 -- Get protected declaration. In the case of a task type declaration,
14045 -- this is simply the parent of the protected type entity. In the single
14046 -- protected object declaration, this parent will be the implicit type,
14047 -- and we can find the corresponding single protected object declaration
14048 -- by searching forward in the declaration list in the tree.
14049
14050 -- Is the test for N_Single_Protected_Declaration needed here??? Nodes
14051 -- of this type should have been removed during semantic analysis.
14052
14053 Pdec := Parent (Ptyp);
14054 while Nkind (Pdec) not in
14055 N_Protected_Type_Declaration | N_Single_Protected_Declaration
14056 loop
14057 Next (Pdec);
14058 end loop;
14059
14060 -- Build the parameter list for the call. Note that _Init is the name
14061 -- of the formal for the object to be initialized, which is the task
14062 -- value record itself.
14063
14064 Args := New_List;
14065
14066 -- For lock-free implementation, skip initializations of the Protection
14067 -- object.
14068
14069 if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
14070
14071 -- Object parameter. This is a pointer to the object of type
14072 -- Protection used by the GNARL to control the protected object.
14073
14074 Append_To (Args,
14075 Make_Attribute_Reference (Loc,
14076 Prefix =>
14077 Make_Selected_Component (Loc,
14078 Prefix => Make_Identifier (Loc, Name_uInit),
14079 Selector_Name => Make_Identifier (Loc, Name_uObject)),
14080 Attribute_Name => Name_Unchecked_Access));
14081
14082 -- Priority parameter. Set to Unspecified_Priority unless there is a
14083 -- Priority rep item, in which case we take the value from the pragma
14084 -- or attribute definition clause, or there is an Interrupt_Priority
14085 -- rep item and no Priority rep item, and we set the ceiling to
14086 -- Interrupt_Priority'Last, an implementation-defined value, see
14087 -- (RM D.3(10)).
14088
14089 if Has_Rep_Item (Ptyp, Name_Priority, Check_Parents => False) then
14090 declare
14091 Prio_Clause : constant Node_Id :=
14092 Get_Rep_Item
14093 (Ptyp, Name_Priority, Check_Parents => False);
14094
14095 Prio : Node_Id;
14096
14097 begin
14098 -- Pragma Priority
14099
14100 if Nkind (Prio_Clause) = N_Pragma then
14101 Prio :=
14102 Expression
14103 (First (Pragma_Argument_Associations (Prio_Clause)));
14104
14105 -- Get_Rep_Item returns either priority pragma
14106
14107 if Pragma_Name (Prio_Clause) = Name_Priority then
14108 Prio_Type := RTE (RE_Any_Priority);
14109 else
14110 Prio_Type := RTE (RE_Interrupt_Priority);
14111 end if;
14112
14113 -- Attribute definition clause Priority
14114
14115 else
14116 if Chars (Prio_Clause) = Name_Priority then
14117 Prio_Type := RTE (RE_Any_Priority);
14118 else
14119 Prio_Type := RTE (RE_Interrupt_Priority);
14120 end if;
14121
14122 Prio := Expression (Prio_Clause);
14123 end if;
14124
14125 -- Always create a locale variable to capture the priority.
14126 -- The priority is also passed to Install_Restriced_Handlers.
14127 -- Note that it is really necessary to create this variable
14128 -- explicitly. It might be thought that removing side effects
14129 -- would the appropriate approach, but that could generate
14130 -- declarations improperly placed in the enclosing scope.
14131
14132 Prio_Var := Make_Temporary (Loc, 'R', Prio);
14133 Append_To (L,
14134 Make_Object_Declaration (Loc,
14135 Defining_Identifier => Prio_Var,
14136 Object_Definition => New_Occurrence_Of (Prio_Type, Loc),
14137 Expression => Relocate_Node (Prio)));
14138
14139 Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
14140 end;
14141
14142 -- When no priority is specified but an xx_Handler pragma is, we
14143 -- default to System.Interrupts.Default_Interrupt_Priority, see
14144 -- D.3(10).
14145
14146 elsif Has_Attach_Handler (Ptyp)
14147 or else Has_Interrupt_Handler (Ptyp)
14148 then
14149 Append_To (Args,
14150 New_Occurrence_Of (RTE (RE_Default_Interrupt_Priority), Loc));
14151
14152 -- Normal case, no priority or xx_Handler specified, default priority
14153
14154 else
14155 Append_To (Args,
14156 New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
14157 end if;
14158
14159 -- Deadline_Floor parameter for GNAT_Ravenscar_EDF runtimes
14160
14161 if Restricted_Profile and Task_Dispatching_Policy = 'E' then
14162 Deadline_Floor : declare
14163 Item : constant Node_Id :=
14164 Get_Rep_Item
14165 (Ptyp, Name_Deadline_Floor, Check_Parents => False);
14166
14167 Deadline : Node_Id;
14168
14169 begin
14170 if Present (Item) then
14171
14172 -- Pragma Deadline_Floor
14173
14174 if Nkind (Item) = N_Pragma then
14175 Deadline :=
14176 Expression
14177 (First (Pragma_Argument_Associations (Item)));
14178
14179 -- Attribute definition clause Deadline_Floor
14180
14181 else
14182 pragma Assert
14183 (Nkind (Item) = N_Attribute_Definition_Clause);
14184
14185 Deadline := Expression (Item);
14186 end if;
14187
14188 Append_To (Args, Deadline);
14189
14190 -- Unusual case: default deadline
14191
14192 else
14193 Append_To (Args,
14194 New_Occurrence_Of (RTE (RE_Time_Span_Zero), Loc));
14195 end if;
14196 end Deadline_Floor;
14197 end if;
14198
14199 -- Test for Compiler_Info parameter. This parameter allows entry body
14200 -- procedures and barrier functions to be called from the runtime. It
14201 -- is a pointer to the record generated by the compiler to represent
14202 -- the protected object.
14203
14204 -- A protected type without entries that covers an interface and
14205 -- overrides the abstract routines with protected procedures is
14206 -- considered equivalent to a protected type with entries in the
14207 -- context of dispatching select statements.
14208
14209 -- Protected types with interrupt handlers (when not using a
14210 -- restricted profile) are also considered equivalent to protected
14211 -- types with entries.
14212
14213 -- The types which are used (Static_Interrupt_Protection and
14214 -- Dynamic_Interrupt_Protection) are derived from Protection_Entries.
14215
14216 declare
14217 Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
14218
14219 Called_Subp : RE_Id;
14220
14221 begin
14222 case Pkg_Id is
14223 when System_Tasking_Protected_Objects_Entries =>
14224 Called_Subp := RE_Initialize_Protection_Entries;
14225
14226 -- Argument Compiler_Info
14227
14228 Append_To (Args,
14229 Make_Attribute_Reference (Loc,
14230 Prefix => Make_Identifier (Loc, Name_uInit),
14231 Attribute_Name => Name_Address));
14232
14233 when System_Tasking_Protected_Objects_Single_Entry =>
14234 Called_Subp := RE_Initialize_Protection_Entry;
14235
14236 -- Argument Compiler_Info
14237
14238 Append_To (Args,
14239 Make_Attribute_Reference (Loc,
14240 Prefix => Make_Identifier (Loc, Name_uInit),
14241 Attribute_Name => Name_Address));
14242
14243 when System_Tasking_Protected_Objects =>
14244 Called_Subp := RE_Initialize_Protection;
14245
14246 when others =>
14247 raise Program_Error;
14248 end case;
14249
14250 -- Entry_Queue_Maxes parameter. This is an access to an array of
14251 -- naturals representing the entry queue maximums for each entry
14252 -- in the protected type. Zero represents no max. The access is
14253 -- null if there is no limit for all entries (usual case).
14254
14255 if Has_Entry
14256 and then Pkg_Id = System_Tasking_Protected_Objects_Entries
14257 then
14258 if Present (Entry_Max_Queue_Lengths_Array (Ptyp)) then
14259 Append_To (Args,
14260 Make_Attribute_Reference (Loc,
14261 Prefix =>
14262 New_Occurrence_Of
14263 (Entry_Max_Queue_Lengths_Array (Ptyp), Loc),
14264 Attribute_Name => Name_Unrestricted_Access));
14265 else
14266 Append_To (Args, Make_Null (Loc));
14267 end if;
14268
14269 -- Edge cases exist where entry initialization functions are
14270 -- called, but no entries exist, so null is appended.
14271
14272 elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
14273 Append_To (Args, Make_Null (Loc));
14274 end if;
14275
14276 -- Entry_Bodies parameter. This is a pointer to an array of
14277 -- pointers to the entry body procedures and barrier functions of
14278 -- the object. If the protected type has no entries this object
14279 -- will not exist, in this case, pass a null (it can happen when
14280 -- there are protected interrupt handlers or interfaces).
14281
14282 if Has_Entry then
14283 P_Arr := Entry_Bodies_Array (Ptyp);
14284
14285 -- Argument Entry_Body (for single entry) or Entry_Bodies (for
14286 -- multiple entries).
14287
14288 Append_To (Args,
14289 Make_Attribute_Reference (Loc,
14290 Prefix => New_Occurrence_Of (P_Arr, Loc),
14291 Attribute_Name => Name_Unrestricted_Access));
14292
14293 if Pkg_Id = System_Tasking_Protected_Objects_Entries then
14294
14295 -- Find index mapping function (clumsy but ok for now)
14296
14297 while Ekind (P_Arr) /= E_Function loop
14298 Next_Entity (P_Arr);
14299 end loop;
14300
14301 Append_To (Args,
14302 Make_Attribute_Reference (Loc,
14303 Prefix => New_Occurrence_Of (P_Arr, Loc),
14304 Attribute_Name => Name_Unrestricted_Access));
14305 end if;
14306
14307 elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
14308
14309 -- This is the case where we have a protected object with
14310 -- interfaces and no entries, and the single entry restriction
14311 -- is in effect. We pass a null pointer for the entry
14312 -- parameter because there is no actual entry.
14313
14314 Append_To (Args, Make_Null (Loc));
14315
14316 elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
14317
14318 -- This is the case where we have a protected object with no
14319 -- entries and:
14320 -- - either interrupt handlers with non restricted profile,
14321 -- - or interfaces
14322 -- Note that the types which are used for interrupt handlers
14323 -- (Static/Dynamic_Interrupt_Protection) are derived from
14324 -- Protection_Entries. We pass two null pointers because there
14325 -- is no actual entry, and the initialization procedure needs
14326 -- both Entry_Bodies and Find_Body_Index.
14327
14328 Append_To (Args, Make_Null (Loc));
14329 Append_To (Args, Make_Null (Loc));
14330 end if;
14331
14332 Append_To (L,
14333 Make_Procedure_Call_Statement (Loc,
14334 Name =>
14335 New_Occurrence_Of (RTE (Called_Subp), Loc),
14336 Parameter_Associations => Args));
14337 end;
14338 end if;
14339
14340 if Has_Attach_Handler (Ptyp) then
14341
14342 -- We have a list of N Attach_Handler (ProcI, ExprI), and we have to
14343 -- make the following call:
14344
14345 -- Install_Handlers (_object,
14346 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
14347
14348 -- or, in the case of Ravenscar:
14349
14350 -- Install_Restricted_Handlers
14351 -- (Prio, ((Expr1, Proc1'access), ...., (ExprN, ProcN'access)));
14352
14353 declare
14354 Args : constant List_Id := New_List;
14355 Table : constant List_Id := New_List;
14356 Ritem : Node_Id := First_Rep_Item (Ptyp);
14357
14358 begin
14359 -- Build the Priority parameter (only for ravenscar)
14360
14361 if Restricted then
14362
14363 -- Priority comes from a pragma
14364
14365 if Present (Prio_Var) then
14366 Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
14367
14368 -- Priority is the default one
14369
14370 else
14371 Append_To (Args,
14372 New_Occurrence_Of
14373 (RTE (RE_Default_Interrupt_Priority), Loc));
14374 end if;
14375 end if;
14376
14377 -- Build the Attach_Handler table argument
14378
14379 while Present (Ritem) loop
14380 if Nkind (Ritem) = N_Pragma
14381 and then Pragma_Name (Ritem) = Name_Attach_Handler
14382 then
14383 declare
14384 Handler : constant Node_Id :=
14385 First (Pragma_Argument_Associations (Ritem));
14386
14387 Interrupt : constant Node_Id := Next (Handler);
14388 Expr : constant Node_Id := Expression (Interrupt);
14389
14390 begin
14391 Append_To (Table,
14392 Make_Aggregate (Loc, Expressions => New_List (
14393 Unchecked_Convert_To
14394 (RTE (RE_System_Interrupt_Id), Expr),
14395 Make_Attribute_Reference (Loc,
14396 Prefix =>
14397 Make_Selected_Component (Loc,
14398 Prefix =>
14399 Make_Identifier (Loc, Name_uInit),
14400 Selector_Name =>
14401 Duplicate_Subexpr_No_Checks
14402 (Expression (Handler))),
14403 Attribute_Name => Name_Access))));
14404 end;
14405 end if;
14406
14407 Next_Rep_Item (Ritem);
14408 end loop;
14409
14410 -- Append the table argument we just built
14411
14412 Append_To (Args, Make_Aggregate (Loc, Table));
14413
14414 -- Append the Install_Handlers (or Install_Restricted_Handlers)
14415 -- call to the statements.
14416
14417 if Restricted then
14418 -- Call a simplified version of Install_Handlers to be used
14419 -- when the Ravenscar restrictions are in effect
14420 -- (Install_Restricted_Handlers).
14421
14422 Append_To (L,
14423 Make_Procedure_Call_Statement (Loc,
14424 Name =>
14425 New_Occurrence_Of
14426 (RTE (RE_Install_Restricted_Handlers), Loc),
14427 Parameter_Associations => Args));
14428
14429 else
14430 if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
14431
14432 -- First, prepends the _object argument
14433
14434 Prepend_To (Args,
14435 Make_Attribute_Reference (Loc,
14436 Prefix =>
14437 Make_Selected_Component (Loc,
14438 Prefix => Make_Identifier (Loc, Name_uInit),
14439 Selector_Name =>
14440 Make_Identifier (Loc, Name_uObject)),
14441 Attribute_Name => Name_Unchecked_Access));
14442 end if;
14443
14444 -- Then, insert call to Install_Handlers
14445
14446 Append_To (L,
14447 Make_Procedure_Call_Statement (Loc,
14448 Name =>
14449 New_Occurrence_Of (RTE (RE_Install_Handlers), Loc),
14450 Parameter_Associations => Args));
14451 end if;
14452 end;
14453 end if;
14454
14455 return L;
14456 end Make_Initialize_Protection;
14457
14458 ---------------------------
14459 -- Make_Task_Create_Call --
14460 ---------------------------
14461
14462 function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
14463 Loc : constant Source_Ptr := Sloc (Task_Rec);
14464 Args : List_Id;
14465 Ecount : Node_Id;
14466 Name : Node_Id;
14467 Tdec : Node_Id;
14468 Tdef : Node_Id;
14469 Tnam : Name_Id;
14470 Ttyp : Node_Id;
14471
14472 begin
14473 Ttyp := Corresponding_Concurrent_Type (Task_Rec);
14474 Tnam := Chars (Ttyp);
14475
14476 -- Get task declaration. In the case of a task type declaration, this is
14477 -- simply the parent of the task type entity. In the single task
14478 -- declaration, this parent will be the implicit type, and we can find
14479 -- the corresponding single task declaration by searching forward in the
14480 -- declaration list in the tree.
14481
14482 -- Is the test for N_Single_Task_Declaration needed here??? Nodes of
14483 -- this type should have been removed during semantic analysis.
14484
14485 Tdec := Parent (Ttyp);
14486 while Nkind (Tdec) not in
14487 N_Task_Type_Declaration | N_Single_Task_Declaration
14488 loop
14489 Next (Tdec);
14490 end loop;
14491
14492 -- Now we can find the task definition from this declaration
14493
14494 Tdef := Task_Definition (Tdec);
14495
14496 -- Build the parameter list for the call. Note that _Init is the name
14497 -- of the formal for the object to be initialized, which is the task
14498 -- value record itself.
14499
14500 Args := New_List;
14501
14502 -- Priority parameter. Set to Unspecified_Priority unless there is a
14503 -- Priority rep item, in which case we take the value from the rep item.
14504 -- Not used on Ravenscar_EDF profile.
14505
14506 if not (Restricted_Profile and then Task_Dispatching_Policy = 'E') then
14507 if Has_Rep_Item (Ttyp, Name_Priority, Check_Parents => False) then
14508 Append_To (Args,
14509 Make_Selected_Component (Loc,
14510 Prefix => Make_Identifier (Loc, Name_uInit),
14511 Selector_Name => Make_Identifier (Loc, Name_uPriority)));
14512 else
14513 Append_To (Args,
14514 New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
14515 end if;
14516 end if;
14517
14518 -- Optional Stack parameter
14519
14520 if Restricted_Profile then
14521
14522 -- If the stack has been preallocated by the expander then
14523 -- pass its address. Otherwise, pass a null address.
14524
14525 if Preallocated_Stacks_On_Target then
14526 Append_To (Args,
14527 Make_Attribute_Reference (Loc,
14528 Prefix =>
14529 Make_Selected_Component (Loc,
14530 Prefix => Make_Identifier (Loc, Name_uInit),
14531 Selector_Name => Make_Identifier (Loc, Name_uStack)),
14532 Attribute_Name => Name_Address));
14533
14534 else
14535 Append_To (Args,
14536 New_Occurrence_Of (RTE (RE_Null_Address), Loc));
14537 end if;
14538 end if;
14539
14540 -- Size parameter. If no Storage_Size pragma is present, then
14541 -- the size is taken from the taskZ variable for the type, which
14542 -- is either Unspecified_Size, or has been reset by the use of
14543 -- a Storage_Size attribute definition clause. If a pragma is
14544 -- present, then the size is taken from the _Size field of the
14545 -- task value record, which was set from the pragma value.
14546
14547 if Present (Tdef) and then Has_Storage_Size_Pragma (Tdef) then
14548 Append_To (Args,
14549 Make_Selected_Component (Loc,
14550 Prefix => Make_Identifier (Loc, Name_uInit),
14551 Selector_Name => Make_Identifier (Loc, Name_uSize)));
14552
14553 else
14554 Append_To (Args,
14555 New_Occurrence_Of (Storage_Size_Variable (Ttyp), Loc));
14556 end if;
14557
14558 -- Secondary_Stack parameter used for restricted profiles
14559
14560 if Restricted_Profile then
14561
14562 -- If the secondary stack has been allocated by the expander then
14563 -- pass its access pointer. Otherwise, pass null.
14564
14565 if Create_Secondary_Stack_For_Task (Ttyp) then
14566 Append_To (Args,
14567 Make_Attribute_Reference (Loc,
14568 Prefix =>
14569 Make_Selected_Component (Loc,
14570 Prefix => Make_Identifier (Loc, Name_uInit),
14571 Selector_Name =>
14572 Make_Identifier (Loc, Name_uSecondary_Stack)),
14573 Attribute_Name => Name_Unrestricted_Access));
14574
14575 else
14576 Append_To (Args, Make_Null (Loc));
14577 end if;
14578 end if;
14579
14580 -- Secondary_Stack_Size parameter. Set RE_Unspecified_Size unless there
14581 -- is a Secondary_Stack_Size pragma, in which case take the value from
14582 -- the pragma. If the restriction No_Secondary_Stack is active then a
14583 -- size of 0 is passed regardless to prevent the allocation of the
14584 -- unused stack.
14585
14586 if Restriction_Active (No_Secondary_Stack) then
14587 Append_To (Args, Make_Integer_Literal (Loc, 0));
14588
14589 elsif Has_Rep_Pragma
14590 (Ttyp, Name_Secondary_Stack_Size, Check_Parents => False)
14591 then
14592 Append_To (Args,
14593 Make_Selected_Component (Loc,
14594 Prefix => Make_Identifier (Loc, Name_uInit),
14595 Selector_Name =>
14596 Make_Identifier (Loc, Name_uSecondary_Stack_Size)));
14597
14598 else
14599 Append_To (Args,
14600 New_Occurrence_Of (RTE (RE_Unspecified_Size), Loc));
14601 end if;
14602
14603 -- Task_Info parameter. Set to Unspecified_Task_Info unless there is a
14604 -- Task_Info pragma, in which case we take the value from the pragma.
14605
14606 if Has_Rep_Pragma (Ttyp, Name_Task_Info, Check_Parents => False) then
14607 Append_To (Args,
14608 Make_Selected_Component (Loc,
14609 Prefix => Make_Identifier (Loc, Name_uInit),
14610 Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
14611
14612 else
14613 Append_To (Args,
14614 New_Occurrence_Of (RTE (RE_Unspecified_Task_Info), Loc));
14615 end if;
14616
14617 -- CPU parameter. Set to Unspecified_CPU unless there is a CPU rep item,
14618 -- in which case we take the value from the rep item. The parameter is
14619 -- passed as an Integer because in the case of unspecified CPU the
14620 -- value is not in the range of CPU_Range.
14621
14622 if Has_Rep_Item (Ttyp, Name_CPU, Check_Parents => False) then
14623 Append_To (Args,
14624 Convert_To (Standard_Integer,
14625 Make_Selected_Component (Loc,
14626 Prefix => Make_Identifier (Loc, Name_uInit),
14627 Selector_Name => Make_Identifier (Loc, Name_uCPU))));
14628 else
14629 Append_To (Args,
14630 New_Occurrence_Of (RTE (RE_Unspecified_CPU), Loc));
14631 end if;
14632
14633 if not Restricted_Profile or else Task_Dispatching_Policy = 'E' then
14634
14635 -- Deadline parameter. If no Relative_Deadline pragma is present,
14636 -- then the deadline is Time_Span_Zero. If a pragma is present, then
14637 -- the deadline is taken from the _Relative_Deadline field of the
14638 -- task value record, which was set from the pragma value. Note that
14639 -- this parameter must not be generated for the restricted profiles
14640 -- since Ravenscar does not allow deadlines.
14641
14642 -- Case where pragma Relative_Deadline applies: use given value
14643
14644 if Present (Tdef) and then Has_Relative_Deadline_Pragma (Tdef) then
14645 Append_To (Args,
14646 Make_Selected_Component (Loc,
14647 Prefix => Make_Identifier (Loc, Name_uInit),
14648 Selector_Name =>
14649 Make_Identifier (Loc, Name_uRelative_Deadline)));
14650
14651 -- No pragma Relative_Deadline apply to the task
14652
14653 else
14654 Append_To (Args,
14655 New_Occurrence_Of (RTE (RE_Time_Span_Zero), Loc));
14656 end if;
14657 end if;
14658
14659 if not Restricted_Profile then
14660
14661 -- Dispatching_Domain parameter. If no Dispatching_Domain rep item is
14662 -- present, then the dispatching domain is null. If a rep item is
14663 -- present, then the dispatching domain is taken from the
14664 -- _Dispatching_Domain field of the task value record, which was set
14665 -- from the rep item value.
14666
14667 -- Case where Dispatching_Domain rep item applies: use given value
14668
14669 if Has_Rep_Item
14670 (Ttyp, Name_Dispatching_Domain, Check_Parents => False)
14671 then
14672 Append_To (Args,
14673 Make_Selected_Component (Loc,
14674 Prefix =>
14675 Make_Identifier (Loc, Name_uInit),
14676 Selector_Name =>
14677 Make_Identifier (Loc, Name_uDispatching_Domain)));
14678
14679 -- No pragma or aspect Dispatching_Domain applies to the task
14680
14681 else
14682 Append_To (Args, Make_Null (Loc));
14683 end if;
14684
14685 -- Number of entries. This is an expression of the form:
14686
14687 -- n + _Init.a'Length + _Init.a'B'Length + ...
14688
14689 -- where a,b... are the entry family names for the task definition
14690
14691 Ecount :=
14692 Build_Entry_Count_Expression
14693 (Ttyp,
14694 Component_Items
14695 (Component_List
14696 (Type_Definition
14697 (Parent (Corresponding_Record_Type (Ttyp))))),
14698 Loc);
14699 Append_To (Args, Ecount);
14700
14701 -- Master parameter. This is a reference to the _Master parameter of
14702 -- the initialization procedure, except in the case of the pragma
14703 -- Restrictions (No_Task_Hierarchy) where the value is fixed to
14704 -- System.Tasking.Library_Task_Level.
14705
14706 if Restriction_Active (No_Task_Hierarchy) = False then
14707 Append_To (Args, Make_Identifier (Loc, Name_uMaster));
14708 else
14709 Append_To (Args,
14710 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
14711 end if;
14712 end if;
14713
14714 -- State parameter. This is a pointer to the task body procedure. The
14715 -- required value is obtained by taking 'Unrestricted_Access of the task
14716 -- body procedure and converting it (with an unchecked conversion) to
14717 -- the type required by the task kernel. For further details, see the
14718 -- description of Expand_N_Task_Body. We use 'Unrestricted_Access rather
14719 -- than 'Address in order to avoid creating trampolines.
14720
14721 declare
14722 Body_Proc : constant Node_Id := Get_Task_Body_Procedure (Ttyp);
14723 Subp_Ptr_Typ : constant Node_Id :=
14724 Create_Itype (E_Access_Subprogram_Type, Tdec);
14725 Ref : constant Node_Id := Make_Itype_Reference (Loc);
14726
14727 begin
14728 Set_Directly_Designated_Type (Subp_Ptr_Typ, Body_Proc);
14729 Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
14730
14731 -- Be sure to freeze a reference to the access-to-subprogram type,
14732 -- otherwise gigi will complain that it's in the wrong scope, because
14733 -- it's actually inside the init procedure for the record type that
14734 -- corresponds to the task type.
14735
14736 Set_Itype (Ref, Subp_Ptr_Typ);
14737 Append_Freeze_Action (Task_Rec, Ref);
14738
14739 Append_To (Args,
14740 Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
14741 Make_Qualified_Expression (Loc,
14742 Subtype_Mark => New_Occurrence_Of (Subp_Ptr_Typ, Loc),
14743 Expression =>
14744 Make_Attribute_Reference (Loc,
14745 Prefix => New_Occurrence_Of (Body_Proc, Loc),
14746 Attribute_Name => Name_Unrestricted_Access))));
14747 end;
14748
14749 -- Discriminants parameter. This is just the address of the task
14750 -- value record itself (which contains the discriminant values
14751
14752 Append_To (Args,
14753 Make_Attribute_Reference (Loc,
14754 Prefix => Make_Identifier (Loc, Name_uInit),
14755 Attribute_Name => Name_Address));
14756
14757 -- Elaborated parameter. This is an access to the elaboration Boolean
14758
14759 Append_To (Args,
14760 Make_Attribute_Reference (Loc,
14761 Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
14762 Attribute_Name => Name_Unchecked_Access));
14763
14764 -- Add Chain parameter (not done for sequential elaboration policy, see
14765 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
14766
14767 if Partition_Elaboration_Policy /= 'S' then
14768 Append_To (Args, Make_Identifier (Loc, Name_uChain));
14769 end if;
14770
14771 -- Task name parameter. Take this from the _Task_Id parameter to the
14772 -- init call unless there is a Task_Name pragma, in which case we take
14773 -- the value from the pragma.
14774
14775 if Has_Rep_Pragma (Ttyp, Name_Task_Name, Check_Parents => False) then
14776 -- Copy expression in full, because it may be dynamic and have
14777 -- side effects.
14778
14779 Append_To (Args,
14780 New_Copy_Tree
14781 (Expression
14782 (First
14783 (Pragma_Argument_Associations
14784 (Get_Rep_Pragma
14785 (Ttyp, Name_Task_Name, Check_Parents => False))))));
14786
14787 else
14788 Append_To (Args, Make_Identifier (Loc, Name_uTask_Name));
14789 end if;
14790
14791 -- Created_Task parameter. This is the _Task_Id field of the task
14792 -- record value
14793
14794 Append_To (Args,
14795 Make_Selected_Component (Loc,
14796 Prefix => Make_Identifier (Loc, Name_uInit),
14797 Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
14798
14799 declare
14800 Create_RE : RE_Id;
14801
14802 begin
14803 if Restricted_Profile then
14804 if Partition_Elaboration_Policy = 'S' then
14805 Create_RE := RE_Create_Restricted_Task_Sequential;
14806 else
14807 Create_RE := RE_Create_Restricted_Task;
14808 end if;
14809 else
14810 Create_RE := RE_Create_Task;
14811 end if;
14812
14813 Name := New_Occurrence_Of (RTE (Create_RE), Loc);
14814 end;
14815
14816 return
14817 Make_Procedure_Call_Statement (Loc,
14818 Name => Name,
14819 Parameter_Associations => Args);
14820 end Make_Task_Create_Call;
14821
14822 ------------------------------
14823 -- Next_Protected_Operation --
14824 ------------------------------
14825
14826 function Next_Protected_Operation (N : Node_Id) return Node_Id is
14827 Next_Op : Node_Id;
14828
14829 begin
14830 -- Check whether there is a subsequent body for a protected operation
14831 -- in the current protected body. In Ada2012 that includes expression
14832 -- functions that are completions.
14833
14834 Next_Op := Next (N);
14835 while Present (Next_Op)
14836 and then Nkind (Next_Op) not in
14837 N_Subprogram_Body | N_Entry_Body | N_Expression_Function
14838 loop
14839 Next (Next_Op);
14840 end loop;
14841
14842 return Next_Op;
14843 end Next_Protected_Operation;
14844
14845 ---------------------
14846 -- Null_Statements --
14847 ---------------------
14848
14849 function Null_Statements (Stats : List_Id) return Boolean is
14850 Stmt : Node_Id;
14851
14852 begin
14853 Stmt := First (Stats);
14854 while Nkind (Stmt) /= N_Empty
14855 and then (Nkind (Stmt) in N_Null_Statement | N_Label
14856 or else
14857 (Nkind (Stmt) = N_Pragma
14858 and then
14859 Pragma_Name_Unmapped (Stmt) in Name_Unreferenced
14860 | Name_Unmodified
14861 | Name_Warnings))
14862 loop
14863 Next (Stmt);
14864 end loop;
14865
14866 return Nkind (Stmt) = N_Empty;
14867 end Null_Statements;
14868
14869 --------------------------
14870 -- Parameter_Block_Pack --
14871 --------------------------
14872
14873 function Parameter_Block_Pack
14874 (Loc : Source_Ptr;
14875 Blk_Typ : Entity_Id;
14876 Actuals : List_Id;
14877 Formals : List_Id;
14878 Decls : List_Id;
14879 Stmts : List_Id) return Node_Id
14880 is
14881 Actual : Entity_Id;
14882 Expr : Node_Id := Empty;
14883 Formal : Entity_Id;
14884 Has_Param : Boolean := False;
14885 P : Entity_Id;
14886 Params : List_Id;
14887 Temp_Asn : Node_Id;
14888 Temp_Nam : Node_Id;
14889
14890 begin
14891 Actual := First (Actuals);
14892 Formal := Defining_Identifier (First (Formals));
14893 Params := New_List;
14894 while Present (Actual) loop
14895 if Is_By_Copy_Type (Etype (Actual)) then
14896 -- Generate:
14897 -- Jnn : aliased <formal-type>
14898
14899 Temp_Nam := Make_Temporary (Loc, 'J');
14900
14901 Append_To (Decls,
14902 Make_Object_Declaration (Loc,
14903 Aliased_Present => True,
14904 Defining_Identifier => Temp_Nam,
14905 Object_Definition =>
14906 New_Occurrence_Of (Etype (Formal), Loc)));
14907
14908 -- The object is initialized with an explicit assignment
14909 -- later. Indicate that it does not need an initialization
14910 -- to prevent spurious warnings if the type excludes null.
14911
14912 Set_No_Initialization (Last (Decls));
14913
14914 if Ekind (Formal) /= E_Out_Parameter then
14915
14916 -- Generate:
14917 -- Jnn := <actual>
14918
14919 Temp_Asn :=
14920 New_Occurrence_Of (Temp_Nam, Loc);
14921
14922 Set_Assignment_OK (Temp_Asn);
14923
14924 Append_To (Stmts,
14925 Make_Assignment_Statement (Loc,
14926 Name => Temp_Asn,
14927 Expression => New_Copy_Tree (Actual)));
14928 end if;
14929
14930 -- If the actual is not controlling, generate:
14931
14932 -- Jnn'unchecked_access
14933
14934 -- and add it to aggegate for access to formals. Note that the
14935 -- actual may be by-copy but still be a controlling actual if it
14936 -- is an access to class-wide interface.
14937
14938 if not Is_Controlling_Actual (Actual) then
14939 Append_To (Params,
14940 Make_Attribute_Reference (Loc,
14941 Attribute_Name => Name_Unchecked_Access,
14942 Prefix => New_Occurrence_Of (Temp_Nam, Loc)));
14943
14944 Has_Param := True;
14945 end if;
14946
14947 -- The controlling parameter is omitted
14948
14949 else
14950 if not Is_Controlling_Actual (Actual) then
14951 Append_To (Params,
14952 Make_Reference (Loc, New_Copy_Tree (Actual)));
14953
14954 Has_Param := True;
14955 end if;
14956 end if;
14957
14958 Next_Actual (Actual);
14959 Next_Formal_With_Extras (Formal);
14960 end loop;
14961
14962 if Has_Param then
14963 Expr := Make_Aggregate (Loc, Params);
14964 end if;
14965
14966 -- Generate:
14967 -- P : Ann := (
14968 -- J1'unchecked_access;
14969 -- <actual2>'reference;
14970 -- ...);
14971
14972 P := Make_Temporary (Loc, 'P');
14973
14974 Append_To (Decls,
14975 Make_Object_Declaration (Loc,
14976 Defining_Identifier => P,
14977 Object_Definition => New_Occurrence_Of (Blk_Typ, Loc),
14978 Expression => Expr));
14979
14980 return P;
14981 end Parameter_Block_Pack;
14982
14983 ----------------------------
14984 -- Parameter_Block_Unpack --
14985 ----------------------------
14986
14987 function Parameter_Block_Unpack
14988 (Loc : Source_Ptr;
14989 P : Entity_Id;
14990 Actuals : List_Id;
14991 Formals : List_Id) return List_Id
14992 is
14993 Actual : Entity_Id;
14994 Asnmt : Node_Id;
14995 Formal : Entity_Id;
14996 Has_Asnmt : Boolean := False;
14997 Result : constant List_Id := New_List;
14998
14999 begin
15000 Actual := First (Actuals);
15001 Formal := Defining_Identifier (First (Formals));
15002 while Present (Actual) loop
15003 if Is_By_Copy_Type (Etype (Actual))
15004 and then Ekind (Formal) /= E_In_Parameter
15005 then
15006 -- Generate:
15007 -- <actual> := P.<formal>;
15008
15009 Asnmt :=
15010 Make_Assignment_Statement (Loc,
15011 Name =>
15012 New_Copy (Actual),
15013 Expression =>
15014 Make_Explicit_Dereference (Loc,
15015 Make_Selected_Component (Loc,
15016 Prefix =>
15017 New_Occurrence_Of (P, Loc),
15018 Selector_Name =>
15019 Make_Identifier (Loc, Chars (Formal)))));
15020
15021 Set_Assignment_OK (Name (Asnmt));
15022 Append_To (Result, Asnmt);
15023
15024 Has_Asnmt := True;
15025 end if;
15026
15027 Next_Actual (Actual);
15028 Next_Formal_With_Extras (Formal);
15029 end loop;
15030
15031 if Has_Asnmt then
15032 return Result;
15033 else
15034 return New_List (Make_Null_Statement (Loc));
15035 end if;
15036 end Parameter_Block_Unpack;
15037
15038 ---------------------
15039 -- Reset_Scopes_To --
15040 ---------------------
15041
15042 procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id) is
15043 function Reset_Scope (N : Node_Id) return Traverse_Result;
15044 -- Temporaries may have been declared during expansion of the procedure
15045 -- created for an entry body or an accept alternative. Indicate that
15046 -- their scope is the new body, to ensure proper generation of uplevel
15047 -- references where needed during unnesting.
15048
15049 procedure Reset_Scopes is new Traverse_Proc (Reset_Scope);
15050
15051 -----------------
15052 -- Reset_Scope --
15053 -----------------
15054
15055 function Reset_Scope (N : Node_Id) return Traverse_Result is
15056 Decl : Node_Id;
15057
15058 begin
15059 -- If this is a block statement with an Identifier, it forms a scope,
15060 -- so we want to reset its scope but not look inside.
15061
15062 if N /= Bod
15063 and then Nkind (N) = N_Block_Statement
15064 and then Present (Identifier (N))
15065 then
15066 Set_Scope (Entity (Identifier (N)), E);
15067 return Skip;
15068
15069 -- Ditto for a package declaration or a full type declaration, etc.
15070
15071 elsif (Nkind (N) = N_Package_Declaration
15072 and then N /= Specification (N))
15073 or else Nkind (N) in N_Declaration
15074 or else Nkind (N) in N_Renaming_Declaration
15075 then
15076 Set_Scope (Defining_Entity (N), E);
15077 return Skip;
15078
15079 elsif N = Bod then
15080
15081 -- Scan declarations in new body. Declarations in the statement
15082 -- part will be handled during later traversal.
15083
15084 Decl := First (Declarations (N));
15085 while Present (Decl) loop
15086 Reset_Scopes (Decl);
15087 Next (Decl);
15088 end loop;
15089
15090 elsif Nkind (N) = N_Freeze_Entity then
15091
15092 -- Scan the actions associated with a freeze node, which may
15093 -- actually be declarations with entities that need to have
15094 -- their scopes reset.
15095
15096 Decl := First (Actions (N));
15097 while Present (Decl) loop
15098 Reset_Scopes (Decl);
15099 Next (Decl);
15100 end loop;
15101
15102 elsif N /= Bod and then Nkind (N) in N_Proper_Body then
15103
15104 -- A subprogram without a separate declaration may be encountered,
15105 -- and we need to reset the subprogram's entity's scope.
15106
15107 if Nkind (N) = N_Subprogram_Body then
15108 Set_Scope (Defining_Entity (Specification (N)), E);
15109 end if;
15110
15111 return Skip;
15112 end if;
15113
15114 return OK;
15115 end Reset_Scope;
15116
15117 -- Start of processing for Reset_Scopes_To
15118
15119 begin
15120 Reset_Scopes (Bod);
15121 end Reset_Scopes_To;
15122
15123 ----------------------
15124 -- Set_Discriminals --
15125 ----------------------
15126
15127 procedure Set_Discriminals (Dec : Node_Id) is
15128 D : Entity_Id;
15129 Pdef : Entity_Id;
15130 D_Minal : Entity_Id;
15131
15132 begin
15133 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
15134 Pdef := Defining_Identifier (Dec);
15135
15136 if Has_Discriminants (Pdef) then
15137 D := First_Discriminant (Pdef);
15138 while Present (D) loop
15139 D_Minal :=
15140 Make_Defining_Identifier (Sloc (D),
15141 Chars => New_External_Name (Chars (D), 'D'));
15142
15143 Set_Ekind (D_Minal, E_Constant);
15144 Set_Etype (D_Minal, Etype (D));
15145 Set_Scope (D_Minal, Pdef);
15146 Set_Discriminal (D, D_Minal);
15147 Set_Discriminal_Link (D_Minal, D);
15148
15149 Next_Discriminant (D);
15150 end loop;
15151 end if;
15152 end Set_Discriminals;
15153
15154 -----------------------
15155 -- Trivial_Accept_OK --
15156 -----------------------
15157
15158 function Trivial_Accept_OK return Boolean is
15159 begin
15160 case Opt.Task_Dispatching_Policy is
15161
15162 -- If we have the default task dispatching policy in effect, we can
15163 -- definitely do the optimization (one way of looking at this is to
15164 -- think of the formal definition of the default policy being allowed
15165 -- to run any task it likes after a rendezvous, so even if notionally
15166 -- a full rescheduling occurs, we can say that our dispatching policy
15167 -- (i.e. the default dispatching policy) reorders the queue to be the
15168 -- same as just before the call.
15169
15170 when ' ' =>
15171 return True;
15172
15173 -- FIFO_Within_Priorities certainly does not permit this
15174 -- optimization since the Rendezvous is a scheduling action that may
15175 -- require some other task to be run.
15176
15177 when 'F' =>
15178 return False;
15179
15180 -- For now, disallow the optimization for all other policies. This
15181 -- may be over-conservative, but it is certainly not incorrect.
15182
15183 when others =>
15184 return False;
15185 end case;
15186 end Trivial_Accept_OK;
15187
15188 end Exp_Ch9;