]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/exp_ch9.adb
2015-11-13 Hristian Kirtchev <kirtchev@adacore.com>
[thirdparty/gcc.git] / gcc / ada / exp_ch9.adb
CommitLineData
ee6ba406 1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ C H 9 --
6-- --
7-- B o d y --
8-- --
8149276d 9-- Copyright (C) 1992-2015, Free Software Foundation, Inc. --
ee6ba406 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- --
80df182a 13-- ware Foundation; either version 3, or (at your option) any later ver- --
ee6ba406 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 --
80df182a 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. --
ee6ba406 20-- --
21-- GNAT was originally developed by the GNAT team at New York University. --
e78e8c8e 22-- Extensive contributions were provided by Ada Core Technologies Inc. --
ee6ba406 23-- --
24------------------------------------------------------------------------------
25
26with Atree; use Atree;
27with Checks; use Checks;
28with Einfo; use Einfo;
29with Elists; use Elists;
30with Errout; use Errout;
31with Exp_Ch3; use Exp_Ch3;
ee6ba406 32with Exp_Ch6; use Exp_Ch6;
9a479e51 33with Exp_Ch11; use Exp_Ch11;
ee6ba406 34with Exp_Dbug; use Exp_Dbug;
a652dd51 35with Exp_Disp; use Exp_Disp;
952af0b9 36with Exp_Sel; use Exp_Sel;
ee6ba406 37with Exp_Smem; use Exp_Smem;
38with Exp_Tss; use Exp_Tss;
39with Exp_Util; use Exp_Util;
40with Freeze; use Freeze;
41with Hostparm;
57993a53 42with Itypes; use Itypes;
43with Namet; use Namet;
ee6ba406 44with Nlists; use Nlists;
45with Nmake; use Nmake;
46with Opt; use Opt;
47with Restrict; use Restrict;
1e16c51c 48with Rident; use Rident;
ee6ba406 49with Rtsfind; use Rtsfind;
50with Sem; use Sem;
d60c9ff7 51with Sem_Aux; use Sem_Aux;
9f373bb8 52with Sem_Ch6; use Sem_Ch6;
ee6ba406 53with Sem_Ch8; use Sem_Ch8;
7413d80d 54with Sem_Ch9; use Sem_Ch9;
ee6ba406 55with Sem_Ch11; use Sem_Ch11;
56with Sem_Elab; use Sem_Elab;
0b16c8b7 57with Sem_Eval; use Sem_Eval;
ee6ba406 58with Sem_Res; use Sem_Res;
59with Sem_Util; use Sem_Util;
60with Sinfo; use Sinfo;
61with Snames; use Snames;
62with Stand; use Stand;
f89cc618 63with Stringt; use Stringt;
fb4b3501 64with Targparm; use Targparm;
ee6ba406 65with Tbuild; use Tbuild;
ee6ba406 66with Uintp; use Uintp;
ee6ba406 67
68package body Exp_Ch9 is
69
76a1c25b 70 -- The following constant establishes the upper bound for the index of
71 -- an entry family. It is used to limit the allocated size of protected
72 -- types with defaulted discriminant of an integer type, when the bound
78be29d1 73 -- of some entry family depends on a discriminant. The limitation to entry
74 -- families of 128K should be reasonable in all cases, and is a documented
75 -- implementation restriction.
76a1c25b 76
77 Entry_Family_Bound : constant Int := 2**16;
78
ee6ba406 79 -----------------------
80 -- Local Subprograms --
81 -----------------------
82
83 function Actual_Index_Expression
84 (Sloc : Source_Ptr;
85 Ent : Entity_Id;
86 Index : Node_Id;
bdd64cbe 87 Tsk : Entity_Id) return Node_Id;
57993a53 88 -- Compute the index position for an entry call. Tsk is the target task. If
89 -- the bounds of some entry family depend on discriminants, the expression
90 -- computed by this function uses the discriminants of the target task.
ee6ba406 91
ee6ba406 92 procedure Add_Object_Pointer
57993a53 93 (Loc : Source_Ptr;
94 Conc_Typ : Entity_Id;
95 Decls : List_Id);
96 -- Prepend an object pointer declaration to the declaration list Decls.
97 -- This object pointer is initialized to a type conversion of the System.
98 -- Address pointer passed to entry barrier functions and entry body
99 -- procedures.
ee6ba406 100
76a1c25b 101 procedure Add_Formal_Renamings
102 (Spec : Node_Id;
103 Decls : List_Id;
104 Ent : Entity_Id;
105 Loc : Source_Ptr);
57993a53 106 -- Create renaming declarations for the formals, inside the procedure that
107 -- implements an entry body. The renamings make the original names of the
108 -- formals accessible to gdb, and serve no other purpose.
76a1c25b 109 -- Spec is the specification of the procedure being built.
110 -- Decls is the list of declarations to be enhanced.
111 -- Ent is the entity for the original entry body.
112
d62940bf 113 function Build_Accept_Body (Astat : Node_Id) return Node_Id;
ee6ba406 114 -- Transform accept statement into a block with added exception handler.
115 -- Used both for simple accept statements and for accept alternatives in
116 -- select statements. Astat is the accept statement.
117
118 function Build_Barrier_Function
357dd91a 119 (N : Node_Id;
120 Ent : Entity_Id;
121 Pid : Node_Id) return Node_Id;
ee6ba406 122 -- Build the function body returning the value of the barrier expression
123 -- for the specified entry body.
124
125 function Build_Barrier_Function_Specification
57993a53 126 (Loc : Source_Ptr;
127 Def_Id : Entity_Id) return Node_Id;
128 -- Build a specification for a function implementing the protected entry
129 -- barrier of the specified entry body.
ee6ba406 130
3ff5e35d 131 procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id);
132 -- Build the body of a wrapper procedure for an entry or entry family that
133 -- has contract cases, preconditions, or postconditions. The body gathers
134 -- the executable contract items and expands them in the usual way, and
135 -- performs the entry call itself. This way preconditions are evaluated
136 -- before the call is queued. E is the entry in question, and Decl is the
137 -- enclosing synchronized type declaration at whose freeze point the
138 -- generated body is analyzed.
139
64988bb0 140 function Build_Corresponding_Record
141 (N : Node_Id;
142 Ctyp : Node_Id;
143 Loc : Source_Ptr) return Node_Id;
144 -- Common to tasks and protected types. Copy discriminant specifications,
145 -- build record declaration. N is the type declaration, Ctyp is the
146 -- concurrent entity (task type or protected type).
147
37c6e44c 148 function Build_Dispatching_Tag_Check
149 (K : Entity_Id;
150 N : Node_Id) return Node_Id;
151 -- Utility to create the tree to check whether the dispatching call in
152 -- a timed entry call, a conditional entry call, or an asynchronous
153 -- transfer of control is a call to a primitive of a non-synchronized type.
154 -- K is the temporary that holds the tagged kind of the target object, and
155 -- N is the enclosing construct.
156
ee6ba406 157 function Build_Entry_Count_Expression
158 (Concurrent_Type : Node_Id;
159 Component_List : List_Id;
bdd64cbe 160 Loc : Source_Ptr) return Node_Id;
ee6ba406 161 -- Compute number of entries for concurrent object. This is a count of
162 -- simple entries, followed by an expression that computes the length
163 -- of the range of each entry family. A single array with that size is
164 -- allocated for each concurrent object of the type.
165
7a19298b 166 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
167 -- Build the function that translates the entry index in the call
168 -- (which depends on the size of entry families) into an index into the
169 -- Entry_Bodies_Array, to determine the body and barrier function used
170 -- in a protected entry call. A pointer to this function appears in every
171 -- protected object.
172
173 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
174 -- Build subprogram declaration for previous one
175
176 function Build_Lock_Free_Protected_Subprogram_Body
e12ab46d 177 (N : Node_Id;
178 Prot_Typ : Node_Id;
179 Unprot_Spec : Node_Id) return Node_Id;
180 -- N denotes a subprogram body of protected type Prot_Typ. Unprot_Spec is
181 -- the subprogram specification of the unprotected version of N. Transform
182 -- N such that it invokes the unprotected version of the body.
7a19298b 183
184 function Build_Lock_Free_Unprotected_Subprogram_Body
e12ab46d 185 (N : Node_Id;
186 Prot_Typ : Node_Id) return Node_Id;
187 -- N denotes a subprogram body of protected type Prot_Typ. Build a version
188 -- of N where the original statements of N are synchronized through atomic
189 -- actions such as compare and exchange. Prior to invoking this routine, it
190 -- has been established that N can be implemented in a lock-free fashion.
7a19298b 191
d62940bf 192 function Build_Parameter_Block
193 (Loc : Source_Ptr;
194 Actuals : List_Id;
195 Formals : List_Id;
196 Decls : List_Id) return Entity_Id;
197 -- Generate an access type for each actual parameter in the list Actuals.
36b938a3 198 -- Create an encapsulating record that contains all the actuals and return
d62940bf 199 -- its type. Generate:
200 -- type Ann1 is access all <actual1-type>
201 -- ...
202 -- type AnnN is access all <actualN-type>
203 -- type Pnn is record
204 -- <formal1> : Ann1;
205 -- ...
206 -- <formalN> : AnnN;
207 -- end record;
208
ee6ba406 209 function Build_Protected_Entry
bdd64cbe 210 (N : Node_Id;
211 Ent : Entity_Id;
212 Pid : Node_Id) return Node_Id;
57993a53 213 -- Build the procedure implementing the statement sequence of the specified
214 -- entry body.
ee6ba406 215
216 function Build_Protected_Entry_Specification
57993a53 217 (Loc : Source_Ptr;
218 Def_Id : Entity_Id;
219 Ent_Id : Entity_Id) return Node_Id;
2c145f84 220 -- Build a specification for the procedure implementing the statements of
57993a53 221 -- the specified entry body. Add attributes associating it with the entry
222 -- defining identifier Ent_Id.
223
224 function Build_Protected_Spec
225 (N : Node_Id;
226 Obj_Type : Entity_Id;
227 Ident : Entity_Id;
228 Unprotected : Boolean := False) return List_Id;
229 -- Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
230 -- Subprogram_Type. Builds signature of protected subprogram, adding the
231 -- formal that corresponds to the object itself. For an access to protected
232 -- subprogram, there is no object type to specify, so the parameter has
233 -- type Address and mode In. An indirect call through such a pointer will
234 -- convert the address to a reference to the actual object. The object is
235 -- a limited record and therefore a by_reference type.
ee6ba406 236
237 function Build_Protected_Subprogram_Body
238 (N : Node_Id;
239 Pid : Node_Id;
bdd64cbe 240 N_Op_Spec : Node_Id) return Node_Id;
ee6ba406 241 -- This function is used to construct the protected version of a protected
78be29d1 242 -- subprogram. Its statement sequence first defers abort, then locks the
243 -- associated protected object, and then enters a block that contains a
244 -- call to the unprotected version of the subprogram (for details, see
245 -- Build_Unprotected_Subprogram_Body). This block statement requires a
246 -- cleanup handler that unlocks the object in all cases. For details,
247 -- see Exp_Ch7.Expand_Cleanup_Actions.
ee6ba406 248
7a19298b 249 function Build_Renamed_Formal_Declaration
250 (New_F : Entity_Id;
251 Formal : Entity_Id;
252 Comp : Entity_Id;
253 Renamed_Formal : Node_Id) return Node_Id;
254 -- Create a renaming declaration for a formal, within a protected entry
255 -- body or an accept body. The renamed object is a component of the
256 -- parameter block that is a parameter in the entry call.
257 --
258 -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
259 -- does not dereference the corresponding component to prevent an illegal
260 -- use of the incomplete type (AI05-0151).
261
ee6ba406 262 function Build_Selected_Name
76a1c25b 263 (Prefix : Entity_Id;
264 Selector : Entity_Id;
265 Append_Char : Character := ' ') return Name_Id;
78be29d1 266 -- Build a name in the form of Prefix__Selector, with an optional character
267 -- appended. This is used for internal subprograms generated for operations
268 -- of protected types, including barrier functions. For the subprograms
269 -- generated for entry bodies and entry barriers, the generated name
270 -- includes a sequence number that makes names unique in the presence of
271 -- entry overloading. This is necessary because entry body procedures and
272 -- barrier functions all have the same signature.
ee6ba406 273
274 procedure Build_Simple_Entry_Call
275 (N : Node_Id;
276 Concval : Node_Id;
277 Ename : Node_Id;
278 Index : Node_Id);
279 -- Some comments here would be useful ???
280
281 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
282 -- This routine constructs a specification for the procedure that we will
283 -- build for the task body for task type T. The spec has the form:
284 --
285 -- procedure tnameB (_Task : access tnameV);
286 --
287 -- where name is the character name taken from the task type entity that
288 -- is passed as the argument to the procedure, and tnameV is the task
289 -- value type that is associated with the task type.
290
291 function Build_Unprotected_Subprogram_Body
bdd64cbe 292 (N : Node_Id;
293 Pid : Node_Id) return Node_Id;
ee6ba406 294 -- This routine constructs the unprotected version of a protected
7ee08bca 295 -- subprogram body, which is contains all of the code in the original,
296 -- unexpanded body. This is the version of the protected subprogram that is
297 -- called from all protected operations on the same object, including the
298 -- protected version of the same subprogram.
ee6ba406 299
7a19298b 300 procedure Build_Wrapper_Bodies
301 (Loc : Source_Ptr;
302 Typ : Entity_Id;
303 N : Node_Id);
304 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
305 -- record of a concurrent type. N is the insertion node where all bodies
306 -- will be placed. This routine builds the bodies of the subprograms which
307 -- serve as an indirection mechanism to overriding primitives of concurrent
308 -- types, entries and protected procedures. Any new body is analyzed.
309
310 procedure Build_Wrapper_Specs
311 (Loc : Source_Ptr;
312 Typ : Entity_Id;
313 N : in out Node_Id);
314 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
315 -- record of a concurrent type. N is the insertion node where all specs
316 -- will be placed. This routine builds the specs of the subprograms which
317 -- serve as an indirection mechanism to overriding primitives of concurrent
318 -- types, entries and protected procedures. Any new spec is analyzed.
319
ee6ba406 320 procedure Collect_Entry_Families
321 (Loc : Source_Ptr;
322 Cdecls : List_Id;
323 Current_Node : in out Node_Id;
324 Conctyp : Entity_Id);
325 -- For each entry family in a concurrent type, create an anonymous array
326 -- type of the right size, and add a component to the corresponding_record.
327
57993a53 328 function Concurrent_Object
329 (Spec_Id : Entity_Id;
330 Conc_Typ : Entity_Id) return Entity_Id;
331 -- Given a subprogram entity Spec_Id and concurrent type Conc_Typ, return
332 -- the entity associated with the concurrent object in the Protected_Body_
333 -- Subprogram or the Task_Body_Procedure of Spec_Id. The returned entity
334 -- denotes formal parameter _O, _object or _task.
335
4961db87 336 function Copy_Result_Type (Res : Node_Id) return Node_Id;
337 -- Copy the result type of a function specification, when building the
338 -- internal operation corresponding to a protected function, or when
339 -- expanding an access to protected function. If the result is an anonymous
340 -- access to subprogram itself, we need to create a new signature with the
341 -- same parameter names and the same resolved types, but with new entities
342 -- for the formals.
343
57993a53 344 procedure Debug_Private_Data_Declarations (Decls : List_Id);
345 -- Decls is a list which may contain the declarations created by Install_
346 -- Private_Data_Declarations. All generated entities are marked as needing
347 -- debug info and debug nodes are manually generation where necessary. This
348 -- step of the expansion must to be done after private data has been moved
349 -- to its final resting scope to ensure proper visibility of debug objects.
350
e3cb8202 351 procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id);
352 -- If control flow optimizations are suppressed, and Alt is an accept,
78be29d1 353 -- delay, or entry call alternative with no trailing statements, insert
354 -- a null trailing statement with the given Loc (which is the sloc of
355 -- the accept, delay, or entry call statement). There might not be any
356 -- generated code for the accept, delay, or entry call itself (the effect
357 -- of these statements is part of the general processsing done for the
358 -- enclosing selective accept, timed entry call, or asynchronous select),
359 -- and the null statement is there to carry the sloc of that statement to
360 -- the back-end for trace-based coverage analysis purposes.
e3cb8202 361
7a19298b 362 procedure Extract_Dispatching_Call
363 (N : Node_Id;
364 Call_Ent : out Entity_Id;
365 Object : out Entity_Id;
366 Actuals : out List_Id;
367 Formals : out List_Id);
368 -- Given a dispatching call, extract the entity of the name of the call,
369 -- its actual dispatching object, its actual parameters and the formal
370 -- parameters of the overridden interface-level version. If the type of
371 -- the dispatching object is an access type then an explicit dereference
372 -- is returned in Object.
373
374 procedure Extract_Entry
375 (N : Node_Id;
376 Concval : out Node_Id;
377 Ename : out Node_Id;
378 Index : out Node_Id);
78be29d1 379 -- Given an entry call, returns the associated concurrent object, the entry
380 -- name, and the entry family index.
7a19298b 381
ee6ba406 382 function Family_Offset
383 (Loc : Source_Ptr;
384 Hi : Node_Id;
385 Lo : Node_Id;
cb5f80c1 386 Ttyp : Entity_Id;
387 Cap : Boolean) return Node_Id;
78be29d1 388 -- Compute (Hi - Lo) for two entry family indexes. Hi is the index in an
389 -- accept statement, or the upper bound in the discrete subtype of an entry
390 -- declaration. Lo is the corresponding lower bound. Ttyp is the concurrent
391 -- type of the entry. If Cap is true, the result is capped according to
392 -- Entry_Family_Bound.
ee6ba406 393
394 function Family_Size
395 (Loc : Source_Ptr;
396 Hi : Node_Id;
397 Lo : Node_Id;
cb5f80c1 398 Ttyp : Entity_Id;
399 Cap : Boolean) return Node_Id;
78be29d1 400 -- Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in a
401 -- family, and handle properly the superflat case. This is equivalent to
402 -- the use of 'Length on the index type, but must use Family_Offset to
403 -- handle properly the case of bounds that depend on discriminants. If
404 -- Cap is true, the result is capped according to Entry_Family_Bound.
ee6ba406 405
43602818 406 procedure Find_Enclosing_Context
407 (N : Node_Id;
408 Context : out Node_Id;
409 Context_Id : out Entity_Id;
410 Context_Decls : out List_Id);
411 -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
412 -- Build_Master_Entity. Given an arbitrary node in the tree, find the
3ff5e35d 413 -- nearest enclosing body, block, package, or return statement and return
43602818 414 -- its constituents. Context is the enclosing construct, Context_Id is
415 -- the scope of Context_Id and Context_Decls is the declarative list of
416 -- Context.
417
57993a53 418 function Index_Object (Spec_Id : Entity_Id) return Entity_Id;
419 -- Given a subprogram identifier, return the entity which is associated
78be29d1 420 -- with the protection entry index in the Protected_Body_Subprogram or
421 -- the Task_Body_Procedure of Spec_Id. The returned entity denotes formal
57993a53 422 -- parameter _E.
d62940bf 423
7a19298b 424 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
425 -- Tell whether a given subprogram cannot raise an exception
426
cb5f80c1 427 function Is_Potentially_Large_Family
428 (Base_Index : Entity_Id;
429 Conctyp : Entity_Id;
430 Lo : Node_Id;
431 Hi : Node_Id) return Boolean;
432
d2a42b76 433 function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean;
434 -- Determine whether Id is a function or a procedure and is marked as a
435 -- private primitive.
436
d333ad56 437 function Null_Statements (Stats : List_Id) return Boolean;
438 -- Used to check DO-END sequence. Checks for equivalent of DO NULL; END.
78be29d1 439 -- Allows labels, and pragma Warnings/Unreferenced in the sequence as well
440 -- to still count as null. Returns True for a null sequence. The argument
441 -- is the list of statements from the DO-END sequence.
d333ad56 442
d62940bf 443 function Parameter_Block_Pack
444 (Loc : Source_Ptr;
445 Blk_Typ : Entity_Id;
446 Actuals : List_Id;
447 Formals : List_Id;
448 Decls : List_Id;
76a1c25b 449 Stmts : List_Id) return Entity_Id;
78be29d1 450 -- Set the components of the generated parameter block with the values
451 -- of the actual parameters. Generate aliased temporaries to capture the
d62940bf 452 -- values for types that are passed by copy. Otherwise generate a reference
453 -- to the actual's value. Return the address of the aggregate block.
454 -- Generate:
455 -- Jnn1 : alias <formal-type1>;
456 -- Jnn1 := <actual1>;
457 -- ...
458 -- P : Blk_Typ := (
459 -- Jnn1'unchecked_access;
460 -- <actual2>'reference;
461 -- ...);
462
463 function Parameter_Block_Unpack
464 (Loc : Source_Ptr;
76a1c25b 465 P : Entity_Id;
d62940bf 466 Actuals : List_Id;
467 Formals : List_Id) return List_Id;
468 -- Retrieve the values of the components from the parameter block and
469 -- assign then to the original actual parameters. Generate:
470 -- <actual1> := P.<formal1>;
471 -- ...
472 -- <actualN> := P.<formalN>;
473
d333ad56 474 function Trivial_Accept_OK return Boolean;
475 -- If there is no DO-END block for an accept, or if the DO-END block has
476 -- only null statements, then it is possible to do the Rendezvous with much
477 -- less overhead using the Accept_Trivial routine in the run-time library.
478 -- However, this is not always a valid optimization. Whether it is valid or
479 -- not depends on the Task_Dispatching_Policy. The issue is whether a full
480 -- rescheduling action is required or not. In FIFO_Within_Priorities, such
481 -- a rescheduling is required, so this optimization is not allowed. This
482 -- function returns True if the optimization is permitted.
483
ee6ba406 484 -----------------------------
485 -- Actual_Index_Expression --
486 -----------------------------
487
488 function Actual_Index_Expression
489 (Sloc : Source_Ptr;
490 Ent : Entity_Id;
491 Index : Node_Id;
bdd64cbe 492 Tsk : Entity_Id) return Node_Id
ee6ba406 493 is
9dfe12ae 494 Ttyp : constant Entity_Id := Etype (Tsk);
ee6ba406 495 Expr : Node_Id;
496 Num : Node_Id;
497 Lo : Node_Id;
498 Hi : Node_Id;
499 Prev : Entity_Id;
500 S : Node_Id;
9dfe12ae 501
502 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
2866d595 503 -- Compute difference between bounds of entry family
ee6ba406 504
505 --------------------------
506 -- Actual_Family_Offset --
507 --------------------------
508
ee6ba406 509 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
510
511 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
512 -- Replace a reference to a discriminant with a selected component
513 -- denoting the discriminant of the target task.
514
9dfe12ae 515 -----------------------------
516 -- Actual_Discriminant_Ref --
517 -----------------------------
518
ee6ba406 519 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
9dfe12ae 520 Typ : constant Entity_Id := Etype (Bound);
ee6ba406 521 B : Node_Id;
522
523 begin
524 if not Is_Entity_Name (Bound)
525 or else Ekind (Entity (Bound)) /= E_Discriminant
526 then
527 if Nkind (Bound) = N_Attribute_Reference then
528 return Bound;
529 else
530 B := New_Copy_Tree (Bound);
531 end if;
532
533 else
534 B :=
535 Make_Selected_Component (Sloc,
7ee08bca 536 Prefix => New_Copy_Tree (Tsk),
ee6ba406 537 Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
538
539 Analyze_And_Resolve (B, Typ);
540 end if;
541
542 return
543 Make_Attribute_Reference (Sloc,
544 Attribute_Name => Name_Pos,
7ee08bca 545 Prefix => New_Occurrence_Of (Etype (Bound), Sloc),
546 Expressions => New_List (B));
ee6ba406 547 end Actual_Discriminant_Ref;
548
9dfe12ae 549 -- Start of processing for Actual_Family_Offset
550
ee6ba406 551 begin
552 return
553 Make_Op_Subtract (Sloc,
554 Left_Opnd => Actual_Discriminant_Ref (Hi),
555 Right_Opnd => Actual_Discriminant_Ref (Lo));
556 end Actual_Family_Offset;
557
9dfe12ae 558 -- Start of processing for Actual_Index_Expression
559
ee6ba406 560 begin
cb5f80c1 561 -- The queues of entries and entry families appear in textual order in
562 -- the associated record. The entry index is computed as the sum of the
563 -- number of queues for all entries that precede the designated one, to
564 -- which is added the index expression, if this expression denotes a
565 -- member of a family.
ee6ba406 566
2866d595 567 -- The following is a place holder for the count of simple entries
ee6ba406 568
569 Num := Make_Integer_Literal (Sloc, 1);
570
cb5f80c1 571 -- We construct an expression which is a series of addition operations.
572 -- See comments in Entry_Index_Expression, which is identical in
573 -- structure.
ee6ba406 574
575 if Present (Index) then
576 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
577
578 Expr :=
579 Make_Op_Add (Sloc,
580 Left_Opnd => Num,
ee6ba406 581 Right_Opnd =>
582 Actual_Family_Offset (
583 Make_Attribute_Reference (Sloc,
584 Attribute_Name => Name_Pos,
83c6c069 585 Prefix => New_Occurrence_Of (Base_Type (S), Sloc),
ee6ba406 586 Expressions => New_List (Relocate_Node (Index))),
587 Type_Low_Bound (S)));
588 else
589 Expr := Num;
590 end if;
591
2866d595 592 -- Now add lengths of preceding entries and entry families
ee6ba406 593
594 Prev := First_Entity (Ttyp);
ee6ba406 595 while Chars (Prev) /= Chars (Ent)
596 or else (Ekind (Prev) /= Ekind (Ent))
597 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
598 loop
599 if Ekind (Prev) = E_Entry then
600 Set_Intval (Num, Intval (Num) + 1);
601
602 elsif Ekind (Prev) = E_Entry_Family then
603 S :=
604 Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
5ac05a0a 605
78be29d1 606 -- The need for the following full view retrieval stems from this
607 -- complex case of nested generics and tasking:
5ac05a0a 608
609 -- generic
610 -- type Formal_Index is range <>;
611 -- ...
612 -- package Outer is
613 -- type Index is private;
614 -- generic
615 -- ...
616 -- package Inner is
617 -- procedure P;
618 -- end Inner;
619 -- private
620 -- type Index is new Formal_Index range 1 .. 10;
621 -- end Outer;
622
623 -- package body Outer is
624 -- task type T is
625 -- entry Fam (Index); -- (2)
626 -- entry E;
627 -- end T;
628 -- package body Inner is -- (3)
629 -- procedure P is
630 -- begin
631 -- T.E; -- (1)
632 -- end P;
633 -- end Inner;
634 -- ...
635
636 -- We are currently building the index expression for the entry
637 -- call "T.E" (1). Part of the expansion must mention the range
638 -- of the discrete type "Index" (2) of entry family "Fam".
78be29d1 639
5ac05a0a 640 -- However only the private view of type "Index" is available to
641 -- the inner generic (3) because there was no prior mention of
642 -- the type inside "Inner". This visibility requirement is
643 -- implicit and cannot be detected during the construction of
644 -- the generic trees and needs special handling.
645
646 if In_Instance_Body
647 and then Is_Private_Type (S)
648 and then Present (Full_View (S))
649 then
650 S := Full_View (S);
651 end if;
652
ee6ba406 653 Lo := Type_Low_Bound (S);
654 Hi := Type_High_Bound (S);
655
656 Expr :=
657 Make_Op_Add (Sloc,
658 Left_Opnd => Expr,
659 Right_Opnd =>
660 Make_Op_Add (Sloc,
c0688d2b 661 Left_Opnd => Actual_Family_Offset (Hi, Lo),
662 Right_Opnd => Make_Integer_Literal (Sloc, 1)));
ee6ba406 663
2866d595 664 -- Other components are anonymous types to be ignored
ee6ba406 665
666 else
667 null;
668 end if;
669
670 Next_Entity (Prev);
671 end loop;
672
673 return Expr;
674 end Actual_Index_Expression;
675
76a1c25b 676 --------------------------
677 -- Add_Formal_Renamings --
678 --------------------------
679
680 procedure Add_Formal_Renamings
681 (Spec : Node_Id;
682 Decls : List_Id;
683 Ent : Entity_Id;
684 Loc : Source_Ptr)
685 is
686 Ptr : constant Entity_Id :=
687 Defining_Identifier
688 (Next (First (Parameter_Specifications (Spec))));
689 -- The name of the formal that holds the address of the parameter block
690 -- for the call.
691
b76dc1f0 692 Comp : Entity_Id;
693 Decl : Node_Id;
694 Formal : Entity_Id;
695 New_F : Entity_Id;
696 Renamed_Formal : Node_Id;
76a1c25b 697
698 begin
699 Formal := First_Formal (Ent);
700 while Present (Formal) loop
57993a53 701 Comp := Entry_Component (Formal);
702 New_F :=
70966f50 703 Make_Defining_Identifier (Sloc (Formal),
704 Chars => Chars (Formal));
76a1c25b 705 Set_Etype (New_F, Etype (Formal));
706 Set_Scope (New_F, Ent);
70966f50 707
78be29d1 708 -- Now we set debug info needed on New_F even though it does not come
709 -- from source, so that the debugger will get the right information
710 -- for these generated names.
70966f50 711
712 Set_Debug_Info_Needed (New_F);
76a1c25b 713
714 if Ekind (Formal) = E_In_Parameter then
715 Set_Ekind (New_F, E_Constant);
716 else
717 Set_Ekind (New_F, E_Variable);
718 Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
719 end if;
720
721 Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
722
b76dc1f0 723 Renamed_Formal :=
724 Make_Selected_Component (Loc,
725 Prefix =>
726 Unchecked_Convert_To (Entry_Parameters_Type (Ent),
727 Make_Identifier (Loc, Chars (Ptr))),
83c6c069 728 Selector_Name => New_Occurrence_Of (Comp, Loc));
b76dc1f0 729
76a1c25b 730 Decl :=
b76dc1f0 731 Build_Renamed_Formal_Declaration
732 (New_F, Formal, Comp, Renamed_Formal);
76a1c25b 733
734 Append (Decl, Decls);
735 Set_Renamed_Object (Formal, New_F);
736 Next_Formal (Formal);
737 end loop;
738 end Add_Formal_Renamings;
739
57993a53 740 ------------------------
741 -- Add_Object_Pointer --
742 ------------------------
ee6ba406 743
57993a53 744 procedure Add_Object_Pointer
745 (Loc : Source_Ptr;
746 Conc_Typ : Entity_Id;
747 Decls : List_Id)
ee6ba406 748 is
57993a53 749 Rec_Typ : constant Entity_Id := Corresponding_Record_Type (Conc_Typ);
750 Decl : Node_Id;
751 Obj_Ptr : Node_Id;
ee6ba406 752
753 begin
57993a53 754 -- Create the renaming declaration for the Protection object of a
755 -- protected type. _Object is used by Complete_Entry_Body.
756 -- ??? An attempt to make this a renaming was unsuccessful.
70966f50 757
57993a53 758 -- Build the entity for the access type
70966f50 759
57993a53 760 Obj_Ptr :=
761 Make_Defining_Identifier (Loc,
762 New_External_Name (Chars (Rec_Typ), 'P'));
ee6ba406 763
57993a53 764 -- Generate:
765 -- _object : poVP := poVP!O;
ee6ba406 766
57993a53 767 Decl :=
768 Make_Object_Declaration (Loc,
7ee08bca 769 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uObject),
770 Object_Definition => New_Occurrence_Of (Obj_Ptr, Loc),
771 Expression =>
55868293 772 Unchecked_Convert_To (Obj_Ptr, Make_Identifier (Loc, Name_uO)));
57993a53 773 Set_Debug_Info_Needed (Defining_Identifier (Decl));
774 Prepend_To (Decls, Decl);
4961db87 775
57993a53 776 -- Generate:
777 -- type poVP is access poV;
4961db87 778
57993a53 779 Decl :=
780 Make_Full_Type_Declaration (Loc,
781 Defining_Identifier =>
782 Obj_Ptr,
783 Type_Definition =>
784 Make_Access_To_Object_Definition (Loc,
bb3b440a 785 Subtype_Indication =>
83c6c069 786 New_Occurrence_Of (Rec_Typ, Loc)));
57993a53 787 Set_Debug_Info_Needed (Defining_Identifier (Decl));
788 Prepend_To (Decls, Decl);
789 end Add_Object_Pointer;
ee6ba406 790
ee6ba406 791 -----------------------
792 -- Build_Accept_Body --
793 -----------------------
794
795 function Build_Accept_Body (Astat : Node_Id) return Node_Id is
796 Loc : constant Source_Ptr := Sloc (Astat);
797 Stats : constant Node_Id := Handled_Statement_Sequence (Astat);
798 New_S : Node_Id;
799 Hand : Node_Id;
800 Call : Node_Id;
801 Ohandle : Node_Id;
802
803 begin
804 -- At the end of the statement sequence, Complete_Rendezvous is called.
76a1c25b 805 -- A label skipping the Complete_Rendezvous, and all other accept
806 -- processing, has already been added for the expansion of requeue
284a54ba 807 -- statements. The Sloc is copied from the last statement since it
808 -- is really part of this last statement.
ee6ba406 809
284a54ba 810 Call :=
811 Build_Runtime_Call
812 (Sloc (Last (Statements (Stats))), RE_Complete_Rendezvous);
ee6ba406 813 Insert_Before (Last (Statements (Stats)), Call);
814 Analyze (Call);
815
816 -- If exception handlers are present, then append Complete_Rendezvous
284a54ba 817 -- calls to the handlers, and construct the required outer block. As
818 -- above, the Sloc is copied from the last statement in the sequence.
ee6ba406 819
820 if Present (Exception_Handlers (Stats)) then
821 Hand := First (Exception_Handlers (Stats));
ee6ba406 822 while Present (Hand) loop
284a54ba 823 Call :=
824 Build_Runtime_Call
825 (Sloc (Last (Statements (Hand))), RE_Complete_Rendezvous);
ee6ba406 826 Append (Call, Statements (Hand));
827 Analyze (Call);
828 Next (Hand);
829 end loop;
830
831 New_S :=
832 Make_Handled_Sequence_Of_Statements (Loc,
833 Statements => New_List (
834 Make_Block_Statement (Loc,
9dfe12ae 835 Handled_Statement_Sequence => Stats)));
ee6ba406 836
837 else
838 New_S := Stats;
839 end if;
840
78be29d1 841 -- At this stage we know that the new statement sequence does
842 -- not have an exception handler part, so we supply one to call
ee6ba406 843 -- Exceptional_Complete_Rendezvous. This handler is
844
845 -- when all others =>
846 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
847
848 -- We handle Abort_Signal to make sure that we properly catch the abort
849 -- case and wake up the caller.
850
851 Ohandle := Make_Others_Choice (Loc);
852 Set_All_Others (Ohandle);
853
854 Set_Exception_Handlers (New_S,
855 New_List (
cb5f80c1 856 Make_Implicit_Exception_Handler (Loc,
ee6ba406 857 Exception_Choices => New_List (Ohandle),
858
859 Statements => New_List (
791c4a7c 860 Make_Procedure_Call_Statement (Sloc (Stats),
7ee08bca 861 Name => New_Occurrence_Of (
791c4a7c 862 RTE (RE_Exceptional_Complete_Rendezvous), Sloc (Stats)),
ee6ba406 863 Parameter_Associations => New_List (
791c4a7c 864 Make_Function_Call (Sloc (Stats),
7ee08bca 865 Name =>
866 New_Occurrence_Of
867 (RTE (RE_Get_GNAT_Exception), Sloc (Stats)))))))));
ee6ba406 868
869 Set_Parent (New_S, Astat); -- temp parent for Analyze call
870 Analyze_Exception_Handlers (Exception_Handlers (New_S));
871 Expand_Exception_Handlers (New_S);
872
7ee08bca 873 -- Exceptional_Complete_Rendezvous must be called with abort still
874 -- deferred, which is the case for a "when all others" handler.
ee6ba406 875
876 return New_S;
ee6ba406 877 end Build_Accept_Body;
878
879 -----------------------------------
880 -- Build_Activation_Chain_Entity --
881 -----------------------------------
882
883 procedure Build_Activation_Chain_Entity (N : Node_Id) is
749b64b7 884 function Has_Activation_Chain (Stmt : Node_Id) return Boolean;
7ee08bca 885 -- Determine whether an extended return statement has activation chain
749b64b7 886
887 --------------------------
888 -- Has_Activation_Chain --
889 --------------------------
890
891 function Has_Activation_Chain (Stmt : Node_Id) return Boolean is
892 Decl : Node_Id;
893
894 begin
895 Decl := First (Return_Object_Declarations (Stmt));
896 while Present (Decl) loop
897 if Nkind (Decl) = N_Object_Declaration
898 and then Chars (Defining_Identifier (Decl)) = Name_uChain
899 then
900 return True;
901 end if;
902
903 Next (Decl);
904 end loop;
905
906 return False;
907 end Has_Activation_Chain;
908
909 -- Local variables
910
43602818 911 Context : Node_Id;
912 Context_Id : Entity_Id;
913 Decls : List_Id;
749b64b7 914
915 -- Start of processing for Build_Activation_Chain_Entity
ee6ba406 916
917 begin
d4f55b2a 918 -- Activation chain is never used for sequential elaboration policy, see
919 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
60774346 920
d4f55b2a 921 if Partition_Elaboration_Policy = 'S' then
60774346 922 return;
923 end if;
924
43602818 925 Find_Enclosing_Context (N, Context, Context_Id, Decls);
ee6ba406 926
9a6a4132 927 -- If activation chain entity has not been declared already, create one
ee6ba406 928
43602818 929 if Nkind (Context) = N_Extended_Return_Statement
930 or else No (Activation_Chain_Entity (Context))
cb5f80c1 931 then
749b64b7 932 -- Since extended return statements do not store the entity of the
933 -- chain, examine the return object declarations to avoid creating
934 -- a duplicate.
935
43602818 936 if Nkind (Context) = N_Extended_Return_Statement
937 and then Has_Activation_Chain (Context)
749b64b7 938 then
939 return;
cb5f80c1 940 end if;
ee6ba406 941
749b64b7 942 declare
43602818 943 Loc : constant Source_Ptr := Sloc (Context);
749b64b7 944 Chain : Entity_Id;
945 Decl : Node_Id;
946
947 begin
948 Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
949
950 -- Note: An extended return statement is not really a task
951 -- activator, but it does have an activation chain on which to
952 -- store the tasks temporarily. On successful return, the tasks
953 -- on this chain are moved to the chain passed in by the caller.
954 -- We do not build an Activation_Chain_Entity for an extended
955 -- return statement, because we do not want to build a call to
956 -- Activate_Tasks. Task activation is the responsibility of the
957 -- caller.
958
43602818 959 if Nkind (Context) /= N_Extended_Return_Statement then
960 Set_Activation_Chain_Entity (Context, Chain);
749b64b7 961 end if;
962
963 Decl :=
43602818 964 Make_Object_Declaration (Loc,
749b64b7 965 Defining_Identifier => Chain,
966 Aliased_Present => True,
967 Object_Definition =>
83c6c069 968 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc));
ee6ba406 969
749b64b7 970 Prepend_To (Decls, Decl);
43602818 971
78be29d1 972 -- Ensure that _chain appears in the proper scope of the context
43602818 973
974 if Context_Id /= Current_Scope then
975 Push_Scope (Context_Id);
976 Analyze (Decl);
977 Pop_Scope;
978 else
979 Analyze (Decl);
980 end if;
749b64b7 981 end;
ee6ba406 982 end if;
ee6ba406 983 end Build_Activation_Chain_Entity;
984
985 ----------------------------
986 -- Build_Barrier_Function --
987 ----------------------------
988
989 function Build_Barrier_Function
357dd91a 990 (N : Node_Id;
991 Ent : Entity_Id;
992 Pid : Node_Id) return Node_Id
ee6ba406 993 is
ee6ba406 994 Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
2e2a6452 995 Cond : constant Node_Id := Condition (Ent_Formals);
996 Loc : constant Source_Ptr := Sloc (Cond);
997 Func_Id : constant Entity_Id := Barrier_Function (Ent);
57993a53 998 Op_Decls : constant List_Id := New_List;
2e2a6452 999 Stmt : Node_Id;
57993a53 1000 Func_Body : Node_Id;
ee6ba406 1001
1002 begin
57993a53 1003 -- Add a declaration for the Protection object, renaming declarations
1004 -- for the discriminals and privals and finally a declaration for the
1005 -- entry family index (if applicable).
1006
2e2a6452 1007 Install_Private_Data_Declarations (Sloc (N),
1008 Spec_Id => Func_Id,
1009 Conc_Typ => Pid,
1010 Body_Nod => N,
1011 Decls => Op_Decls,
1012 Barrier => True,
1013 Family => Ekind (Ent) = E_Entry_Family);
1014
1015 -- If compiling with -fpreserve-control-flow, make sure we insert an
1016 -- IF statement so that the back-end knows to generate a conditional
1017 -- branch instruction, even if the condition is just the name of a
e462a42f 1018 -- boolean object. Note that Expand_N_If_Statement knows to preserve
1019 -- such redundant IF statements under -fpreserve-control-flow
1020 -- (whether coming from this routine, or directly from source).
2e2a6452 1021
1022 if Opt.Suppress_Control_Flow_Optimizations then
2f06c88a 1023 Stmt :=
1024 Make_Implicit_If_Statement (Cond,
1025 Condition => Cond,
1026 Then_Statements => New_List (
1027 Make_Simple_Return_Statement (Loc,
1028 New_Occurrence_Of (Standard_True, Loc))),
1029
1030 Else_Statements => New_List (
1031 Make_Simple_Return_Statement (Loc,
1032 New_Occurrence_Of (Standard_False, Loc))));
2e2a6452 1033
1034 else
1035 Stmt := Make_Simple_Return_Statement (Loc, Cond);
1036 end if;
ee6ba406 1037
1038 -- Note: the condition in the barrier function needs to be properly
1039 -- processed for the C/Fortran boolean possibility, but this happens
1040 -- automatically since the return statement does this normalization.
1041
57993a53 1042 Func_Body :=
ee6ba406 1043 Make_Subprogram_Body (Loc,
57993a53 1044 Specification =>
1045 Build_Barrier_Function_Specification (Loc,
1046 Make_Defining_Identifier (Loc, Chars (Func_Id))),
ee6ba406 1047 Declarations => Op_Decls,
1048 Handled_Statement_Sequence =>
1049 Make_Handled_Sequence_Of_Statements (Loc,
2e2a6452 1050 Statements => New_List (Stmt)));
57993a53 1051 Set_Is_Entry_Barrier_Function (Func_Body);
1052
1053 return Func_Body;
ee6ba406 1054 end Build_Barrier_Function;
1055
1056 ------------------------------------------
1057 -- Build_Barrier_Function_Specification --
1058 ------------------------------------------
1059
1060 function Build_Barrier_Function_Specification
57993a53 1061 (Loc : Source_Ptr;
1062 Def_Id : Entity_Id) return Node_Id
ee6ba406 1063 is
1064 begin
70966f50 1065 Set_Debug_Info_Needed (Def_Id);
57993a53 1066
2f06c88a 1067 return
1068 Make_Function_Specification (Loc,
1069 Defining_Unit_Name => Def_Id,
1070 Parameter_Specifications => New_List (
1071 Make_Parameter_Specification (Loc,
1072 Defining_Identifier =>
1073 Make_Defining_Identifier (Loc, Name_uO),
1074 Parameter_Type =>
1075 New_Occurrence_Of (RTE (RE_Address), Loc)),
1076
1077 Make_Parameter_Specification (Loc,
1078 Defining_Identifier =>
1079 Make_Defining_Identifier (Loc, Name_uE),
1080 Parameter_Type =>
1081 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
1082
1083 Result_Definition =>
1084 New_Occurrence_Of (Standard_Boolean, Loc));
ee6ba406 1085 end Build_Barrier_Function_Specification;
1086
1087 --------------------------
1088 -- Build_Call_With_Task --
1089 --------------------------
1090
1091 function Build_Call_With_Task
bdd64cbe 1092 (N : Node_Id;
1093 E : Entity_Id) return Node_Id
ee6ba406 1094 is
1095 Loc : constant Source_Ptr := Sloc (N);
ee6ba406 1096 begin
1097 return
1098 Make_Function_Call (Loc,
7ee08bca 1099 Name => New_Occurrence_Of (E, Loc),
ee6ba406 1100 Parameter_Associations => New_List (Concurrent_Ref (N)));
1101 end Build_Call_With_Task;
1102
9d0eada4 1103 -----------------------------
1104 -- Build_Class_Wide_Master --
1105 -----------------------------
1106
1107 procedure Build_Class_Wide_Master (Typ : Entity_Id) is
1108 Loc : constant Source_Ptr := Sloc (Typ);
1109 Master_Id : Entity_Id;
1110 Master_Scope : Entity_Id;
1111 Name_Id : Node_Id;
1112 Related_Node : Node_Id;
1113 Ren_Decl : Node_Id;
1114
1115 begin
1116 -- Nothing to do if there is no task hierarchy
1117
1118 if Restriction_Active (No_Task_Hierarchy) then
1119 return;
1120 end if;
1121
7ee08bca 1122 -- Find the declaration that created the access type, which is either a
9d0eada4 1123 -- type declaration, or an object declaration with an access definition,
1124 -- in which case the type is anonymous.
1125
1126 if Is_Itype (Typ) then
1127 Related_Node := Associated_Node_For_Itype (Typ);
1128 else
1129 Related_Node := Parent (Typ);
1130 end if;
1131
1132 Master_Scope := Find_Master_Scope (Typ);
1133
1134 -- Nothing to do if the master scope already contains a _master entity.
1135 -- The only exception to this is the following scenario:
1136
1137 -- Source_Scope
1138 -- Transient_Scope_1
1139 -- _master
1140
1141 -- Transient_Scope_2
1142 -- use of master
1143
1144 -- In this case the source scope is marked as having the master entity
1145 -- even though the actual declaration appears inside an inner scope. If
1146 -- the second transient scope requires a _master, it cannot use the one
1147 -- already declared because the entity is not visible.
1148
1149 Name_Id := Make_Identifier (Loc, Name_uMaster);
1150
1151 if not Has_Master_Entity (Master_Scope)
1152 or else No (Current_Entity_In_Scope (Name_Id))
1153 then
1154 declare
1155 Master_Decl : Node_Id;
9d0eada4 1156 begin
1157 Set_Has_Master_Entity (Master_Scope);
1158
1159 -- Generate:
1160 -- _master : constant Integer := Current_Master.all;
1161
1162 Master_Decl :=
1163 Make_Object_Declaration (Loc,
1164 Defining_Identifier =>
1165 Make_Defining_Identifier (Loc, Name_uMaster),
1166 Constant_Present => True,
1167 Object_Definition =>
83c6c069 1168 New_Occurrence_Of (Standard_Integer, Loc),
9d0eada4 1169 Expression =>
1170 Make_Explicit_Dereference (Loc,
83c6c069 1171 New_Occurrence_Of (RTE (RE_Current_Master), Loc)));
9d0eada4 1172
7c4fb271 1173 Insert_Action (Find_Hook_Context (Related_Node), Master_Decl);
9d0eada4 1174 Analyze (Master_Decl);
1175
1176 -- Mark the containing scope as a task master. Masters associated
1177 -- with return statements are already marked at this stage (see
1178 -- Analyze_Subprogram_Body).
1179
1180 if Ekind (Current_Scope) /= E_Return_Statement then
1181 declare
1182 Par : Node_Id := Related_Node;
1183
1184 begin
1185 while Nkind (Par) /= N_Compilation_Unit loop
1186 Par := Parent (Par);
1187
78be29d1 1188 -- If we fall off the top, we are at the outer level,
1189 -- and the environment task is our effective master,
1190 -- so nothing to mark.
9d0eada4 1191
1192 if Nkind_In (Par, N_Block_Statement,
1193 N_Subprogram_Body,
1194 N_Task_Body)
1195 then
1196 Set_Is_Task_Master (Par);
1197 exit;
1198 end if;
1199 end loop;
1200 end;
1201 end if;
1202 end;
1203 end if;
1204
1205 Master_Id :=
ac26337e 1206 Make_Defining_Identifier (Loc, New_External_Name (Chars (Typ), 'M'));
9d0eada4 1207
1208 -- Generate:
ac26337e 1209 -- typeMnn renames _master;
9d0eada4 1210
1211 Ren_Decl :=
1212 Make_Object_Renaming_Declaration (Loc,
1213 Defining_Identifier => Master_Id,
83c6c069 1214 Subtype_Mark => New_Occurrence_Of (Standard_Integer, Loc),
9d0eada4 1215 Name => Name_Id);
1216
43602818 1217 Insert_Action (Related_Node, Ren_Decl);
9d0eada4 1218
1219 Set_Master_Id (Typ, Master_Id);
1220 end Build_Class_Wide_Master;
1221
3ff5e35d 1222 ----------------------------
1223 -- Build_Contract_Wrapper --
1224 ----------------------------
1225
1226 procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id) is
1227 Conc_Typ : constant Entity_Id := Scope (E);
1228 Loc : constant Source_Ptr := Sloc (E);
1229
1230 procedure Add_Discriminant_Renamings
1231 (Obj_Id : Entity_Id;
1232 Decls : List_Id);
1233 -- Add renaming declarations for all discriminants of concurrent type
1234 -- Conc_Typ. Obj_Id is the entity of the wrapper formal parameter which
1235 -- represents the concurrent object.
1236
1237 procedure Add_Matching_Formals (Formals : List_Id; Actuals : List_Id);
1238 -- Add formal parameters that match those of entry E to list Formals.
1239 -- The routine also adds matching actuals for the new formals to list
1240 -- Actuals.
1241
1242 procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id);
1243 -- Relocate pragma Prag to list To. The routine creates a new list if
1244 -- To does not exist.
1245
1246 --------------------------------
1247 -- Add_Discriminant_Renamings --
1248 --------------------------------
1249
1250 procedure Add_Discriminant_Renamings
1251 (Obj_Id : Entity_Id;
1252 Decls : List_Id)
1253 is
1254 Discr : Entity_Id;
1255
1256 begin
1257 -- Inspect the discriminants of the concurrent type and generate a
1258 -- renaming for each one.
1259
1260 if Has_Discriminants (Conc_Typ) then
1261 Discr := First_Discriminant (Conc_Typ);
1262 while Present (Discr) loop
1263 Prepend_To (Decls,
1264 Make_Object_Renaming_Declaration (Loc,
1265 Defining_Identifier =>
1266 Make_Defining_Identifier (Loc, Chars (Discr)),
1267 Subtype_Mark =>
1268 New_Occurrence_Of (Etype (Discr), Loc),
1269 Name =>
1270 Make_Selected_Component (Loc,
1271 Prefix => New_Occurrence_Of (Obj_Id, Loc),
1272 Selector_Name =>
1273 Make_Identifier (Loc, Chars (Discr)))));
1274
1275 Next_Discriminant (Discr);
1276 end loop;
1277 end if;
1278 end Add_Discriminant_Renamings;
1279
1280 --------------------------
1281 -- Add_Matching_Formals --
1282 --------------------------
1283
1284 procedure Add_Matching_Formals (Formals : List_Id; Actuals : List_Id) is
1285 Formal : Entity_Id;
1286 New_Formal : Entity_Id;
1287
1288 begin
1289 -- Inspect the formal parameters of the entry and generate a new
1290 -- matching formal with the same name for the wrapper. A reference
1291 -- to the new formal becomes an actual in the entry call.
1292
1293 Formal := First_Formal (E);
1294 while Present (Formal) loop
1295 New_Formal := Make_Defining_Identifier (Loc, Chars (Formal));
1296 Append_To (Formals,
1297 Make_Parameter_Specification (Loc,
1298 Defining_Identifier => New_Formal,
1299 In_Present => In_Present (Parent (Formal)),
1300 Out_Present => Out_Present (Parent (Formal)),
1301 Parameter_Type =>
1302 New_Occurrence_Of (Etype (Formal), Loc)));
1303
1304 Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
1305 Next_Formal (Formal);
1306 end loop;
1307 end Add_Matching_Formals;
1308
1309 ---------------------
1310 -- Transfer_Pragma --
1311 ---------------------
1312
1313 procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id) is
1314 New_Prag : Node_Id;
1315
1316 begin
1317 if No (To) then
1318 To := New_List;
1319 end if;
1320
1321 New_Prag := Relocate_Node (Prag);
1322
1323 Set_Analyzed (New_Prag, False);
1324 Append (New_Prag, To);
1325 end Transfer_Pragma;
1326
1327 -- Local variables
1328
1329 Items : constant Node_Id := Contract (E);
1330 Actuals : List_Id;
1331 Call : Node_Id;
1332 Call_Nam : Node_Id;
1333 Decls : List_Id := No_List;
1334 Formals : List_Id;
1335 Has_Pragma : Boolean := False;
1336 Index_Id : Entity_Id;
1337 Obj_Id : Entity_Id;
1338 Prag : Node_Id;
1339 Wrapper_Id : Entity_Id;
1340
1341 -- Start of processing for Build_Contract_Wrapper
1342
1343 begin
1344 -- This routine generates a specialized wrapper for a protected or task
1345 -- entry [family] which implements precondition/postcondition semantics.
1346 -- Preconditions and case guards of contract cases are checked before
1347 -- the protected action or rendezvous takes place. Postconditions and
1348 -- consequences of contract cases are checked after the protected action
1349 -- or rendezvous takes place. The structure of the generated wrapper is
1350 -- as follows:
1351
1352 -- procedure Wrapper
1353 -- (Obj_Id : Conc_Typ; -- concurrent object
1354 -- [Index : Index_Typ;] -- index of entry family
1355 -- [Formal_1 : ...; -- parameters of original entry
1356 -- Formal_N : ...])
1357 -- is
1358 -- [Discr_1 : ... renames Obj_Id.Discr_1; -- discriminant
1359 -- Discr_N : ... renames Obj_Id.Discr_N;] -- renamings
1360
1361 -- <precondition checks>
1362 -- <case guard checks>
1363
1364 -- procedure _Postconditions is
1365 -- begin
1366 -- <postcondition checks>
1367 -- <consequence checks>
1368 -- end _Postconditions;
1369
1370 -- begin
1371 -- Entry_Call (Obj_Id, [Index,] [Formal_1, Formal_N]);
1372 -- _Postconditions;
1373 -- end Wrapper;
1374
1375 -- Create the wrapper only when the entry has at least one executable
1376 -- contract item such as contract cases, precondition or postcondition.
1377
1378 if Present (Items) then
1379
1380 -- Inspect the list of pre/postconditions and transfer all available
1381 -- pragmas to the declarative list of the wrapper.
1382
1383 Prag := Pre_Post_Conditions (Items);
1384 while Present (Prag) loop
1385 if Nam_In (Pragma_Name (Prag), Name_Postcondition,
1386 Name_Precondition)
1387 then
1388 Has_Pragma := True;
1389 Transfer_Pragma (Prag, To => Decls);
1390 end if;
1391
1392 Prag := Next_Pragma (Prag);
1393 end loop;
1394
1395 -- Inspect the list of test/contract cases and transfer only contract
1396 -- cases pragmas to the declarative part of the wrapper.
1397
1398 Prag := Contract_Test_Cases (Items);
1399 while Present (Prag) loop
1400 if Pragma_Name (Prag) = Name_Contract_Cases then
1401 Has_Pragma := True;
1402 Transfer_Pragma (Prag, To => Decls);
1403 end if;
1404
1405 Prag := Next_Pragma (Prag);
1406 end loop;
1407 end if;
1408
1409 -- The entry lacks executable contract items and a wrapper is not needed
1410
1411 if not Has_Pragma then
1412 return;
1413 end if;
1414
1415 -- Create the profile of the wrapper. The first formal parameter is the
1416 -- concurrent object.
1417
1418 Obj_Id :=
1419 Make_Defining_Identifier (Loc,
1420 Chars => New_External_Name (Chars (Conc_Typ), 'A'));
1421
1422 Formals := New_List (
1423 Make_Parameter_Specification (Loc,
1424 Defining_Identifier => Obj_Id,
1425 Out_Present => True,
1426 In_Present => True,
1427 Parameter_Type => New_Occurrence_Of (Conc_Typ, Loc)));
1428
1429 -- Construct the call to the original entry. The call will be gradually
1430 -- augmented with an optional entry index and extra parameters.
1431
1432 Call_Nam :=
1433 Make_Selected_Component (Loc,
1434 Prefix => New_Occurrence_Of (Obj_Id, Loc),
1435 Selector_Name => New_Occurrence_Of (E, Loc));
1436
1437 -- When creating a wrapper for an entry family, the second formal is the
1438 -- entry index.
1439
1440 if Ekind (E) = E_Entry_Family then
1441 Index_Id := Make_Defining_Identifier (Loc, Name_I);
1442
1443 Append_To (Formals,
1444 Make_Parameter_Specification (Loc,
1445 Defining_Identifier => Index_Id,
1446 Parameter_Type =>
1447 New_Occurrence_Of (Entry_Index_Type (E), Loc)));
1448
1449 -- The call to the original entry becomes an indexed component to
1450 -- accommodate the entry index.
1451
1452 Call_Nam :=
1453 Make_Indexed_Component (Loc,
1454 Prefix => Call_Nam,
1455 Expressions => New_List (New_Occurrence_Of (Index_Id, Loc)));
1456 end if;
1457
1458 Actuals := New_List;
1459 Call :=
1460 Make_Procedure_Call_Statement (Loc,
1461 Name => Call_Nam,
1462 Parameter_Associations => Actuals);
1463
1464 -- Add formal parameters to match those of the entry and build actuals
1465 -- for the entry call.
1466
1467 Add_Matching_Formals (Formals, Actuals);
1468
1469 -- Add renaming declarations for the discriminants of the enclosing type
1470 -- as the various contract items may reference them.
1471
1472 Add_Discriminant_Renamings (Obj_Id, Decls);
1473
1474 Wrapper_Id :=
1475 Make_Defining_Identifier (Loc, New_External_Name (Chars (E), 'E'));
1476 Set_Contract_Wrapper (E, Wrapper_Id);
1477
1478 -- The wrapper body is analyzed when the enclosing type is frozen
1479
1480 Append_Freeze_Action (Defining_Entity (Decl),
1481 Make_Subprogram_Body (Loc,
1482 Specification =>
1483 Make_Procedure_Specification (Loc,
1484 Defining_Unit_Name => Wrapper_Id,
1485 Parameter_Specifications => Formals),
1486 Declarations => Decls,
1487 Handled_Statement_Sequence =>
1488 Make_Handled_Sequence_Of_Statements (Loc,
1489 Statements => New_List (Call))));
1490 end Build_Contract_Wrapper;
1491
ee6ba406 1492 --------------------------------
1493 -- Build_Corresponding_Record --
1494 --------------------------------
1495
1496 function Build_Corresponding_Record
1497 (N : Node_Id;
1498 Ctyp : Entity_Id;
bdd64cbe 1499 Loc : Source_Ptr) return Node_Id
ee6ba406 1500 is
1501 Rec_Ent : constant Entity_Id :=
1502 Make_Defining_Identifier
1503 (Loc, New_External_Name (Chars (Ctyp), 'V'));
1504 Disc : Entity_Id;
1505 Dlist : List_Id;
1506 New_Disc : Entity_Id;
1507 Cdecls : List_Id;
1508
1509 begin
9f373bb8 1510 Set_Corresponding_Record_Type (Ctyp, Rec_Ent);
9dfe12ae 1511 Set_Ekind (Rec_Ent, E_Record_Type);
1512 Set_Has_Delayed_Freeze (Rec_Ent, Has_Delayed_Freeze (Ctyp));
1513 Set_Is_Concurrent_Record_Type (Rec_Ent, True);
ee6ba406 1514 Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
9dfe12ae 1515 Set_Stored_Constraint (Rec_Ent, No_Elist);
ee6ba406 1516 Cdecls := New_List;
1517
ad274a73 1518 -- Propagate type invariants to the corresponding record type
1519
1520 Set_Has_Invariants (Rec_Ent, Has_Invariants (Ctyp));
1521 Set_Has_Inheritable_Invariants (Rec_Ent,
1522 Has_Inheritable_Invariants (Ctyp));
1523
ee6ba406 1524 -- Use discriminals to create list of discriminants for record, and
1525 -- create new discriminals for use in default expressions, etc. It is
1526 -- worth noting that a task discriminant gives rise to 5 entities;
1527
1528 -- a) The original discriminant.
1529 -- b) The discriminal for use in the task.
1530 -- c) The discriminant of the corresponding record.
9dfe12ae 1531 -- d) The discriminal for the init proc of the corresponding record.
ee6ba406 1532 -- e) The local variable that renames the discriminant in the procedure
1533 -- for the task body.
1534
1535 -- In fact the discriminals b) are used in the renaming declarations
bb3b440a 1536 -- for e). See details in einfo (Handling of Discriminants).
ee6ba406 1537
1538 if Present (Discriminant_Specifications (N)) then
1539 Dlist := New_List;
1540 Disc := First_Discriminant (Ctyp);
1541
1542 while Present (Disc) loop
1543 New_Disc := CR_Discriminant (Disc);
1544
1545 Append_To (Dlist,
1546 Make_Discriminant_Specification (Loc,
1547 Defining_Identifier => New_Disc,
1548 Discriminant_Type =>
1549 New_Occurrence_Of (Etype (Disc), Loc),
1550 Expression =>
1551 New_Copy (Discriminant_Default_Value (Disc))));
1552
1553 Next_Discriminant (Disc);
1554 end loop;
1555
1556 else
1557 Dlist := No_List;
1558 end if;
1559
1560 -- Now we can construct the record type declaration. Note that this
9f373bb8 1561 -- record is "limited tagged". It is "limited" to reflect the underlying
1562 -- limitedness of the task or protected object that it represents, and
1563 -- ensuring for example that it is properly passed by reference. It is
64988bb0 1564 -- "tagged" to give support to dispatching calls through interfaces. We
1565 -- propagate here the list of interfaces covered by the concurrent type
1566 -- (Ada 2005: AI-345).
ee6ba406 1567
1568 return
1569 Make_Full_Type_Declaration (Loc,
1570 Defining_Identifier => Rec_Ent,
1571 Discriminant_Specifications => Dlist,
1572 Type_Definition =>
1573 Make_Record_Definition (Loc,
c0688d2b 1574 Component_List =>
1575 Make_Component_List (Loc, Component_Items => Cdecls),
76a1c25b 1576 Tagged_Present =>
de54c5ab 1577 Ada_Version >= Ada_2005 and then Is_Tagged_Type (Ctyp),
64988bb0 1578 Interface_List => Interface_List (N),
ee6ba406 1579 Limited_Present => True));
1580 end Build_Corresponding_Record;
1581
37c6e44c 1582 ---------------------------------
1583 -- Build_Dispatching_Tag_Check --
1584 ---------------------------------
1585
1586 function Build_Dispatching_Tag_Check
1587 (K : Entity_Id;
1588 N : Node_Id) return Node_Id
1589 is
1590 Loc : constant Source_Ptr := Sloc (N);
83c6c069 1591
37c6e44c 1592 begin
1593 return
1594 Make_Op_Or (Loc,
1595 Make_Op_Eq (Loc,
83c6c069 1596 Left_Opnd =>
1597 New_Occurrence_Of (K, Loc),
1598 Right_Opnd =>
1599 New_Occurrence_Of (RTE (RE_TK_Limited_Tagged), Loc)),
1600
37c6e44c 1601 Make_Op_Eq (Loc,
83c6c069 1602 Left_Opnd =>
1603 New_Occurrence_Of (K, Loc),
1604 Right_Opnd =>
1605 New_Occurrence_Of (RTE (RE_TK_Tagged), Loc)));
37c6e44c 1606 end Build_Dispatching_Tag_Check;
1607
ee6ba406 1608 ----------------------------------
1609 -- Build_Entry_Count_Expression --
1610 ----------------------------------
1611
1612 function Build_Entry_Count_Expression
1613 (Concurrent_Type : Node_Id;
1614 Component_List : List_Id;
bdd64cbe 1615 Loc : Source_Ptr) return Node_Id
ee6ba406 1616 is
1617 Eindx : Nat;
1618 Ent : Entity_Id;
1619 Ecount : Node_Id;
1620 Comp : Node_Id;
1621 Lo : Node_Id;
1622 Hi : Node_Id;
1623 Typ : Entity_Id;
cb5f80c1 1624 Large : Boolean;
ee6ba406 1625
1626 begin
ee6ba406 1627 -- Count number of non-family entries
1628
76a1c25b 1629 Eindx := 0;
1630 Ent := First_Entity (Concurrent_Type);
ee6ba406 1631 while Present (Ent) loop
1632 if Ekind (Ent) = E_Entry then
1633 Eindx := Eindx + 1;
1634 end if;
1635
1636 Next_Entity (Ent);
1637 end loop;
1638
1639 Ecount := Make_Integer_Literal (Loc, Eindx);
1640
1641 -- Loop through entry families building the addition nodes
1642
1643 Ent := First_Entity (Concurrent_Type);
1644 Comp := First (Component_List);
ee6ba406 1645 while Present (Ent) loop
1646 if Ekind (Ent) = E_Entry_Family then
1647 while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
1648 Next (Comp);
1649 end loop;
1650
1651 Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1652 Hi := Type_High_Bound (Typ);
1653 Lo := Type_Low_Bound (Typ);
cb5f80c1 1654 Large := Is_Potentially_Large_Family
1655 (Base_Type (Typ), Concurrent_Type, Lo, Hi);
ee6ba406 1656 Ecount :=
1657 Make_Op_Add (Loc,
1658 Left_Opnd => Ecount,
c0688d2b 1659 Right_Opnd =>
1660 Family_Size (Loc, Hi, Lo, Concurrent_Type, Large));
ee6ba406 1661 end if;
1662
1663 Next_Entity (Ent);
1664 end loop;
1665
1666 return Ecount;
1667 end Build_Entry_Count_Expression;
1668
f89cc618 1669 -----------------------
1670 -- Build_Entry_Names --
1671 -----------------------
1672
12e90c44 1673 procedure Build_Entry_Names
1674 (Obj_Ref : Node_Id;
1675 Obj_Typ : Entity_Id;
1676 Stmts : List_Id)
1677 is
1678 Loc : constant Source_Ptr := Sloc (Obj_Ref);
1679 Data : Entity_Id := Empty;
1680 Index : Entity_Id := Empty;
1681 Typ : Entity_Id := Obj_Typ;
1682
1683 procedure Build_Entry_Name (Comp_Id : Entity_Id);
1684 -- Given an entry [family], create a static string which denotes the
1685 -- name of Comp_Id and assign it to the underlying data structure which
1686 -- contains the entry names of a concurrent object.
1687
1688 function Object_Reference return Node_Id;
1689 -- Return a reference to field _object or _task_id depending on the
1690 -- concurrent object being processed.
1691
1692 ----------------------
1693 -- Build_Entry_Name --
1694 ----------------------
f89cc618 1695
12e90c44 1696 procedure Build_Entry_Name (Comp_Id : Entity_Id) is
f89cc618 1697 function Build_Range (Def : Node_Id) return Node_Id;
1698 -- Given a discrete subtype definition of an entry family, generate a
1699 -- range node which covers the range of Def's type.
1700
12e90c44 1701 procedure Create_Index_And_Data;
1702 -- Generate the declarations of variables Index and Data. Subsequent
1703 -- calls do nothing.
1704
1705 function Increment_Index return Node_Id;
1706 -- Increment the index used in the assignment of string names to the
1707 -- Data array.
1708
1709 function Name_Declaration (Def_Id : Entity_Id) return Node_Id;
1710 -- Given the name of a temporary variable, create the following
1711 -- declaration for it:
1712 --
1713 -- Def_Id : aliased constant String := <String_Name_From_Buffer>;
1714
1715 function Set_Entry_Name (Def_Id : Entity_Id) return Node_Id;
1716 -- Given the name of a temporary variable, place it in the array of
1717 -- string names. Generate:
1718 --
1719 -- Data (Index) := Def_Id'Unchecked_Access;
1720
f89cc618 1721 -----------------
1722 -- Build_Range --
1723 -----------------
1724
1725 function Build_Range (Def : Node_Id) return Node_Id is
1726 High : Node_Id := Type_High_Bound (Etype (Def));
1727 Low : Node_Id := Type_Low_Bound (Etype (Def));
1728
1729 begin
1730 -- If a bound references a discriminant, generate an identifier
1731 -- with the same name. Resolution will map it to the formals of
1732 -- the init proc.
1733
1734 if Is_Entity_Name (Low)
1735 and then Ekind (Entity (Low)) = E_Discriminant
1736 then
12e90c44 1737 Low :=
1738 Make_Selected_Component (Loc,
1739 Prefix => New_Copy_Tree (Obj_Ref),
1740 Selector_Name => Make_Identifier (Loc, Chars (Low)));
f89cc618 1741 else
1742 Low := New_Copy_Tree (Low);
1743 end if;
1744
1745 if Is_Entity_Name (High)
1746 and then Ekind (Entity (High)) = E_Discriminant
1747 then
12e90c44 1748 High :=
1749 Make_Selected_Component (Loc,
1750 Prefix => New_Copy_Tree (Obj_Ref),
1751 Selector_Name => Make_Identifier (Loc, Chars (High)));
f89cc618 1752 else
1753 High := New_Copy_Tree (High);
1754 end if;
1755
1756 return
1757 Make_Range (Loc,
1758 Low_Bound => Low,
1759 High_Bound => High);
1760 end Build_Range;
1761
12e90c44 1762 ---------------------------
1763 -- Create_Index_And_Data --
1764 ---------------------------
f89cc618 1765
12e90c44 1766 procedure Create_Index_And_Data is
1767 begin
1768 if No (Index) and then No (Data) then
1769 declare
687b5687 1770 Count : RE_Id;
1771 Data_Typ : RE_Id;
1772 Size : Entity_Id;
f89cc618 1773
12e90c44 1774 begin
1775 if Is_Protected_Type (Typ) then
687b5687 1776 Count := RO_PE_Number_Of_Entries;
1777 Data_Typ := RE_Protected_Entry_Names_Array;
12e90c44 1778 else
687b5687 1779 Count := RO_ST_Number_Of_Entries;
1780 Data_Typ := RE_Task_Entry_Names_Array;
12e90c44 1781 end if;
e0c76917 1782
12e90c44 1783 -- Step 1: Generate the declaration of the index variable:
f89cc618 1784
687b5687 1785 -- Index : Entry_Index := 1;
f89cc618 1786
12e90c44 1787 Index := Make_Temporary (Loc, 'I');
f3f7771d 1788
12e90c44 1789 Append_To (Stmts,
1790 Make_Object_Declaration (Loc,
1791 Defining_Identifier => Index,
1792 Object_Definition =>
83c6c069 1793 New_Occurrence_Of (RTE (RE_Entry_Index), Loc),
12e90c44 1794 Expression => Make_Integer_Literal (Loc, 1)));
f89cc618 1795
12e90c44 1796 -- Step 2: Generate the declaration of an array to house all
1797 -- names:
f89cc618 1798
687b5687 1799 -- Size : constant Entry_Index := <Count> (Obj_Ref);
12e90c44 1800 -- Data : aliased <Data_Typ> := (1 .. Size => null);
f89cc618 1801
12e90c44 1802 Size := Make_Temporary (Loc, 'S');
f89cc618 1803
12e90c44 1804 Append_To (Stmts,
1805 Make_Object_Declaration (Loc,
1806 Defining_Identifier => Size,
1807 Constant_Present => True,
1808 Object_Definition =>
83c6c069 1809 New_Occurrence_Of (RTE (RE_Entry_Index), Loc),
12e90c44 1810 Expression =>
1811 Make_Function_Call (Loc,
1812 Name =>
83c6c069 1813 New_Occurrence_Of (RTE (Count), Loc),
12e90c44 1814 Parameter_Associations =>
1815 New_List (Object_Reference))));
1816
1817 Data := Make_Temporary (Loc, 'A');
1818
1819 Append_To (Stmts,
1820 Make_Object_Declaration (Loc,
1821 Defining_Identifier => Data,
1822 Aliased_Present => True,
1823 Object_Definition =>
83c6c069 1824 New_Occurrence_Of (RTE (Data_Typ), Loc),
12e90c44 1825 Expression =>
1826 Make_Aggregate (Loc,
1827 Component_Associations => New_List (
1828 Make_Component_Association (Loc,
1829 Choices => New_List (
1830 Make_Range (Loc,
83c6c069 1831 Low_Bound =>
1832 Make_Integer_Literal (Loc, 1),
1833 High_Bound =>
1834 New_Occurrence_Of (Size, Loc))),
12e90c44 1835 Expression => Make_Null (Loc))))));
1836 end;
1837 end if;
1838 end Create_Index_And_Data;
1839
1840 ---------------------
1841 -- Increment_Index --
1842 ---------------------
1843
1844 function Increment_Index return Node_Id is
1845 begin
1846 return
1847 Make_Assignment_Statement (Loc,
83c6c069 1848 Name => New_Occurrence_Of (Index, Loc),
12e90c44 1849 Expression =>
1850 Make_Op_Add (Loc,
83c6c069 1851 Left_Opnd => New_Occurrence_Of (Index, Loc),
12e90c44 1852 Right_Opnd => Make_Integer_Literal (Loc, 1)));
1853 end Increment_Index;
f89cc618 1854
12e90c44 1855 ----------------------
1856 -- Name_Declaration --
1857 ----------------------
1858
1859 function Name_Declaration (Def_Id : Entity_Id) return Node_Id is
1860 begin
1861 return
1862 Make_Object_Declaration (Loc,
1863 Defining_Identifier => Def_Id,
1864 Aliased_Present => True,
1865 Constant_Present => True,
83c6c069 1866 Object_Definition =>
1867 New_Occurrence_Of (Standard_String, Loc),
12e90c44 1868 Expression =>
1869 Make_String_Literal (Loc, String_From_Name_Buffer));
1870 end Name_Declaration;
1871
1872 --------------------
1873 -- Set_Entry_Name --
1874 --------------------
1875
1876 function Set_Entry_Name (Def_Id : Entity_Id) return Node_Id is
1877 begin
1878 return
1879 Make_Assignment_Statement (Loc,
1880 Name =>
1881 Make_Indexed_Component (Loc,
83c6c069 1882 Prefix => New_Occurrence_Of (Data, Loc),
1883 Expressions => New_List (New_Occurrence_Of (Index, Loc))),
12e90c44 1884
1885 Expression =>
1886 Make_Attribute_Reference (Loc,
83c6c069 1887 Prefix => New_Occurrence_Of (Def_Id, Loc),
12e90c44 1888 Attribute_Name => Name_Unchecked_Access));
1889 end Set_Entry_Name;
1890
1891 -- Local variables
1892
1893 Temp_Id : Entity_Id;
1894 Subt_Def : Node_Id;
1895
1896 -- Start of processing for Build_Entry_Name
f89cc618 1897
1898 begin
12e90c44 1899 if Ekind (Comp_Id) = E_Entry_Family then
1900 Subt_Def := Discrete_Subtype_Definition (Parent (Comp_Id));
f3f7771d 1901
12e90c44 1902 Create_Index_And_Data;
f3f7771d 1903
12e90c44 1904 -- Step 1: Create the string name of the entry family.
1905 -- Generate:
1906 -- Temp : aliased constant String := "name ()";
1907
1908 Temp_Id := Make_Temporary (Loc, 'S');
1909 Get_Name_String (Chars (Comp_Id));
1910 Add_Char_To_Name_Buffer (' ');
1911 Add_Char_To_Name_Buffer ('(');
1912 Add_Char_To_Name_Buffer (')');
1913
1914 Append_To (Stmts, Name_Declaration (Temp_Id));
1915
1916 -- Generate:
1917 -- for Member in Family_Low .. Family_High loop
1918 -- Set_Entry_Name (...);
1919 -- Index := Index + 1;
1920 -- end loop;
1921
1922 Append_To (Stmts,
1923 Make_Loop_Statement (Loc,
1924 Iteration_Scheme =>
1925 Make_Iteration_Scheme (Loc,
1926 Loop_Parameter_Specification =>
1927 Make_Loop_Parameter_Specification (Loc,
1928 Defining_Identifier =>
1929 Make_Temporary (Loc, 'L'),
1930 Discrete_Subtype_Definition =>
1931 Build_Range (Subt_Def))),
1932
1933 Statements => New_List (
1934 Set_Entry_Name (Temp_Id),
1935 Increment_Index),
1936 End_Label => Empty));
1937
1938 -- Entry
1939
1940 else
1941 Create_Index_And_Data;
1942
1943 -- Step 1: Create the string name of the entry. Generate:
1944 -- Temp : aliased constant String := "name";
1945
1946 Temp_Id := Make_Temporary (Loc, 'S');
1947 Get_Name_String (Chars (Comp_Id));
1948
1949 Append_To (Stmts, Name_Declaration (Temp_Id));
1950
1951 -- Step 2: Associate the string name with the underlying data
1952 -- structure.
f89cc618 1953
12e90c44 1954 Append_To (Stmts, Set_Entry_Name (Temp_Id));
1955 Append_To (Stmts, Increment_Index);
1956 end if;
f89cc618 1957 end Build_Entry_Name;
1958
12e90c44 1959 ----------------------
1960 -- Object_Reference --
1961 ----------------------
f89cc618 1962
12e90c44 1963 function Object_Reference return Node_Id is
1964 Conc_Typ : constant Entity_Id := Corresponding_Record_Type (Typ);
1965 Field : Name_Id;
1966 Ref : Node_Id;
f89cc618 1967
1968 begin
f89cc618 1969 if Is_Protected_Type (Typ) then
12e90c44 1970 Field := Name_uObject;
1971 else
1972 Field := Name_uTask_Id;
f89cc618 1973 end if;
1974
12e90c44 1975 Ref :=
1976 Make_Selected_Component (Loc,
1977 Prefix =>
1978 Unchecked_Convert_To (Conc_Typ, New_Copy_Tree (Obj_Ref)),
1979 Selector_Name => Make_Identifier (Loc, Field));
f89cc618 1980
12e90c44 1981 if Is_Protected_Type (Typ) then
1982 Ref :=
1983 Make_Attribute_Reference (Loc,
1984 Prefix => Ref,
1985 Attribute_Name => Name_Unchecked_Access);
1986 end if;
f89cc618 1987
12e90c44 1988 return Ref;
1989 end Object_Reference;
f89cc618 1990
12e90c44 1991 -- Local variables
f89cc618 1992
12e90c44 1993 Comp : Node_Id;
1994 Proc : RE_Id;
f89cc618 1995
1996 -- Start of processing for Build_Entry_Names
1997
1998 begin
1999 -- Retrieve the original concurrent type
2000
2001 if Is_Concurrent_Record_Type (Typ) then
2002 Typ := Corresponding_Concurrent_Type (Typ);
2003 end if;
2004
12e90c44 2005 pragma Assert (Is_Concurrent_Type (Typ));
f89cc618 2006
2007 -- Nothing to do if the type has no entries
2008
2009 if not Has_Entries (Typ) then
12e90c44 2010 return;
f89cc618 2011 end if;
2012
2013 -- Avoid generating entry names for a protected type with only one entry
2014
2015 if Is_Protected_Type (Typ)
12e90c44 2016 and then Find_Protection_Type (Base_Type (Typ)) /=
2017 RTE (RE_Protection_Entries)
f89cc618 2018 then
12e90c44 2019 return;
f89cc618 2020 end if;
2021
12e90c44 2022 -- Step 1: Populate the array with statically generated strings denoting
2023 -- entries and entry family names.
f89cc618 2024
2025 Comp := First_Entity (Typ);
2026 while Present (Comp) loop
12e90c44 2027 if Comes_From_Source (Comp)
2028 and then Ekind_In (Comp, E_Entry, E_Entry_Family)
2029 then
f89cc618 2030 Build_Entry_Name (Comp);
f89cc618 2031 end if;
2032
2033 Next_Entity (Comp);
2034 end loop;
2035
12e90c44 2036 -- Step 2: Associate the array with the related concurrent object:
f89cc618 2037
12e90c44 2038 -- Set_Entry_Names (Obj_Ref, <Data>'Unchecked_Access);
2039
2040 if Present (Data) then
2041 if Is_Protected_Type (Typ) then
2042 Proc := RO_PE_Set_Entry_Names;
2043 else
2044 Proc := RO_ST_Set_Entry_Names;
2045 end if;
2046
2047 Append_To (Stmts,
2048 Make_Procedure_Call_Statement (Loc,
83c6c069 2049 Name => New_Occurrence_Of (RTE (Proc), Loc),
12e90c44 2050 Parameter_Associations => New_List (
2051 Object_Reference,
2052 Make_Attribute_Reference (Loc,
83c6c069 2053 Prefix => New_Occurrence_Of (Data, Loc),
12e90c44 2054 Attribute_Name => Name_Unchecked_Access))));
2055 end if;
f89cc618 2056 end Build_Entry_Names;
2057
d62940bf 2058 ---------------------------
2059 -- Build_Parameter_Block --
2060 ---------------------------
2061
2062 function Build_Parameter_Block
2063 (Loc : Source_Ptr;
2064 Actuals : List_Id;
2065 Formals : List_Id;
2066 Decls : List_Id) return Entity_Id
2067 is
2068 Actual : Entity_Id;
2069 Comp_Nam : Node_Id;
d62940bf 2070 Comps : List_Id;
2071 Formal : Entity_Id;
76a1c25b 2072 Has_Comp : Boolean := False;
2073 Rec_Nam : Node_Id;
d62940bf 2074
2075 begin
2076 Actual := First (Actuals);
2077 Comps := New_List;
2078 Formal := Defining_Identifier (First (Formals));
76a1c25b 2079
d62940bf 2080 while Present (Actual) loop
76a1c25b 2081 if not Is_Controlling_Actual (Actual) then
d62940bf 2082
76a1c25b 2083 -- Generate:
2084 -- type Ann is access all <actual-type>
d62940bf 2085
ec97ce79 2086 Comp_Nam := Make_Temporary (Loc, 'A');
11cf765a 2087 Set_Is_Param_Block_Component_Type (Comp_Nam);
d62940bf 2088
76a1c25b 2089 Append_To (Decls,
2090 Make_Full_Type_Declaration (Loc,
ec97ce79 2091 Defining_Identifier => Comp_Nam,
2092 Type_Definition =>
76a1c25b 2093 Make_Access_To_Object_Definition (Loc,
ec97ce79 2094 All_Present => True,
2095 Constant_Present => Ekind (Formal) = E_In_Parameter,
76a1c25b 2096 Subtype_Indication =>
83c6c069 2097 New_Occurrence_Of (Etype (Actual), Loc))));
d62940bf 2098
76a1c25b 2099 -- Generate:
2100 -- Param : Ann;
2101
2102 Append_To (Comps,
2103 Make_Component_Declaration (Loc,
2104 Defining_Identifier =>
2105 Make_Defining_Identifier (Loc, Chars (Formal)),
2106 Component_Definition =>
2107 Make_Component_Definition (Loc,
2108 Aliased_Present =>
2109 False,
2110 Subtype_Indication =>
83c6c069 2111 New_Occurrence_Of (Comp_Nam, Loc))));
76a1c25b 2112
2113 Has_Comp := True;
2114 end if;
d62940bf 2115
2116 Next_Actual (Actual);
2117 Next_Formal_With_Extras (Formal);
2118 end loop;
2119
ec97ce79 2120 Rec_Nam := Make_Temporary (Loc, 'P');
d62940bf 2121
76a1c25b 2122 if Has_Comp then
d62940bf 2123
76a1c25b 2124 -- Generate:
2125 -- type Pnn is record
2126 -- Param1 : Ann1;
2127 -- ...
2128 -- ParamN : AnnN;
d62940bf 2129
76a1c25b 2130 -- where Pnn is a parameter wrapping record, Param1 .. ParamN are
2131 -- the original parameter names and Ann1 .. AnnN are the access to
2132 -- actual types.
2133
2134 Append_To (Decls,
2135 Make_Full_Type_Declaration (Loc,
2136 Defining_Identifier =>
2137 Rec_Nam,
2138 Type_Definition =>
2139 Make_Record_Definition (Loc,
2140 Component_List =>
2141 Make_Component_List (Loc, Comps))));
2142 else
2143 -- Generate:
2144 -- type Pnn is null record;
d62940bf 2145
76a1c25b 2146 Append_To (Decls,
2147 Make_Full_Type_Declaration (Loc,
2148 Defining_Identifier =>
2149 Rec_Nam,
2150 Type_Definition =>
2151 Make_Record_Definition (Loc,
2152 Null_Present => True,
2153 Component_List => Empty)));
2154 end if;
2155
2156 return Rec_Nam;
d62940bf 2157 end Build_Parameter_Block;
2158
b76dc1f0 2159 --------------------------------------
2160 -- Build_Renamed_Formal_Declaration --
2161 --------------------------------------
2162
2163 function Build_Renamed_Formal_Declaration
2164 (New_F : Entity_Id;
2165 Formal : Entity_Id;
2166 Comp : Entity_Id;
2167 Renamed_Formal : Node_Id) return Node_Id
2168 is
2169 Loc : constant Source_Ptr := Sloc (New_F);
2170 Decl : Node_Id;
2171
2172 begin
2173 -- If the formal is a tagged incomplete type, it is already passed
2174 -- by reference, so it is sufficient to rename the pointer component
2175 -- that corresponds to the actual. Otherwise we need to dereference
2176 -- the pointer component to obtain the actual.
2177
2178 if Is_Incomplete_Type (Etype (Formal))
2179 and then Is_Tagged_Type (Etype (Formal))
2180 then
2181 Decl :=
2182 Make_Object_Renaming_Declaration (Loc,
2183 Defining_Identifier => New_F,
83c6c069 2184 Subtype_Mark => New_Occurrence_Of (Etype (Comp), Loc),
b76dc1f0 2185 Name => Renamed_Formal);
2186
2187 else
2188 Decl :=
2189 Make_Object_Renaming_Declaration (Loc,
2190 Defining_Identifier => New_F,
83c6c069 2191 Subtype_Mark => New_Occurrence_Of (Etype (Formal), Loc),
b76dc1f0 2192 Name =>
2193 Make_Explicit_Dereference (Loc, Renamed_Formal));
2194 end if;
2195
2196 return Decl;
2197 end Build_Renamed_Formal_Declaration;
2198
d2a42b76 2199 --------------------------
2200 -- Build_Wrapper_Bodies --
2201 --------------------------
9f373bb8 2202
d2a42b76 2203 procedure Build_Wrapper_Bodies
2204 (Loc : Source_Ptr;
2205 Typ : Entity_Id;
2206 N : Node_Id)
9f373bb8 2207 is
d2a42b76 2208 Rec_Typ : Entity_Id;
9f373bb8 2209
d2a42b76 2210 function Build_Wrapper_Body
2211 (Loc : Source_Ptr;
2212 Subp_Id : Entity_Id;
2213 Obj_Typ : Entity_Id;
2214 Formals : List_Id) return Node_Id;
2215 -- Ada 2005 (AI-345): Build the body that wraps a primitive operation
2216 -- associated with a protected or task type. Subp_Id is the subprogram
2217 -- name which will be wrapped. Obj_Typ is the type of the new formal
2218 -- parameter which handles dispatching and object notation. Formals are
2219 -- the original formals of Subp_Id which will be explicitly replicated.
2220
2221 ------------------------
2222 -- Build_Wrapper_Body --
2223 ------------------------
2224
2225 function Build_Wrapper_Body
2226 (Loc : Source_Ptr;
2227 Subp_Id : Entity_Id;
2228 Obj_Typ : Entity_Id;
2229 Formals : List_Id) return Node_Id
2230 is
2231 Body_Spec : Node_Id;
9f373bb8 2232
d2a42b76 2233 begin
b7edc5bb 2234 Body_Spec := Build_Wrapper_Spec (Subp_Id, Obj_Typ, Formals);
9f373bb8 2235
d2a42b76 2236 -- The subprogram is not overriding or is not a primitive declared
2237 -- between two views.
9f373bb8 2238
d2a42b76 2239 if No (Body_Spec) then
2240 return Empty;
2241 end if;
9f373bb8 2242
d2a42b76 2243 declare
f9e6d9d0 2244 Actuals : List_Id := No_List;
2245 Conv_Id : Node_Id;
2246 First_Form : Node_Id;
2247 Formal : Node_Id;
2248 Nam : Node_Id;
9f373bb8 2249
d2a42b76 2250 begin
2251 -- Map formals to actuals. Use the list built for the wrapper
2252 -- spec, skipping the object notation parameter.
9f373bb8 2253
0754d6dd 2254 First_Form := First (Parameter_Specifications (Body_Spec));
9f373bb8 2255
0754d6dd 2256 Formal := First_Form;
9f373bb8 2257 Next (Formal);
9f373bb8 2258
d2a42b76 2259 if Present (Formal) then
2260 Actuals := New_List;
d2a42b76 2261 while Present (Formal) loop
2262 Append_To (Actuals,
55868293 2263 Make_Identifier (Loc,
2264 Chars => Chars (Defining_Identifier (Formal))));
d2a42b76 2265 Next (Formal);
2266 end loop;
2267 end if;
2268
2269 -- Special processing for primitives declared between a private
0754d6dd 2270 -- type and its completion: the wrapper needs a properly typed
2271 -- parameter if the wrapped operation has a controlling first
2272 -- parameter. Note that this might not be the case for a function
2273 -- with a controlling result.
d2a42b76 2274
2275 if Is_Private_Primitive_Subprogram (Subp_Id) then
2276 if No (Actuals) then
2277 Actuals := New_List;
2278 end if;
2279
0754d6dd 2280 if Is_Controlling_Formal (First_Formal (Subp_Id)) then
2281 Prepend_To (Actuals,
f9e6d9d0 2282 Unchecked_Convert_To
2283 (Corresponding_Concurrent_Type (Obj_Typ),
2284 Make_Identifier (Loc, Name_uO)));
d2a42b76 2285
0754d6dd 2286 else
2287 Prepend_To (Actuals,
55868293 2288 Make_Identifier (Loc,
2289 Chars => Chars (Defining_Identifier (First_Form))));
0754d6dd 2290 end if;
d2a42b76 2291
83c6c069 2292 Nam := New_Occurrence_Of (Subp_Id, Loc);
d2a42b76 2293 else
2294 -- An access-to-variable object parameter requires an explicit
2295 -- dereference in the unchecked conversion. This case occurs
2296 -- when a protected entry wrapper must override an interface
2297 -- level procedure with interface access as first parameter.
2298
d0fbdcb2 2299 -- O.all.Subp_Id (Formal_1, ..., Formal_N)
d2a42b76 2300
0754d6dd 2301 if Nkind (Parameter_Type (First_Form)) =
d2a42b76 2302 N_Access_Definition
2303 then
2304 Conv_Id :=
2305 Make_Explicit_Dereference (Loc,
2306 Prefix => Make_Identifier (Loc, Name_uO));
2307 else
2308 Conv_Id := Make_Identifier (Loc, Name_uO);
2309 end if;
2310
2311 Nam :=
2312 Make_Selected_Component (Loc,
d03ada96 2313 Prefix =>
f9e6d9d0 2314 Unchecked_Convert_To
2315 (Corresponding_Concurrent_Type (Obj_Typ), Conv_Id),
83c6c069 2316 Selector_Name => New_Occurrence_Of (Subp_Id, Loc));
d2a42b76 2317 end if;
2318
0754d6dd 2319 -- Create the subprogram body. For a function, the call to the
2320 -- actual subprogram has to be converted to the corresponding
2321 -- record if it is a controlling result.
d2a42b76 2322
2323 if Ekind (Subp_Id) = E_Function then
0754d6dd 2324 declare
2325 Res : Node_Id;
2326
2327 begin
2328 Res :=
2329 Make_Function_Call (Loc,
2330 Name => Nam,
2331 Parameter_Associations => Actuals);
2332
2333 if Has_Controlling_Result (Subp_Id) then
2334 Res :=
2335 Unchecked_Convert_To
2336 (Corresponding_Record_Type (Etype (Subp_Id)), Res);
2337 end if;
2338
2339 return
2340 Make_Subprogram_Body (Loc,
2341 Specification => Body_Spec,
2342 Declarations => Empty_List,
2343 Handled_Statement_Sequence =>
2344 Make_Handled_Sequence_Of_Statements (Loc,
2345 Statements => New_List (
2346 Make_Simple_Return_Statement (Loc, Res))));
2347 end;
d2a42b76 2348
2349 else
2350 return
2351 Make_Subprogram_Body (Loc,
3ade4496 2352 Specification => Body_Spec,
2353 Declarations => Empty_List,
d2a42b76 2354 Handled_Statement_Sequence =>
2355 Make_Handled_Sequence_Of_Statements (Loc,
2356 Statements => New_List (
2357 Make_Procedure_Call_Statement (Loc,
3ade4496 2358 Name => Nam,
d2a42b76 2359 Parameter_Associations => Actuals))));
2360 end if;
2361 end;
2362 end Build_Wrapper_Body;
2363
2364 -- Start of processing for Build_Wrapper_Bodies
2365
2366 begin
2367 if Is_Concurrent_Type (Typ) then
2368 Rec_Typ := Corresponding_Record_Type (Typ);
9f373bb8 2369 else
d2a42b76 2370 Rec_Typ := Typ;
9f373bb8 2371 end if;
2372
d2a42b76 2373 -- Generate wrapper bodies for a concurrent type which implements an
2374 -- interface.
2375
2376 if Present (Interfaces (Rec_Typ)) then
2377 declare
2378 Insert_Nod : Node_Id;
2379 Prim : Entity_Id;
2380 Prim_Elmt : Elmt_Id;
2381 Prim_Decl : Node_Id;
2382 Subp : Entity_Id;
2383 Wrap_Body : Node_Id;
2384 Wrap_Id : Entity_Id;
2385
2386 begin
2387 Insert_Nod := N;
2388
2389 -- Examine all primitive operations of the corresponding record
2390 -- type, looking for wrapper specs. Generate bodies in order to
2391 -- complete them.
2392
2393 Prim_Elmt := First_Elmt (Primitive_Operations (Rec_Typ));
2394 while Present (Prim_Elmt) loop
2395 Prim := Node (Prim_Elmt);
2396
2397 if (Ekind (Prim) = E_Function
c0688d2b 2398 or else Ekind (Prim) = E_Procedure)
d2a42b76 2399 and then Is_Primitive_Wrapper (Prim)
2400 then
2401 Subp := Wrapped_Entity (Prim);
2402 Prim_Decl := Parent (Parent (Prim));
2403
2404 Wrap_Body :=
2405 Build_Wrapper_Body (Loc,
2406 Subp_Id => Subp,
2407 Obj_Typ => Rec_Typ,
2408 Formals => Parameter_Specifications (Parent (Subp)));
2409 Wrap_Id := Defining_Unit_Name (Specification (Wrap_Body));
2410
2411 Set_Corresponding_Spec (Wrap_Body, Prim);
2412 Set_Corresponding_Body (Prim_Decl, Wrap_Id);
2413
2414 Insert_After (Insert_Nod, Wrap_Body);
2415 Insert_Nod := Wrap_Body;
2416
2417 Analyze (Wrap_Body);
2418 end if;
2419
2420 Next_Elmt (Prim_Elmt);
2421 end loop;
2422 end;
9f373bb8 2423 end if;
d2a42b76 2424 end Build_Wrapper_Bodies;
9f373bb8 2425
2426 ------------------------
2427 -- Build_Wrapper_Spec --
2428 ------------------------
2429
2430 function Build_Wrapper_Spec
b7edc5bb 2431 (Subp_Id : Entity_Id;
d2a42b76 2432 Obj_Typ : Entity_Id;
2433 Formals : List_Id) return Node_Id
9f373bb8 2434 is
b7edc5bb 2435 Loc : constant Source_Ptr := Sloc (Subp_Id);
d2a42b76 2436 First_Param : Node_Id;
2437 Iface : Entity_Id;
2438 Iface_Elmt : Elmt_Id;
2439 Iface_Op : Entity_Id;
2440 Iface_Op_Elmt : Elmt_Id;
9f373bb8 2441
2442 function Overriding_Possible
d2a42b76 2443 (Iface_Op : Entity_Id;
2444 Wrapper : Entity_Id) return Boolean;
2445 -- Determine whether a primitive operation can be overridden by Wrapper.
2446 -- Iface_Op is the candidate primitive operation of an interface type,
2447 -- Wrapper is the generated entry wrapper.
9f373bb8 2448
d2a42b76 2449 function Replicate_Formals
9f373bb8 2450 (Loc : Source_Ptr;
2451 Formals : List_Id) return List_Id;
d2a42b76 2452 -- An explicit parameter replication is required due to the Is_Entry_
2453 -- Formal flag being set for all the formals of an entry. The explicit
9f373bb8 2454 -- replication removes the flag that would otherwise cause a different
2455 -- path of analysis.
2456
2457 -------------------------
2458 -- Overriding_Possible --
2459 -------------------------
2460
2461 function Overriding_Possible
d2a42b76 2462 (Iface_Op : Entity_Id;
2463 Wrapper : Entity_Id) return Boolean
9f373bb8 2464 is
d2a42b76 2465 Iface_Op_Spec : constant Node_Id := Parent (Iface_Op);
2466 Wrapper_Spec : constant Node_Id := Parent (Wrapper);
9f373bb8 2467
2468 function Type_Conformant_Parameters
d2a42b76 2469 (Iface_Op_Params : List_Id;
2470 Wrapper_Params : List_Id) return Boolean;
9f373bb8 2471 -- Determine whether the parameters of the generated entry wrapper
2472 -- and those of a primitive operation are type conformant. During
2473 -- this check, the first parameter of the primitive operation is
0754d6dd 2474 -- skipped if it is a controlling argument: protected functions
2475 -- may have a controlling result.
9f373bb8 2476
2477 --------------------------------
2478 -- Type_Conformant_Parameters --
2479 --------------------------------
2480
2481 function Type_Conformant_Parameters
d2a42b76 2482 (Iface_Op_Params : List_Id;
2483 Wrapper_Params : List_Id) return Boolean
9f373bb8 2484 is
d2a42b76 2485 Iface_Op_Param : Node_Id;
2486 Iface_Op_Typ : Entity_Id;
2487 Wrapper_Param : Node_Id;
2488 Wrapper_Typ : Entity_Id;
4961db87 2489
9f373bb8 2490 begin
0754d6dd 2491 -- Skip the first (controlling) parameter of primitive operation
2492
2493 Iface_Op_Param := First (Iface_Op_Params);
2494
2495 if Present (First_Formal (Iface_Op))
2496 and then Is_Controlling_Formal (First_Formal (Iface_Op))
2497 then
2498 Iface_Op_Param := Next (Iface_Op_Param);
2499 end if;
9f373bb8 2500
d2a42b76 2501 Wrapper_Param := First (Wrapper_Params);
2502 while Present (Iface_Op_Param)
2503 and then Present (Wrapper_Param)
9f373bb8 2504 loop
d2a42b76 2505 Iface_Op_Typ := Find_Parameter_Type (Iface_Op_Param);
2506 Wrapper_Typ := Find_Parameter_Type (Wrapper_Param);
4961db87 2507
cb5f80c1 2508 -- The two parameters must be mode conformant
9f373bb8 2509
4961db87 2510 if not Conforming_Types
d2a42b76 2511 (Iface_Op_Typ, Wrapper_Typ, Mode_Conformant)
9f373bb8 2512 then
2513 return False;
2514 end if;
2515
d2a42b76 2516 Next (Iface_Op_Param);
2517 Next (Wrapper_Param);
9f373bb8 2518 end loop;
2519
2520 -- One of the lists is longer than the other
2521
d2a42b76 2522 if Present (Iface_Op_Param) or else Present (Wrapper_Param) then
9f373bb8 2523 return False;
2524 end if;
2525
2526 return True;
2527 end Type_Conformant_Parameters;
2528
2529 -- Start of processing for Overriding_Possible
2530
2531 begin
d2a42b76 2532 if Chars (Iface_Op) /= Chars (Wrapper) then
9f373bb8 2533 return False;
2534 end if;
2535
d2a42b76 2536 -- If an inherited subprogram is implemented by a protected procedure
2537 -- or an entry, then the first parameter of the inherited subprogram
ab527457 2538 -- must be of mode OUT or IN OUT, or access-to-variable parameter.
9f373bb8 2539
d2a42b76 2540 if Ekind (Iface_Op) = E_Procedure
2541 and then Present (Parameter_Specifications (Iface_Op_Spec))
2542 then
2543 declare
2544 Obj_Param : constant Node_Id :=
2545 First (Parameter_Specifications (Iface_Op_Spec));
d2a42b76 2546 begin
2547 if not Out_Present (Obj_Param)
2548 and then Nkind (Parameter_Type (Obj_Param)) /=
3ade4496 2549 N_Access_Definition
d2a42b76 2550 then
2551 return False;
2552 end if;
2553 end;
9f373bb8 2554 end if;
2555
d2a42b76 2556 return
2557 Type_Conformant_Parameters (
2558 Parameter_Specifications (Iface_Op_Spec),
2559 Parameter_Specifications (Wrapper_Spec));
9f373bb8 2560 end Overriding_Possible;
2561
d2a42b76 2562 -----------------------
2563 -- Replicate_Formals --
2564 -----------------------
9f373bb8 2565
d2a42b76 2566 function Replicate_Formals
9f373bb8 2567 (Loc : Source_Ptr;
2568 Formals : List_Id) return List_Id
2569 is
2570 New_Formals : constant List_Id := New_List;
2571 Formal : Node_Id;
57993a53 2572 Param_Type : Node_Id;
9f373bb8 2573
2574 begin
2575 Formal := First (Formals);
d2a42b76 2576
2577 -- Skip the object parameter when dealing with primitives declared
2578 -- between two views.
2579
0754d6dd 2580 if Is_Private_Primitive_Subprogram (Subp_Id)
2581 and then not Has_Controlling_Result (Subp_Id)
2582 then
d2a42b76 2583 Formal := Next (Formal);
2584 end if;
2585
76a1c25b 2586 while Present (Formal) loop
9f373bb8 2587
76a1c25b 2588 -- Create an explicit copy of the entry parameter
9f373bb8 2589
57993a53 2590 -- When creating the wrapper subprogram for a primitive operation
2591 -- of a protected interface we must construct an equivalent
2592 -- signature to that of the overriding operation. For regular
2593 -- parameters we can just use the type of the formal, but for
2594 -- access to subprogram parameters we need to reanalyze the
2595 -- parameter type to create local entities for the signature of
2596 -- the subprogram type. Using the entities of the overriding
2597 -- subprogram will result in out-of-scope errors in the back-end.
2598
2599 if Nkind (Parameter_Type (Formal)) = N_Access_Definition then
2600 Param_Type := Copy_Separate_Tree (Parameter_Type (Formal));
2601 else
2602 Param_Type :=
83c6c069 2603 New_Occurrence_Of (Etype (Parameter_Type (Formal)), Loc);
57993a53 2604 end if;
2605
76a1c25b 2606 Append_To (New_Formals,
2607 Make_Parameter_Specification (Loc,
2608 Defining_Identifier =>
2609 Make_Defining_Identifier (Loc,
6fdfe796 2610 Chars => Chars
2611 (Defining_Identifier (Formal))),
2612 In_Present => In_Present (Formal),
2613 Out_Present => Out_Present (Formal),
2614 Null_Exclusion_Present => Null_Exclusion_Present (Formal),
2615 Parameter_Type => Param_Type));
9f373bb8 2616
76a1c25b 2617 Next (Formal);
2618 end loop;
9f373bb8 2619
2620 return New_Formals;
d2a42b76 2621 end Replicate_Formals;
9f373bb8 2622
2623 -- Start of processing for Build_Wrapper_Spec
2624
2625 begin
d1a2e31b 2626 -- No point in building wrappers for untagged concurrent types
9f373bb8 2627
d2a42b76 2628 pragma Assert (Is_Tagged_Type (Obj_Typ));
76a1c25b 2629
d2a42b76 2630 -- An entry or a protected procedure can override a routine where the
2631 -- controlling formal is either IN OUT, OUT or is of access-to-variable
2632 -- type. Since the wrapper must have the exact same signature as that of
2633 -- the overridden subprogram, we try to find the overriding candidate
2634 -- and use its controlling formal.
9f373bb8 2635
d2a42b76 2636 First_Param := Empty;
9f373bb8 2637
d2a42b76 2638 -- Check every implemented interface
9f373bb8 2639
d2a42b76 2640 if Present (Interfaces (Obj_Typ)) then
2641 Iface_Elmt := First_Elmt (Interfaces (Obj_Typ));
2642 Search : while Present (Iface_Elmt) loop
cb5f80c1 2643 Iface := Node (Iface_Elmt);
2644
d2a42b76 2645 -- Check every interface primitive
2646
cb5f80c1 2647 if Present (Primitive_Operations (Iface)) then
d2a42b76 2648 Iface_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
2649 while Present (Iface_Op_Elmt) loop
2650 Iface_Op := Node (Iface_Op_Elmt);
cb5f80c1 2651
d2a42b76 2652 -- Ignore predefined primitives
2653
2654 if not Is_Predefined_Dispatching_Operation (Iface_Op) then
2655 Iface_Op := Ultimate_Alias (Iface_Op);
cb5f80c1 2656
36b938a3 2657 -- The current primitive operation can be overridden by
cb5f80c1 2658 -- the generated entry wrapper.
2659
d2a42b76 2660 if Overriding_Possible (Iface_Op, Subp_Id) then
2661 First_Param :=
2662 First (Parameter_Specifications (Parent (Iface_Op)));
cb5f80c1 2663
d2a42b76 2664 exit Search;
cb5f80c1 2665 end if;
2666 end if;
2667
d2a42b76 2668 Next_Elmt (Iface_Op_Elmt);
cb5f80c1 2669 end loop;
2670 end if;
2671
2672 Next_Elmt (Iface_Elmt);
d2a42b76 2673 end loop Search;
2674 end if;
2675
a11384db 2676 -- Ada 2012 (AI05-0090-1): If no interface primitive is covered by
2677 -- this subprogram and this is not a primitive declared between two
2678 -- views then force the generation of a wrapper. As an optimization,
2679 -- previous versions of the frontend avoid generating the wrapper;
2680 -- however, the wrapper facilitates locating and reporting an error
2681 -- when a duplicate declaration is found later. See example in
2682 -- AI05-0090-1.
d2a42b76 2683
2684 if No (First_Param)
2685 and then not Is_Private_Primitive_Subprogram (Subp_Id)
2686 then
a11384db 2687 if Is_Task_Type
2688 (Corresponding_Concurrent_Type (Obj_Typ))
2689 then
2690 First_Param :=
2691 Make_Parameter_Specification (Loc,
0f3b1f49 2692 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
2693 In_Present => True,
2694 Out_Present => False,
83c6c069 2695 Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
a11384db 2696
2697 -- For entries and procedures of protected types the mode of
2698 -- the controlling argument must be in-out.
2699
2700 else
2701 First_Param :=
2702 Make_Parameter_Specification (Loc,
2703 Defining_Identifier =>
2704 Make_Defining_Identifier (Loc,
2705 Chars => Name_uO),
2706 In_Present => True,
2707 Out_Present => (Ekind (Subp_Id) /= E_Function),
83c6c069 2708 Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
a11384db 2709 end if;
9f373bb8 2710 end if;
2711
d2a42b76 2712 declare
2713 Wrapper_Id : constant Entity_Id :=
2714 Make_Defining_Identifier (Loc, Chars (Subp_Id));
2715 New_Formals : List_Id;
2716 Obj_Param : Node_Id;
2717 Obj_Param_Typ : Entity_Id;
2718
2719 begin
2720 -- Minimum decoration is needed to catch the entity in
2721 -- Sem_Ch6.Override_Dispatching_Operation.
cb5f80c1 2722
d2a42b76 2723 if Ekind (Subp_Id) = E_Function then
2724 Set_Ekind (Wrapper_Id, E_Function);
2725 else
2726 Set_Ekind (Wrapper_Id, E_Procedure);
2727 end if;
cb5f80c1 2728
d2a42b76 2729 Set_Is_Primitive_Wrapper (Wrapper_Id);
2730 Set_Wrapped_Entity (Wrapper_Id, Subp_Id);
2731 Set_Is_Private_Primitive (Wrapper_Id,
2732 Is_Private_Primitive_Subprogram (Subp_Id));
cb5f80c1 2733
d2a42b76 2734 -- Process the formals
9f373bb8 2735
d2a42b76 2736 New_Formals := Replicate_Formals (Loc, Formals);
9f373bb8 2737
0754d6dd 2738 -- A function with a controlling result and no first controlling
2739 -- formal needs no additional parameter.
2740
2741 if Has_Controlling_Result (Subp_Id)
2742 and then
2743 (No (First_Formal (Subp_Id))
2744 or else not Is_Controlling_Formal (First_Formal (Subp_Id)))
2745 then
2746 null;
2747
d2a42b76 2748 -- Routine Subp_Id has been found to override an interface primitive.
2749 -- If the interface operation has an access parameter, create a copy
2750 -- of it, with the same null exclusion indicator if present.
57993a53 2751
0754d6dd 2752 elsif Present (First_Param) then
d2a42b76 2753 if Nkind (Parameter_Type (First_Param)) = N_Access_Definition then
2754 Obj_Param_Typ :=
2755 Make_Access_Definition (Loc,
4beb22df 2756 Subtype_Mark =>
8149276d 2757 New_Occurrence_Of (Obj_Typ, Loc),
2758 Null_Exclusion_Present =>
2759 Null_Exclusion_Present (Parameter_Type (First_Param)),
4beb22df 2760 Constant_Present =>
8149276d 2761 Constant_Present (Parameter_Type (First_Param)));
d2a42b76 2762 else
83c6c069 2763 Obj_Param_Typ := New_Occurrence_Of (Obj_Typ, Loc);
d2a42b76 2764 end if;
2765
2766 Obj_Param :=
2767 Make_Parameter_Specification (Loc,
2768 Defining_Identifier =>
3ade4496 2769 Make_Defining_Identifier (Loc,
2770 Chars => Name_uO),
2771 In_Present => In_Present (First_Param),
2772 Out_Present => Out_Present (First_Param),
2773 Parameter_Type => Obj_Param_Typ);
d2a42b76 2774
0754d6dd 2775 Prepend_To (New_Formals, Obj_Param);
2776
d2a42b76 2777 -- If we are dealing with a primitive declared between two views,
0754d6dd 2778 -- implemented by a synchronized operation, we need to create
2779 -- a default parameter. The mode of the parameter must match that
2780 -- of the primitive operation.
d2a42b76 2781
0754d6dd 2782 else
2783 pragma Assert (Is_Private_Primitive_Subprogram (Subp_Id));
d2a42b76 2784 Obj_Param :=
2785 Make_Parameter_Specification (Loc,
2786 Defining_Identifier =>
2787 Make_Defining_Identifier (Loc, Name_uO),
d4b026c1 2788 In_Present => In_Present (Parent (First_Entity (Subp_Id))),
d2a42b76 2789 Out_Present => Ekind (Subp_Id) /= E_Function,
83c6c069 2790 Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
0754d6dd 2791 Prepend_To (New_Formals, Obj_Param);
d2a42b76 2792 end if;
2793
0754d6dd 2794 -- Build the final spec. If it is a function with a controlling
2795 -- result, it is a primitive operation of the corresponding
2796 -- record type, so mark the spec accordingly.
d2a42b76 2797
2798 if Ekind (Subp_Id) = E_Function then
0754d6dd 2799 declare
2800 Res_Def : Node_Id;
2801
2802 begin
2803 if Has_Controlling_Result (Subp_Id) then
2804 Res_Def :=
2805 New_Occurrence_Of
2806 (Corresponding_Record_Type (Etype (Subp_Id)), Loc);
2807 else
2808 Res_Def := New_Copy (Result_Definition (Parent (Subp_Id)));
2809 end if;
2810
2811 return
2812 Make_Function_Specification (Loc,
2813 Defining_Unit_Name => Wrapper_Id,
2814 Parameter_Specifications => New_Formals,
2815 Result_Definition => Res_Def);
2816 end;
9f373bb8 2817 else
d2a42b76 2818 return
2819 Make_Procedure_Specification (Loc,
3ade4496 2820 Defining_Unit_Name => Wrapper_Id,
d2a42b76 2821 Parameter_Specifications => New_Formals);
9f373bb8 2822 end if;
d2a42b76 2823 end;
2824 end Build_Wrapper_Spec;
9f373bb8 2825
d2a42b76 2826 -------------------------
2827 -- Build_Wrapper_Specs --
2828 -------------------------
9f373bb8 2829
d2a42b76 2830 procedure Build_Wrapper_Specs
2831 (Loc : Source_Ptr;
2832 Typ : Entity_Id;
2833 N : in out Node_Id)
2834 is
2835 Def : Node_Id;
2836 Rec_Typ : Entity_Id;
43e39b42 2837 procedure Scan_Declarations (L : List_Id);
2838 -- Common processing for visible and private declarations
2839 -- of a protected type.
2840
2841 procedure Scan_Declarations (L : List_Id) is
2842 Decl : Node_Id;
2843 Wrap_Decl : Node_Id;
2844 Wrap_Spec : Node_Id;
2845
2846 begin
2847 if No (L) then
2848 return;
2849 end if;
2850
2851 Decl := First (L);
2852 while Present (Decl) loop
2853 Wrap_Spec := Empty;
2854
2855 if Nkind (Decl) = N_Entry_Declaration
2856 and then Ekind (Defining_Identifier (Decl)) = E_Entry
2857 then
2858 Wrap_Spec :=
2859 Build_Wrapper_Spec
2860 (Subp_Id => Defining_Identifier (Decl),
2861 Obj_Typ => Rec_Typ,
2862 Formals => Parameter_Specifications (Decl));
2863
2864 elsif Nkind (Decl) = N_Subprogram_Declaration then
2865 Wrap_Spec :=
2866 Build_Wrapper_Spec
2867 (Subp_Id => Defining_Unit_Name (Specification (Decl)),
2868 Obj_Typ => Rec_Typ,
2869 Formals =>
2870 Parameter_Specifications (Specification (Decl)));
2871 end if;
2872
2873 if Present (Wrap_Spec) then
2874 Wrap_Decl :=
2875 Make_Subprogram_Declaration (Loc,
2876 Specification => Wrap_Spec);
2877
2878 Insert_After (N, Wrap_Decl);
2879 N := Wrap_Decl;
2880
2881 Analyze (Wrap_Decl);
2882 end if;
2883
2884 Next (Decl);
2885 end loop;
2886 end Scan_Declarations;
2887
2888 -- start of processing for Build_Wrapper_Specs
d2a42b76 2889
2890 begin
2891 if Is_Protected_Type (Typ) then
2892 Def := Protected_Definition (Parent (Typ));
2893 else pragma Assert (Is_Task_Type (Typ));
2894 Def := Task_Definition (Parent (Typ));
9f373bb8 2895 end if;
2896
d2a42b76 2897 Rec_Typ := Corresponding_Record_Type (Typ);
9f373bb8 2898
d2a42b76 2899 -- Generate wrapper specs for a concurrent type which implements an
43e39b42 2900 -- interface. Operations in both the visible and private parts may
2901 -- implement progenitor operations.
9f373bb8 2902
c0688d2b 2903 if Present (Interfaces (Rec_Typ)) and then Present (Def) then
43e39b42 2904 Scan_Declarations (Visible_Declarations (Def));
2905 Scan_Declarations (Private_Declarations (Def));
9f373bb8 2906 end if;
d2a42b76 2907 end Build_Wrapper_Specs;
9f373bb8 2908
ee6ba406 2909 ---------------------------
2910 -- Build_Find_Body_Index --
2911 ---------------------------
2912
bdd64cbe 2913 function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id is
ee6ba406 2914 Loc : constant Source_Ptr := Sloc (Typ);
2915 Ent : Entity_Id;
2916 E_Typ : Entity_Id;
2917 Has_F : Boolean := False;
2918 Index : Nat;
2919 If_St : Node_Id := Empty;
2920 Lo : Node_Id;
2921 Hi : Node_Id;
2922 Decls : List_Id := New_List;
2923 Ret : Node_Id;
2924 Spec : Node_Id;
2925 Siz : Node_Id := Empty;
2926
2927 procedure Add_If_Clause (Expr : Node_Id);
2866d595 2928 -- Add test for range of current entry
ee6ba406 2929
2930 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
2931 -- If a bound of an entry is given by a discriminant, retrieve the
2932 -- actual value of the discriminant from the enclosing object.
2933
2934 -------------------
2935 -- Add_If_Clause --
2936 -------------------
2937
2938 procedure Add_If_Clause (Expr : Node_Id) is
2939 Cond : Node_Id;
2940 Stats : constant List_Id :=
2941 New_List (
0d85cfbf 2942 Make_Simple_Return_Statement (Loc,
ee6ba406 2943 Expression => Make_Integer_Literal (Loc, Index + 1)));
2944
2945 begin
2866d595 2946 -- Index for current entry body
ee6ba406 2947
7a19298b 2948 Index := Index + 1;
2949
2950 -- Compute total length of entry queues so far
2951
2952 if No (Siz) then
2953 Siz := Expr;
2954 else
2955 Siz :=
2956 Make_Op_Add (Loc,
c0688d2b 2957 Left_Opnd => Siz,
7a19298b 2958 Right_Opnd => Expr);
2959 end if;
2960
2961 Cond :=
2962 Make_Op_Le (Loc,
2963 Left_Opnd => Make_Identifier (Loc, Name_uE),
2964 Right_Opnd => Siz);
2965
2966 -- Map entry queue indexes in the range of the current family
2967 -- into the current index, that designates the entry body.
2968
2969 if No (If_St) then
2970 If_St :=
2971 Make_Implicit_If_Statement (Typ,
2972 Condition => Cond,
2973 Then_Statements => Stats,
2974 Elsif_Parts => New_List);
2975 Ret := If_St;
2976
2977 else
2978 Append_To (Elsif_Parts (If_St),
2979 Make_Elsif_Part (Loc,
2980 Condition => Cond,
2981 Then_Statements => Stats));
2982 end if;
2983 end Add_If_Clause;
2984
2985 ------------------------------
2986 -- Convert_Discriminant_Ref --
2987 ------------------------------
2988
2989 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
2990 B : Node_Id;
2991
2992 begin
2993 if Is_Entity_Name (Bound)
2994 and then Ekind (Entity (Bound)) = E_Discriminant
2995 then
2996 B :=
2997 Make_Selected_Component (Loc,
2998 Prefix =>
2999 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
3000 Make_Explicit_Dereference (Loc,
3001 Make_Identifier (Loc, Name_uObject))),
3002 Selector_Name => Make_Identifier (Loc, Chars (Bound)));
3003 Set_Etype (B, Etype (Entity (Bound)));
3004 else
3005 B := New_Copy_Tree (Bound);
3006 end if;
3007
3008 return B;
3009 end Convert_Discriminant_Ref;
3010
3011 -- Start of processing for Build_Find_Body_Index
3012
3013 begin
3014 Spec := Build_Find_Body_Index_Spec (Typ);
3015
3016 Ent := First_Entity (Typ);
3017 while Present (Ent) loop
3018 if Ekind (Ent) = E_Entry_Family then
3019 Has_F := True;
3020 exit;
3021 end if;
3022
3023 Next_Entity (Ent);
3024 end loop;
3025
3026 if not Has_F then
3027
3028 -- If the protected type has no entry families, there is a one-one
3029 -- correspondence between entry queue and entry body.
3030
3031 Ret :=
3032 Make_Simple_Return_Statement (Loc,
3033 Expression => Make_Identifier (Loc, Name_uE));
3034
3035 else
3036 -- Suppose entries e1, e2, ... have size l1, l2, ... we generate
3037 -- the following:
3038
3039 -- if E <= l1 then return 1;
3040 -- elsif E <= l1 + l2 then return 2;
3041 -- ...
3042
3043 Index := 0;
3044 Siz := Empty;
3045 Ent := First_Entity (Typ);
3046
3047 Add_Object_Pointer (Loc, Typ, Decls);
3048
3049 while Present (Ent) loop
3050 if Ekind (Ent) = E_Entry then
3051 Add_If_Clause (Make_Integer_Literal (Loc, 1));
3052
3053 elsif Ekind (Ent) = E_Entry_Family then
3054 E_Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
3055 Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
3056 Lo := Convert_Discriminant_Ref (Type_Low_Bound (E_Typ));
3057 Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ, False));
3058 end if;
3059
3060 Next_Entity (Ent);
3061 end loop;
3062
3063 if Index = 1 then
3064 Decls := New_List;
3065 Ret :=
3066 Make_Simple_Return_Statement (Loc,
3067 Expression => Make_Integer_Literal (Loc, 1));
3068
3069 elsif Nkind (Ret) = N_If_Statement then
3070
3071 -- Ranges are in increasing order, so last one doesn't need guard
3072
3073 declare
3074 Nod : constant Node_Id := Last (Elsif_Parts (Ret));
3075 begin
3076 Remove (Nod);
3077 Set_Else_Statements (Ret, Then_Statements (Nod));
3078 end;
3079 end if;
3080 end if;
3081
3082 return
3083 Make_Subprogram_Body (Loc,
3084 Specification => Spec,
3085 Declarations => Decls,
3086 Handled_Statement_Sequence =>
3087 Make_Handled_Sequence_Of_Statements (Loc,
3088 Statements => New_List (Ret)));
3089 end Build_Find_Body_Index;
3090
3091 --------------------------------
3092 -- Build_Find_Body_Index_Spec --
3093 --------------------------------
3094
3095 function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id is
3096 Loc : constant Source_Ptr := Sloc (Typ);
3097 Id : constant Entity_Id :=
3098 Make_Defining_Identifier (Loc,
3099 Chars => New_External_Name (Chars (Typ), 'F'));
3100 Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
3101 Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
3102
3103 begin
3104 return
3105 Make_Function_Specification (Loc,
3106 Defining_Unit_Name => Id,
3107 Parameter_Specifications => New_List (
3108 Make_Parameter_Specification (Loc,
3109 Defining_Identifier => Parm1,
3110 Parameter_Type =>
83c6c069 3111 New_Occurrence_Of (RTE (RE_Address), Loc)),
7a19298b 3112
3113 Make_Parameter_Specification (Loc,
3114 Defining_Identifier => Parm2,
3115 Parameter_Type =>
83c6c069 3116 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
7a19298b 3117
3118 Result_Definition => New_Occurrence_Of (
3119 RTE (RE_Protected_Entry_Index), Loc));
3120 end Build_Find_Body_Index_Spec;
3121
3122 -----------------------------------------------
3123 -- Build_Lock_Free_Protected_Subprogram_Body --
3124 -----------------------------------------------
3125
3126 function Build_Lock_Free_Protected_Subprogram_Body
e12ab46d 3127 (N : Node_Id;
3128 Prot_Typ : Node_Id;
3129 Unprot_Spec : Node_Id) return Node_Id
7a19298b 3130 is
e12ab46d 3131 Actuals : constant List_Id := New_List;
3132 Loc : constant Source_Ptr := Sloc (N);
3133 Spec : constant Node_Id := Specification (N);
3134 Unprot_Id : constant Entity_Id := Defining_Unit_Name (Unprot_Spec);
3135 Formal : Node_Id;
3136 Prot_Spec : Node_Id;
3137 Stmt : Node_Id;
7a19298b 3138
3139 begin
e12ab46d 3140 -- Create the protected version of the body
7a19298b 3141
e12ab46d 3142 Prot_Spec :=
3143 Build_Protected_Sub_Specification (N, Prot_Typ, Protected_Mode);
7a19298b 3144
e12ab46d 3145 -- Build the actual parameters which appear in the call to the
3146 -- unprotected version of the body.
7a19298b 3147
e12ab46d 3148 Formal := First (Parameter_Specifications (Prot_Spec));
3149 while Present (Formal) loop
3150 Append_To (Actuals,
3151 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
3152
3153 Next (Formal);
7a19298b 3154 end loop;
3155
e12ab46d 3156 -- Function case, generate:
3157 -- return <Unprot_Func_Call>;
7a19298b 3158
e12ab46d 3159 if Nkind (Spec) = N_Function_Specification then
3160 Stmt :=
3161 Make_Simple_Return_Statement (Loc,
3162 Expression =>
3163 Make_Function_Call (Loc,
3164 Name =>
3165 Make_Identifier (Loc, Chars (Unprot_Id)),
3166 Parameter_Associations => Actuals));
7a19298b 3167
e12ab46d 3168 -- Procedure case, call the unprotected version
7a19298b 3169
3170 else
e12ab46d 3171 Stmt :=
7a19298b 3172 Make_Procedure_Call_Statement (Loc,
e12ab46d 3173 Name =>
3174 Make_Identifier (Loc, Chars (Unprot_Id)),
3175 Parameter_Associations => Actuals);
7a19298b 3176 end if;
3177
3178 return
3179 Make_Subprogram_Body (Loc,
e12ab46d 3180 Declarations => Empty_List,
3181 Specification => Prot_Spec,
7a19298b 3182 Handled_Statement_Sequence =>
3183 Make_Handled_Sequence_Of_Statements (Loc,
e12ab46d 3184 Statements => New_List (Stmt)));
7a19298b 3185 end Build_Lock_Free_Protected_Subprogram_Body;
3186
3187 -------------------------------------------------
3188 -- Build_Lock_Free_Unprotected_Subprogram_Body --
3189 -------------------------------------------------
3190
e12ab46d 3191 -- Procedures which meet the lock-free implementation requirements and
3192 -- reference a unique scalar component Comp are expanded in the following
3193 -- manner:
3194
3195 -- procedure P (...) is
da2e82e9 3196 -- Expected_Comp : constant Comp_Type :=
3197 -- Comp_Type
3198 -- (System.Atomic_Primitives.Lock_Free_Read_N
3199 -- (_Object.Comp'Address));
e12ab46d 3200 -- begin
3201 -- loop
3202 -- declare
d0a9ea3b 3203 -- <original declarations before the object renaming declaration
3204 -- of Comp>
da2e82e9 3205 --
3206 -- Desired_Comp : Comp_Type := Expected_Comp;
3207 -- Comp : Comp_Type renames Desired_Comp;
3208 --
d0a9ea3b 3209 -- <original delarations after the object renaming declaration
3210 -- of Comp>
da2e82e9 3211 --
e12ab46d 3212 -- begin
3213 -- <original statements>
da2e82e9 3214 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3215 -- (_Object.Comp'Address,
3216 -- Interfaces.Unsigned_N (Expected_Comp),
3217 -- Interfaces.Unsigned_N (Desired_Comp));
e12ab46d 3218 -- end;
e12ab46d 3219 -- end loop;
3220 -- end P;
3221
d0a9ea3b 3222 -- Each return and raise statement of P is transformed into an atomic
3223 -- status check:
e12ab46d 3224
da2e82e9 3225 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
3226 -- (_Object.Comp'Address,
3227 -- Interfaces.Unsigned_N (Expected_Comp),
3228 -- Interfaces.Unsigned_N (Desired_Comp));
3229 -- then
e12ab46d 3230 -- <original statement>
3231 -- else
3232 -- goto L0;
3233 -- end if;
3234
3235 -- Functions which meet the lock-free implementation requirements and
3236 -- reference a unique scalar component Comp are expanded in the following
3237 -- manner:
3238
3239 -- function F (...) return ... is
d0a9ea3b 3240 -- <original declarations before the object renaming declaration
3241 -- of Comp>
da2e82e9 3242 --
3243 -- Expected_Comp : constant Comp_Type :=
3244 -- Comp_Type
3245 -- (System.Atomic_Primitives.Lock_Free_Read_N
3246 -- (_Object.Comp'Address));
3247 -- Comp : Comp_Type renames Expected_Comp;
3248 --
d0a9ea3b 3249 -- <original delarations after the object renaming declaration of
3250 -- Comp>
da2e82e9 3251 --
e12ab46d 3252 -- begin
3253 -- <original statements>
3254 -- end F;
3255
7a19298b 3256 function Build_Lock_Free_Unprotected_Subprogram_Body
e12ab46d 3257 (N : Node_Id;
3258 Prot_Typ : Node_Id) return Node_Id
7a19298b 3259 is
e12ab46d 3260 function Referenced_Component (N : Node_Id) return Entity_Id;
3261 -- Subprograms which meet the lock-free implementation criteria are
3262 -- allowed to reference only one unique component. Return the prival
3263 -- of the said component.
7a19298b 3264
e12ab46d 3265 --------------------------
3266 -- Referenced_Component --
3267 --------------------------
7a19298b 3268
e12ab46d 3269 function Referenced_Component (N : Node_Id) return Entity_Id is
3270 Comp : Entity_Id;
3271 Decl : Node_Id;
3272 Source_Comp : Entity_Id := Empty;
7a19298b 3273
e12ab46d 3274 begin
3275 -- Find the unique source component which N references in its
3276 -- statements.
7a19298b 3277
e12ab46d 3278 for Index in 1 .. Lock_Free_Subprogram_Table.Last loop
3279 declare
3280 Element : Lock_Free_Subprogram renames
3281 Lock_Free_Subprogram_Table.Table (Index);
3282 begin
3283 if Element.Sub_Body = N then
3284 Source_Comp := Element.Comp_Id;
3285 exit;
3286 end if;
3287 end;
3288 end loop;
7a19298b 3289
e12ab46d 3290 if No (Source_Comp) then
3291 return Empty;
3292 end if;
3293
3294 -- Find the prival which corresponds to the source component within
3295 -- the declarations of N.
3296
3297 Decl := First (Declarations (N));
3298 while Present (Decl) loop
7a19298b 3299
e12ab46d 3300 -- Privals appear as object renamings
7a19298b 3301
e12ab46d 3302 if Nkind (Decl) = N_Object_Renaming_Declaration then
3303 Comp := Defining_Identifier (Decl);
7a19298b 3304
e12ab46d 3305 if Present (Prival_Link (Comp))
3306 and then Prival_Link (Comp) = Source_Comp
3307 then
3308 return Comp;
3309 end if;
3310 end if;
7a19298b 3311
e12ab46d 3312 Next (Decl);
3313 end loop;
7a19298b 3314
e12ab46d 3315 return Empty;
3316 end Referenced_Component;
ee6ba406 3317
e12ab46d 3318 -- Local variables
ee6ba406 3319
da2e82e9 3320 Comp : constant Entity_Id := Referenced_Component (N);
3321 Loc : constant Source_Ptr := Sloc (N);
3322 Hand_Stmt_Seq : Node_Id := Handled_Statement_Sequence (N);
3323 Decls : List_Id := Declarations (N);
ee6ba406 3324
e12ab46d 3325 -- Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
ee6ba406 3326
e12ab46d 3327 begin
3ff5e35d 3328 -- Add renamings for the protection object, discriminals, privals, and
d0a9ea3b 3329 -- the entry index constant for use by debugger.
3330
3331 Debug_Private_Data_Declarations (Decls);
ee6ba406 3332
e12ab46d 3333 -- Perform the lock-free expansion when the subprogram references a
3334 -- protected component.
ee6ba406 3335
e12ab46d 3336 if Present (Comp) then
10381db1 3337 Protected_Component_Ref : declare
d0a9ea3b 3338 Comp_Decl : constant Node_Id := Parent (Comp);
3339 Comp_Sel_Nam : constant Node_Id := Name (Comp_Decl);
7413d80d 3340 Comp_Type : constant Entity_Id := Etype (Comp);
da2e82e9 3341
3342 Is_Procedure : constant Boolean :=
3343 Ekind (Corresponding_Spec (N)) = E_Procedure;
3344 -- Indicates if N is a protected procedure body
3345
3346 Block_Decls : List_Id;
3347 Try_Write : Entity_Id;
3348 Desired_Comp : Entity_Id;
3349 Decl : Node_Id;
3350 Label : Node_Id;
3351 Label_Id : Entity_Id := Empty;
3352 Read : Entity_Id;
3353 Expected_Comp : Entity_Id;
3354 Stmt : Node_Id;
3355 Stmts : List_Id :=
3356 New_Copy_List (Statements (Hand_Stmt_Seq));
3357 Typ_Size : Int;
3358 Unsigned : Entity_Id;
ee6ba406 3359
d0a9ea3b 3360 function Process_Node (N : Node_Id) return Traverse_Result;
3361 -- Transform a single node if it is a return statement, a raise
3362 -- statement or a reference to Comp.
3363
3364 procedure Process_Stmts (Stmts : List_Id);
3365 -- Given a statement sequence Stmts, wrap any return or raise
3366 -- statements in the following manner:
3367 --
da2e82e9 3368 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
3369 -- (_Object.Comp'Address,
3370 -- Interfaces.Unsigned_N (Expected_Comp),
3371 -- Interfaces.Unsigned_N (Desired_Comp))
d0a9ea3b 3372 -- then
3373 -- <Stmt>;
3374 -- else
3375 -- goto L0;
3376 -- end if;
3377
3378 ------------------
3379 -- Process_Node --
3380 ------------------
3381
3382 function Process_Node (N : Node_Id) return Traverse_Result is
3383
3384 procedure Wrap_Statement (Stmt : Node_Id);
3385 -- Wrap an arbitrary statement inside an if statement where the
3386 -- condition does an atomic check on the state of the object.
3387
3388 --------------------
3389 -- Wrap_Statement --
3390 --------------------
3391
3392 procedure Wrap_Statement (Stmt : Node_Id) is
3393 begin
3394 -- The first time through, create the declaration of a label
3395 -- which is used to skip the remainder of source statements
3396 -- if the state of the object has changed.
3397
3398 if No (Label_Id) then
3399 Label_Id :=
3400 Make_Identifier (Loc, New_External_Name ('L', 0));
3401 Set_Entity (Label_Id,
3402 Make_Defining_Identifier (Loc, Chars (Label_Id)));
3403 end if;
3404
3405 -- Generate:
da2e82e9 3406 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
3407 -- (_Object.Comp'Address,
3408 -- Interfaces.Unsigned_N (Expected_Comp),
3409 -- Interfaces.Unsigned_N (Desired_Comp))
d0a9ea3b 3410 -- then
3411 -- <Stmt>;
3412 -- else
3413 -- goto L0;
3414 -- end if;
3415
3416 Rewrite (Stmt,
85377c9b 3417 Make_Implicit_If_Statement (N,
094ed68e 3418 Condition =>
d0a9ea3b 3419 Make_Function_Call (Loc,
3420 Name =>
83c6c069 3421 New_Occurrence_Of (Try_Write, Loc),
d0a9ea3b 3422 Parameter_Associations => New_List (
3423 Make_Attribute_Reference (Loc,
3424 Prefix => Relocate_Node (Comp_Sel_Nam),
3425 Attribute_Name => Name_Address),
3426
3427 Unchecked_Convert_To (Unsigned,
83c6c069 3428 New_Occurrence_Of (Expected_Comp, Loc)),
d0a9ea3b 3429
3430 Unchecked_Convert_To (Unsigned,
83c6c069 3431 New_Occurrence_Of (Desired_Comp, Loc)))),
d0a9ea3b 3432
3433 Then_Statements => New_List (Relocate_Node (Stmt)),
3434
3435 Else_Statements => New_List (
3436 Make_Goto_Statement (Loc,
3437 Name =>
83c6c069 3438 New_Occurrence_Of (Entity (Label_Id), Loc)))));
d0a9ea3b 3439 end Wrap_Statement;
3440
3441 -- Start of processing for Process_Node
3442
3443 begin
3444 -- Wrap each return and raise statement that appear inside a
3445 -- procedure. Skip the last return statement which is added by
3446 -- default since it is transformed into an exit statement.
3447
3448 if Is_Procedure
3449 and then ((Nkind (N) = N_Simple_Return_Statement
3450 and then N /= Last (Stmts))
3451 or else Nkind (N) = N_Extended_Return_Statement
3452 or else (Nkind_In (N, N_Raise_Constraint_Error,
3453 N_Raise_Program_Error,
3454 N_Raise_Statement,
3455 N_Raise_Storage_Error)
3456 and then Comes_From_Source (N)))
3457 then
3458 Wrap_Statement (N);
3459 return Skip;
3460 end if;
3461
3462 -- Force reanalysis
3463
3464 Set_Analyzed (N, False);
3465
3466 return OK;
3467 end Process_Node;
3468
3469 procedure Process_Nodes is new Traverse_Proc (Process_Node);
3470
3471 -------------------
3472 -- Process_Stmts --
3473 -------------------
3474
3475 procedure Process_Stmts (Stmts : List_Id) is
3476 Stmt : Node_Id;
d0a9ea3b 3477 begin
3478 Stmt := First (Stmts);
3479 while Present (Stmt) loop
3480 Process_Nodes (Stmt);
3481 Next (Stmt);
3482 end loop;
3483 end Process_Stmts;
3484
10381db1 3485 -- Start of processing for Protected_Component_Ref
3486
e12ab46d 3487 begin
7413d80d 3488 -- Get the type size
3489
ba9b1a39 3490 if Known_Static_Esize (Comp_Type) then
7413d80d 3491 Typ_Size := UI_To_Int (Esize (Comp_Type));
3492
623e8f94 3493 -- If the Esize (Object_Size) is unknown at compile time, look at
7413d80d 3494 -- the RM_Size (Value_Size) since it may have been set by an
3495 -- explicit representation clause.
3496
ba9b1a39 3497 elsif Known_Static_RM_Size (Comp_Type) then
1094a5ca 3498 Typ_Size := UI_To_Int (RM_Size (Comp_Type));
3499
3500 -- Should not happen since this has already been checked in
3501 -- Allows_Lock_Free_Implementation (see Sem_Ch9).
a16536f8 3502
7413d80d 3503 else
1094a5ca 3504 raise Program_Error;
7413d80d 3505 end if;
3506
e12ab46d 3507 -- Retrieve all relevant atomic routines and types
ee6ba406 3508
e12ab46d 3509 case Typ_Size is
3510 when 8 =>
da2e82e9 3511 Try_Write := RTE (RE_Lock_Free_Try_Write_8);
3512 Read := RTE (RE_Lock_Free_Read_8);
3513 Unsigned := RTE (RE_Uint8);
ee6ba406 3514
e12ab46d 3515 when 16 =>
da2e82e9 3516 Try_Write := RTE (RE_Lock_Free_Try_Write_16);
3517 Read := RTE (RE_Lock_Free_Read_16);
3518 Unsigned := RTE (RE_Uint16);
ee6ba406 3519
e12ab46d 3520 when 32 =>
da2e82e9 3521 Try_Write := RTE (RE_Lock_Free_Try_Write_32);
3522 Read := RTE (RE_Lock_Free_Read_32);
3523 Unsigned := RTE (RE_Uint32);
7a19298b 3524
e12ab46d 3525 when 64 =>
da2e82e9 3526 Try_Write := RTE (RE_Lock_Free_Try_Write_64);
3527 Read := RTE (RE_Lock_Free_Read_64);
3528 Unsigned := RTE (RE_Uint64);
ee6ba406 3529
e12ab46d 3530 when others =>
3531 raise Program_Error;
3532 end case;
ee6ba406 3533
e12ab46d 3534 -- Generate:
da2e82e9 3535 -- Expected_Comp : constant Comp_Type :=
3536 -- Comp_Type
3537 -- (System.Atomic_Primitives.Lock_Free_Read_N
3538 -- (_Object.Comp'Address));
ee6ba406 3539
da2e82e9 3540 Expected_Comp :=
e12ab46d 3541 Make_Defining_Identifier (Loc,
3542 New_External_Name (Chars (Comp), Suffix => "_saved"));
ee6ba406 3543
e12ab46d 3544 Decl :=
3545 Make_Object_Declaration (Loc,
da2e82e9 3546 Defining_Identifier => Expected_Comp,
83c6c069 3547 Object_Definition => New_Occurrence_Of (Comp_Type, Loc),
da2e82e9 3548 Constant_Present => True,
e12ab46d 3549 Expression =>
7413d80d 3550 Unchecked_Convert_To (Comp_Type,
e12ab46d 3551 Make_Function_Call (Loc,
83c6c069 3552 Name => New_Occurrence_Of (Read, Loc),
da2e82e9 3553 Parameter_Associations => New_List (
3554 Make_Attribute_Reference (Loc,
3555 Prefix => Relocate_Node (Comp_Sel_Nam),
3556 Attribute_Name => Name_Address)))));
ee6ba406 3557
e12ab46d 3558 -- Protected procedures
ee6ba406 3559
e12ab46d 3560 if Is_Procedure then
d0a9ea3b 3561 -- Move the original declarations inside the generated block
3562
3563 Block_Decls := Decls;
3564
da2e82e9 3565 -- Reset the declarations list of the protected procedure to
3566 -- contain only Decl.
d0a9ea3b 3567
da2e82e9 3568 Decls := New_List (Decl);
ee6ba406 3569
e12ab46d 3570 -- Generate:
da2e82e9 3571 -- Desired_Comp : Comp_Type := Expected_Comp;
ee6ba406 3572
da2e82e9 3573 Desired_Comp :=
e12ab46d 3574 Make_Defining_Identifier (Loc,
3575 New_External_Name (Chars (Comp), Suffix => "_current"));
ee6ba406 3576
da2e82e9 3577 -- Insert the declarations of Expected_Comp and Desired_Comp in
d0a9ea3b 3578 -- the block declarations right before the renaming of the
3579 -- protected component.
3580
d0a9ea3b 3581 Insert_Before (Comp_Decl,
e12ab46d 3582 Make_Object_Declaration (Loc,
da2e82e9 3583 Defining_Identifier => Desired_Comp,
83c6c069 3584 Object_Definition => New_Occurrence_Of (Comp_Type, Loc),
d0a9ea3b 3585 Expression =>
83c6c069 3586 New_Occurrence_Of (Expected_Comp, Loc)));
ee6ba406 3587
e12ab46d 3588 -- Protected function
ee6ba406 3589
e12ab46d 3590 else
da2e82e9 3591 Desired_Comp := Expected_Comp;
d0a9ea3b 3592
da2e82e9 3593 -- Insert the declaration of Expected_Comp in the function
d0a9ea3b 3594 -- declarations right before the renaming of the protected
3595 -- component.
3596
3597 Insert_Before (Comp_Decl, Decl);
e12ab46d 3598 end if;
ee6ba406 3599
d0a9ea3b 3600 -- Rewrite the protected component renaming declaration to be a
da2e82e9 3601 -- renaming of Desired_Comp.
d0a9ea3b 3602
3603 -- Generate:
da2e82e9 3604 -- Comp : Comp_Type renames Desired_Comp;
d0a9ea3b 3605
3606 Rewrite (Comp_Decl,
3607 Make_Object_Renaming_Declaration (Loc,
3608 Defining_Identifier =>
3609 Defining_Identifier (Comp_Decl),
094ed68e 3610 Subtype_Mark =>
d0a9ea3b 3611 New_Occurrence_Of (Comp_Type, Loc),
094ed68e 3612 Name =>
83c6c069 3613 New_Occurrence_Of (Desired_Comp, Loc)));
d0a9ea3b 3614
3615 -- Wrap any return or raise statements in Stmts in same the manner
3616 -- described in Process_Stmts.
3617
3618 Process_Stmts (Stmts);
ee6ba406 3619
e12ab46d 3620 -- Generate:
da2e82e9 3621 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3622 -- (_Object.Comp'Address,
3623 -- Interfaces.Unsigned_N (Expected_Comp),
3624 -- Interfaces.Unsigned_N (Desired_Comp))
e12ab46d 3625
3626 if Is_Procedure then
3627 Stmt :=
3628 Make_Exit_Statement (Loc,
3629 Condition =>
3630 Make_Function_Call (Loc,
3631 Name =>
83c6c069 3632 New_Occurrence_Of (Try_Write, Loc),
e12ab46d 3633 Parameter_Associations => New_List (
3634 Make_Attribute_Reference (Loc,
d0a9ea3b 3635 Prefix => Relocate_Node (Comp_Sel_Nam),
e12ab46d 3636 Attribute_Name => Name_Address),
ee6ba406 3637
e12ab46d 3638 Unchecked_Convert_To (Unsigned,
83c6c069 3639 New_Occurrence_Of (Expected_Comp, Loc)),
e12ab46d 3640
3641 Unchecked_Convert_To (Unsigned,
83c6c069 3642 New_Occurrence_Of (Desired_Comp, Loc)))));
e12ab46d 3643
3644 -- Small optimization: transform the default return statement
3645 -- of a procedure into the atomic exit statement.
3646
3647 if Nkind (Last (Stmts)) = N_Simple_Return_Statement then
3648 Rewrite (Last (Stmts), Stmt);
3649 else
3650 Append_To (Stmts, Stmt);
3651 end if;
3652 end if;
3653
3654 -- Create the declaration of the label used to skip the rest of
3655 -- the source statements when the object state changes.
3656
3657 if Present (Label_Id) then
3658 Label := Make_Label (Loc, Label_Id);
e12ab46d 3659 Append_To (Decls,
3660 Make_Implicit_Label_Declaration (Loc,
3661 Defining_Identifier => Entity (Label_Id),
3662 Label_Construct => Label));
e12ab46d 3663 Append_To (Stmts, Label);
3664 end if;
3665
3666 -- Generate:
3667 -- loop
3668 -- declare
3669 -- <Decls>
3670 -- begin
3671 -- <Stmts>
3672 -- end;
3673 -- end loop;
3674
3675 if Is_Procedure then
10381db1 3676 Stmts :=
3677 New_List (
10381db1 3678 Make_Loop_Statement (Loc,
3679 Statements => New_List (
3680 Make_Block_Statement (Loc,
3681 Declarations => Block_Decls,
3682 Handled_Statement_Sequence =>
3683 Make_Handled_Sequence_Of_Statements (Loc,
3684 Statements => Stmts))),
3685 End_Label => Empty));
e12ab46d 3686 end if;
d0a9ea3b 3687
3688 Hand_Stmt_Seq :=
3689 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts);
10381db1 3690 end Protected_Component_Ref;
e12ab46d 3691 end if;
3692
7a19298b 3693 -- Make an unprotected version of the subprogram for use within the same
3694 -- object, with new name and extra parameter representing the object.
ee6ba406 3695
e12ab46d 3696 return
ee6ba406 3697 Make_Subprogram_Body (Loc,
7a19298b 3698 Specification =>
e12ab46d 3699 Build_Protected_Sub_Specification (N, Prot_Typ, Unprotected_Mode),
7a19298b 3700 Declarations => Decls,
d0a9ea3b 3701 Handled_Statement_Sequence => Hand_Stmt_Seq);
7a19298b 3702 end Build_Lock_Free_Unprotected_Subprogram_Body;
ee6ba406 3703
3704 -------------------------
3705 -- Build_Master_Entity --
3706 -------------------------
3707
43602818 3708 procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
3709 Loc : constant Source_Ptr := Sloc (Obj_Or_Typ);
3710 Context : Node_Id;
3711 Context_Id : Entity_Id;
3712 Decl : Node_Id;
3713 Decls : List_Id;
3714 Par : Node_Id;
d5b349fa 3715
ee6ba406 3716 begin
43602818 3717 if Is_Itype (Obj_Or_Typ) then
3718 Par := Associated_Node_For_Itype (Obj_Or_Typ);
9d0eada4 3719 else
43602818 3720 Par := Parent (Obj_Or_Typ);
9d0eada4 3721 end if;
5dad4396 3722
43602818 3723 -- When creating a master for a record component which is either a task
3724 -- or access-to-task, the enclosing record is the master scope and the
3725 -- proper insertion point is the component list.
1e16c51c 3726
43602818 3727 if Is_Record_Type (Current_Scope) then
3728 Context := Par;
3729 Context_Id := Current_Scope;
3730 Decls := List_Containing (Context);
ee6ba406 3731
43602818 3732 -- Default case for object declarations and access types. Note that the
3ff5e35d 3733 -- context is updated to the nearest enclosing body, block, package, or
43602818 3734 -- return statement.
9d0eada4 3735
9d0eada4 3736 else
43602818 3737 Find_Enclosing_Context (Par, Context, Context_Id, Decls);
3738 end if;
3739
3740 -- Do not create a master if one already exists or there is no task
3741 -- hierarchy.
3742
3743 if Has_Master_Entity (Context_Id)
3744 or else Restriction_Active (No_Task_Hierarchy)
3745 then
3746 return;
9d0eada4 3747 end if;
3748
3749 -- Create a master, generate:
ee6ba406 3750 -- _Master : constant Master_Id := Current_Master.all;
ee6ba406 3751
43602818 3752 Decl :=
ee6ba406 3753 Make_Object_Declaration (Loc,
3754 Defining_Identifier =>
3755 Make_Defining_Identifier (Loc, Name_uMaster),
9d0eada4 3756 Constant_Present => True,
83c6c069 3757 Object_Definition => New_Occurrence_Of (RTE (RE_Master_Id), Loc),
9d0eada4 3758 Expression =>
ee6ba406 3759 Make_Explicit_Dereference (Loc,
83c6c069 3760 New_Occurrence_Of (RTE (RE_Current_Master), Loc)));
ee6ba406 3761
43602818 3762 -- The master is inserted at the start of the declarative list of the
3763 -- context.
5dad4396 3764
43602818 3765 Prepend_To (Decls, Decl);
ee6ba406 3766
43602818 3767 -- In certain cases where transient scopes are involved, the immediate
3768 -- scope is not always the proper master scope. Ensure that the master
3769 -- declaration and entity appear in the same context.
ee6ba406 3770
43602818 3771 if Context_Id /= Current_Scope then
3772 Push_Scope (Context_Id);
3773 Analyze (Decl);
3774 Pop_Scope;
3775 else
3776 Analyze (Decl);
3777 end if;
3778
3779 -- Mark the enclosing scope and its associated construct as being task
3780 -- masters.
ee6ba406 3781
43602818 3782 Set_Has_Master_Entity (Context_Id);
ee6ba406 3783
43602818 3784 while Present (Context)
3785 and then Nkind (Context) /= N_Compilation_Unit
3786 loop
9d0eada4 3787 if Nkind_In (Context, N_Block_Statement,
3788 N_Subprogram_Body,
3789 N_Task_Body)
ee6ba406 3790 then
43602818 3791 Set_Is_Task_Master (Context);
3792 exit;
ee6ba406 3793
9d0eada4 3794 elsif Nkind (Parent (Context)) = N_Subunit then
3795 Context := Corresponding_Stub (Parent (Context));
ee6ba406 3796 end if;
43602818 3797
3798 Context := Parent (Context);
ee6ba406 3799 end loop;
3800 end Build_Master_Entity;
3801
9d0eada4 3802 ---------------------------
3803 -- Build_Master_Renaming --
3804 ---------------------------
3805
43602818 3806 procedure Build_Master_Renaming
3807 (Ptr_Typ : Entity_Id;
3808 Ins_Nod : Node_Id := Empty)
3809 is
3810 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
3811 Context : Node_Id;
9d0eada4 3812 Master_Decl : Node_Id;
3813 Master_Id : Entity_Id;
3814
3815 begin
3816 -- Nothing to do if there is no task hierarchy
3817
3818 if Restriction_Active (No_Task_Hierarchy) then
3819 return;
3820 end if;
3821
43602818 3822 -- Determine the proper context to insert the master renaming
3823
3824 if Present (Ins_Nod) then
3825 Context := Ins_Nod;
3826 elsif Is_Itype (Ptr_Typ) then
3827 Context := Associated_Node_For_Itype (Ptr_Typ);
3828 else
3829 Context := Parent (Ptr_Typ);
3830 end if;
3831
3832 -- Generate:
3833 -- <Ptr_Typ>M : Master_Id renames _Master;
3834
9d0eada4 3835 Master_Id :=
3836 Make_Defining_Identifier (Loc,
43602818 3837 New_External_Name (Chars (Ptr_Typ), 'M'));
9d0eada4 3838
3839 Master_Decl :=
3840 Make_Object_Renaming_Declaration (Loc,
3841 Defining_Identifier => Master_Id,
83c6c069 3842 Subtype_Mark => New_Occurrence_Of (RTE (RE_Master_Id), Loc),
9d0eada4 3843 Name => Make_Identifier (Loc, Name_uMaster));
3844
43602818 3845 Insert_Action (Context, Master_Decl);
9d0eada4 3846
43602818 3847 -- The renamed master now services the access type
3848
3849 Set_Master_Id (Ptr_Typ, Master_Id);
9d0eada4 3850 end Build_Master_Renaming;
3851
4606d5a9 3852 -----------------------------------------
3853 -- Build_Private_Protected_Declaration --
3854 -----------------------------------------
3855
3fecb07d 3856 function Build_Private_Protected_Declaration
3857 (N : Node_Id) return Entity_Id
4606d5a9 3858 is
3859 Loc : constant Source_Ptr := Sloc (N);
3860 Body_Id : constant Entity_Id := Defining_Entity (N);
3861 Decl : Node_Id;
3862 Plist : List_Id;
3863 Formal : Entity_Id;
3864 New_Spec : Node_Id;
3865 Spec_Id : Entity_Id;
3866
3867 begin
3868 Formal := First_Formal (Body_Id);
3869
3fecb07d 3870 -- The protected operation always has at least one formal, namely the
3871 -- object itself, but it is only placed in the parameter list if
3872 -- expansion is enabled.
4606d5a9 3873
3fecb07d 3874 if Present (Formal) or else Expander_Active then
4606d5a9 3875 Plist := Copy_Parameter_List (Body_Id);
3876 else
3877 Plist := No_List;
3878 end if;
3879
3880 if Nkind (Specification (N)) = N_Procedure_Specification then
3881 New_Spec :=
3882 Make_Procedure_Specification (Loc,
3fecb07d 3883 Defining_Unit_Name =>
4606d5a9 3884 Make_Defining_Identifier (Sloc (Body_Id),
3885 Chars => Chars (Body_Id)),
3fecb07d 3886 Parameter_Specifications =>
3887 Plist);
4606d5a9 3888 else
3889 New_Spec :=
3890 Make_Function_Specification (Loc,
86ab3fb8 3891 Defining_Unit_Name =>
3892 Make_Defining_Identifier (Sloc (Body_Id),
3893 Chars => Chars (Body_Id)),
3894 Parameter_Specifications => Plist,
3895 Result_Definition =>
3896 New_Occurrence_Of (Etype (Body_Id), Loc));
4606d5a9 3897 end if;
3898
3fecb07d 3899 Decl := Make_Subprogram_Declaration (Loc, Specification => New_Spec);
4606d5a9 3900 Insert_Before (N, Decl);
3901 Spec_Id := Defining_Unit_Name (New_Spec);
3902
3fecb07d 3903 -- Indicate that the entity comes from source, to ensure that cross-
3904 -- reference information is properly generated. The body itself is
3905 -- rewritten during expansion, and the body entity will not appear in
3906 -- calls to the operation.
4606d5a9 3907
3908 Set_Comes_From_Source (Spec_Id, True);
3909 Analyze (Decl);
3910 Set_Has_Completion (Spec_Id);
3911 Set_Convention (Spec_Id, Convention_Protected);
3912 return Spec_Id;
3913 end Build_Private_Protected_Declaration;
3914
ee6ba406 3915 ---------------------------
3916 -- Build_Protected_Entry --
3917 ---------------------------
3918
3919 function Build_Protected_Entry
bdd64cbe 3920 (N : Node_Id;
3921 Ent : Entity_Id;
3922 Pid : Node_Id) return Node_Id
ee6ba406 3923 is
3ff5e35d 3924 Bod_Decls : constant List_Id := New_List;
3925 Decls : constant List_Id := Declarations (N);
3926 End_Lab : constant Node_Id :=
3927 End_Label (Handled_Statement_Sequence (N));
3928 End_Loc : constant Source_Ptr :=
3929 Sloc (Last (Statements (Handled_Statement_Sequence (N))));
3930 -- Used for the generated call to Complete_Entry_Body
3931
4961db87 3932 Loc : constant Source_Ptr := Sloc (N);
3933
3ff5e35d 3934 Bod_Id : Entity_Id;
3935 Bod_Spec : Node_Id;
3936 Bod_Stmts : List_Id;
3937 Complete : Node_Id;
3938 Ohandle : Node_Id;
4961db87 3939
3ff5e35d 3940 EH_Loc : Source_Ptr;
4961db87 3941 -- Used for the exception handler, inserted at end of the body
3942
ee6ba406 3943 begin
4961db87 3944 -- Set the source location on the exception handler only when debugging
3945 -- the expanded code (see Make_Implicit_Exception_Handler).
3946
3947 if Debug_Generated_Code then
3ff5e35d 3948 EH_Loc := End_Loc;
0d85cfbf 3949
424dddae 3950 -- Otherwise the inserted code should not be visible to the debugger
0d85cfbf 3951
4961db87 3952 else
3ff5e35d 3953 EH_Loc := No_Location;
4961db87 3954 end if;
3955
3ff5e35d 3956 Bod_Id :=
ee6ba406 3957 Make_Defining_Identifier (Loc,
3958 Chars => Chars (Protected_Body_Subprogram (Ent)));
3ff5e35d 3959 Bod_Spec := Build_Protected_Entry_Specification (Loc, Bod_Id, Empty);
ee6ba406 3960
57993a53 3961 -- Add the following declarations:
46e32b5e 3962
57993a53 3963 -- type poVP is access poV;
3964 -- _object : poVP := poVP (_O);
46e32b5e 3965
57993a53 3966 -- where _O is the formal parameter associated with the concurrent
3967 -- object. These declarations are needed for Complete_Entry_Body.
ee6ba406 3968
3ff5e35d 3969 Add_Object_Pointer (Loc, Pid, Bod_Decls);
ee6ba406 3970
57993a53 3971 -- Add renamings for all formals, the Protection object, discriminals,
2c145f84 3972 -- privals and the entry index constant for use by debugger.
76a1c25b 3973
3ff5e35d 3974 Add_Formal_Renamings (Bod_Spec, Bod_Decls, Ent, Loc);
57993a53 3975 Debug_Private_Data_Declarations (Decls);
76a1c25b 3976
46e32b5e 3977 -- Put the declarations and the statements from the entry
3978
3ff5e35d 3979 Bod_Stmts :=
46e32b5e 3980 New_List (
3981 Make_Block_Statement (Loc,
3ff5e35d 3982 Declarations => Decls,
3983 Handled_Statement_Sequence => Handled_Statement_Sequence (N)));
46e32b5e 3984
70966f50 3985 case Corresponding_Runtime_Package (Pid) is
3986 when System_Tasking_Protected_Objects_Entries =>
3ff5e35d 3987 Append_To (Bod_Stmts,
46e32b5e 3988 Make_Procedure_Call_Statement (End_Loc,
3989 Name =>
83c6c069 3990 New_Occurrence_Of (RTE (RE_Complete_Entry_Body), Loc),
46e32b5e 3991 Parameter_Associations => New_List (
3992 Make_Attribute_Reference (End_Loc,
3993 Prefix =>
3994 Make_Selected_Component (End_Loc,
3995 Prefix =>
3996 Make_Identifier (End_Loc, Name_uObject),
3997 Selector_Name =>
3998 Make_Identifier (End_Loc, Name_uObject)),
3999 Attribute_Name => Name_Unchecked_Access))));
70966f50 4000
4001 when System_Tasking_Protected_Objects_Single_Entry =>
46e32b5e 4002
4003 -- Historically, a call to Complete_Single_Entry_Body was
4004 -- inserted, but it was a null procedure.
4005
4006 null;
70966f50 4007
4008 when others =>
4009 raise Program_Error;
4010 end case;
ee6ba406 4011
4961db87 4012 -- When exceptions can not be propagated, we never need to call
3ff5e35d 4013 -- Exception_Complete_Entry_Body.
ee6ba406 4014
4961db87 4015 if No_Exception_Handlers_Set then
ee6ba406 4016 return
4017 Make_Subprogram_Body (Loc,
3ff5e35d 4018 Specification => Bod_Spec,
4019 Declarations => Bod_Decls,
ee6ba406 4020 Handled_Statement_Sequence =>
4961db87 4021 Make_Handled_Sequence_Of_Statements (Loc,
3ff5e35d 4022 Statements => Bod_Stmts,
57993a53 4023 End_Label => End_Lab));
ee6ba406 4024
4025 else
4026 Ohandle := Make_Others_Choice (Loc);
4027 Set_All_Others (Ohandle);
4028
70966f50 4029 case Corresponding_Runtime_Package (Pid) is
4030 when System_Tasking_Protected_Objects_Entries =>
4031 Complete :=
83c6c069 4032 New_Occurrence_Of
70966f50 4033 (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
ee6ba406 4034
70966f50 4035 when System_Tasking_Protected_Objects_Single_Entry =>
4036 Complete :=
83c6c069 4037 New_Occurrence_Of
70966f50 4038 (RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
4039
4040 when others =>
4041 raise Program_Error;
4042 end case;
ee6ba406 4043
d8e08976 4044 -- Establish link between subprogram body entity and source entry
40134aa2 4045
3ff5e35d 4046 Set_Corresponding_Protected_Entry (Bod_Id, Ent);
40134aa2 4047
76a1c25b 4048 -- Create body of entry procedure. The renaming declarations are
4049 -- placed ahead of the block that contains the actual entry body.
4050
ee6ba406 4051 return
4052 Make_Subprogram_Body (Loc,
3ff5e35d 4053 Specification => Bod_Spec,
4054 Declarations => Bod_Decls,
ee6ba406 4055 Handled_Statement_Sequence =>
4056 Make_Handled_Sequence_Of_Statements (Loc,
3ff5e35d 4057 Statements => Bod_Stmts,
4058 End_Label => End_Lab,
ee6ba406 4059 Exception_Handlers => New_List (
3ff5e35d 4060 Make_Implicit_Exception_Handler (EH_Loc,
ee6ba406 4061 Exception_Choices => New_List (Ohandle),
4062
3ff5e35d 4063 Statements => New_List (
4064 Make_Procedure_Call_Statement (EH_Loc,
4065 Name => Complete,
ee6ba406 4066 Parameter_Associations => New_List (
3ff5e35d 4067 Make_Attribute_Reference (EH_Loc,
4068 Prefix =>
4069 Make_Selected_Component (EH_Loc,
55868293 4070 Prefix =>
3ff5e35d 4071 Make_Identifier (EH_Loc, Name_uObject),
ee6ba406 4072 Selector_Name =>
3ff5e35d 4073 Make_Identifier (EH_Loc, Name_uObject)),
4074 Attribute_Name => Name_Unchecked_Access),
ee6ba406 4075
3ff5e35d 4076 Make_Function_Call (EH_Loc,
4077 Name =>
4078 New_Occurrence_Of
4079 (RTE (RE_Get_GNAT_Exception), Loc)))))))));
ee6ba406 4080 end if;
4081 end Build_Protected_Entry;
4082
4083 -----------------------------------------
4084 -- Build_Protected_Entry_Specification --
4085 -----------------------------------------
4086
4087 function Build_Protected_Entry_Specification
57993a53 4088 (Loc : Source_Ptr;
4089 Def_Id : Entity_Id;
4090 Ent_Id : Entity_Id) return Node_Id
ee6ba406 4091 is
57993a53 4092 P : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uP);
ee6ba406 4093
4094 begin
70966f50 4095 Set_Debug_Info_Needed (Def_Id);
ee6ba406 4096
4097 if Present (Ent_Id) then
4098 Append_Elmt (P, Accept_Address (Ent_Id));
4099 end if;
4100
57993a53 4101 return
4102 Make_Procedure_Specification (Loc,
4103 Defining_Unit_Name => Def_Id,
4104 Parameter_Specifications => New_List (
4105 Make_Parameter_Specification (Loc,
4106 Defining_Identifier =>
4107 Make_Defining_Identifier (Loc, Name_uO),
4108 Parameter_Type =>
83c6c069 4109 New_Occurrence_Of (RTE (RE_Address), Loc)),
ee6ba406 4110
57993a53 4111 Make_Parameter_Specification (Loc,
4112 Defining_Identifier => P,
4113 Parameter_Type =>
83c6c069 4114 New_Occurrence_Of (RTE (RE_Address), Loc)),
ee6ba406 4115
57993a53 4116 Make_Parameter_Specification (Loc,
4117 Defining_Identifier =>
4118 Make_Defining_Identifier (Loc, Name_uE),
4119 Parameter_Type =>
83c6c069 4120 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))));
ee6ba406 4121 end Build_Protected_Entry_Specification;
4122
4123 --------------------------
4124 -- Build_Protected_Spec --
4125 --------------------------
4126
4127 function Build_Protected_Spec
4128 (N : Node_Id;
4129 Obj_Type : Entity_Id;
57993a53 4130 Ident : Entity_Id;
4131 Unprotected : Boolean := False) return List_Id
ee6ba406 4132 is
57993a53 4133 Loc : constant Source_Ptr := Sloc (N);
4134 Decl : Node_Id;
4135 Formal : Entity_Id;
4136 New_Plist : List_Id;
4137 New_Param : Node_Id;
ee6ba406 4138
4139 begin
4140 New_Plist := New_List;
57993a53 4141
ee6ba406 4142 Formal := First_Formal (Ident);
ee6ba406 4143 while Present (Formal) loop
4144 New_Param :=
4145 Make_Parameter_Specification (Loc,
4146 Defining_Identifier =>
4147 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
e43fc5c5 4148 Aliased_Present => Aliased_Present (Parent (Formal)),
4149 In_Present => In_Present (Parent (Formal)),
4150 Out_Present => Out_Present (Parent (Formal)),
83c6c069 4151 Parameter_Type => New_Occurrence_Of (Etype (Formal), Loc));
ee6ba406 4152
4153 if Unprotected then
4154 Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
4155 end if;
4156
4157 Append (New_Param, New_Plist);
4158 Next_Formal (Formal);
4159 end loop;
4160
4161 -- If the subprogram is a procedure and the context is not an access
4162 -- to protected subprogram, the parameter is in-out. Otherwise it is
4163 -- an in parameter.
4164
76a1c25b 4165 Decl :=
ee6ba406 4166 Make_Parameter_Specification (Loc,
4167 Defining_Identifier =>
4168 Make_Defining_Identifier (Loc, Name_uObject),
4169 In_Present => True,
4170 Out_Present =>
57993a53 4171 (Etype (Ident) = Standard_Void_Type
c0688d2b 4172 and then not Is_RTE (Obj_Type, RE_Address)),
57993a53 4173 Parameter_Type =>
83c6c069 4174 New_Occurrence_Of (Obj_Type, Loc));
70966f50 4175 Set_Debug_Info_Needed (Defining_Identifier (Decl));
76a1c25b 4176 Prepend_To (New_Plist, Decl);
ee6ba406 4177
4178 return New_Plist;
4179 end Build_Protected_Spec;
4180
4181 ---------------------------------------
4182 -- Build_Protected_Sub_Specification --
4183 ---------------------------------------
4184
4185 function Build_Protected_Sub_Specification
57993a53 4186 (N : Node_Id;
4187 Prot_Typ : Entity_Id;
4188 Mode : Subprogram_Protection_Mode) return Node_Id
ee6ba406 4189 is
d62940bf 4190 Loc : constant Source_Ptr := Sloc (N);
4191 Decl : Node_Id;
57993a53 4192 Def_Id : Entity_Id;
d62940bf 4193 New_Id : Entity_Id;
4194 New_Plist : List_Id;
4195 New_Spec : Node_Id;
4196
4197 Append_Chr : constant array (Subprogram_Protection_Mode) of Character :=
4198 (Dispatching_Mode => ' ',
4199 Protected_Mode => 'P',
4200 Unprotected_Mode => 'N');
ee6ba406 4201
4202 begin
57993a53 4203 if Ekind (Defining_Unit_Name (Specification (N))) =
4204 E_Subprogram_Body
ee6ba406 4205 then
4206 Decl := Unit_Declaration_Node (Corresponding_Spec (N));
4207 else
4208 Decl := N;
4209 end if;
4210
57993a53 4211 Def_Id := Defining_Unit_Name (Specification (Decl));
ee6ba406 4212
d62940bf 4213 New_Plist :=
57993a53 4214 Build_Protected_Spec
4215 (Decl, Corresponding_Record_Type (Prot_Typ), Def_Id,
4216 Mode = Unprotected_Mode);
fa7497e8 4217 New_Id :=
4218 Make_Defining_Identifier (Loc,
57993a53 4219 Chars => Build_Selected_Name (Prot_Typ, Def_Id, Append_Chr (Mode)));
fa7497e8 4220
4221 -- The unprotected operation carries the user code, and debugging
4222 -- information must be generated for it, even though this spec does
4223 -- not come from source. It is also convenient to allow gdb to step
4224 -- into the protected operation, even though it only contains lock/
4225 -- unlock calls.
4226
70966f50 4227 Set_Debug_Info_Needed (New_Id);
fa7497e8 4228
d3f21ab5 4229 -- If a pragma Eliminate applies to the source entity, the internal
4230 -- subprograms will be eliminated as well.
4231
4232 Set_Is_Eliminated (New_Id, Is_Eliminated (Def_Id));
4233
ee6ba406 4234 if Nkind (Specification (Decl)) = N_Procedure_Specification then
57993a53 4235 New_Spec :=
ee6ba406 4236 Make_Procedure_Specification (Loc,
fa7497e8 4237 Defining_Unit_Name => New_Id,
ee6ba406 4238 Parameter_Specifications => New_Plist);
4239
57993a53 4240 -- Create a new specification for the anonymous subprogram type
4961db87 4241
57993a53 4242 else
ee6ba406 4243 New_Spec :=
4244 Make_Function_Specification (Loc,
fa7497e8 4245 Defining_Unit_Name => New_Id,
ee6ba406 4246 Parameter_Specifications => New_Plist,
d62940bf 4247 Result_Definition =>
4961db87 4248 Copy_Result_Type (Result_Definition (Specification (Decl))));
4249
ee6ba406 4250 Set_Return_Present (Defining_Unit_Name (New_Spec));
ee6ba406 4251 end if;
57993a53 4252
4253 return New_Spec;
ee6ba406 4254 end Build_Protected_Sub_Specification;
4255
4256 -------------------------------------
4257 -- Build_Protected_Subprogram_Body --
4258 -------------------------------------
4259
4260 function Build_Protected_Subprogram_Body
4261 (N : Node_Id;
4262 Pid : Node_Id;
bdd64cbe 4263 N_Op_Spec : Node_Id) return Node_Id
ee6ba406 4264 is
4265 Loc : constant Source_Ptr := Sloc (N);
4266 Op_Spec : Node_Id;
ee6ba406 4267 P_Op_Spec : Node_Id;
4268 Uactuals : List_Id;
4269 Pformal : Node_Id;
4270 Unprot_Call : Node_Id;
4271 Sub_Body : Node_Id;
4272 Lock_Name : Node_Id;
4273 Lock_Stmt : Node_Id;
ee6ba406 4274 R : Node_Id;
bdd64cbe 4275 Return_Stmt : Node_Id := Empty; -- init to avoid gcc 3 warning
4276 Pre_Stmts : List_Id := No_List; -- init to avoid gcc 3 warning
ee6ba406 4277 Stmts : List_Id;
4278 Object_Parm : Node_Id;
4279 Exc_Safe : Boolean;
d2500eb5 4280 Lock_Kind : RE_Id;
ee6ba406 4281
ee6ba406 4282 begin
4283 Op_Spec := Specification (N);
ee6ba406 4284 Exc_Safe := Is_Exception_Safe (N);
4285
ee6ba406 4286 P_Op_Spec :=
d62940bf 4287 Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
ee6ba406 4288
76a1c25b 4289 -- Build a list of the formal parameters of the protected version of
4290 -- the subprogram to use as the actual parameters of the unprotected
4291 -- version.
ee6ba406 4292
4293 Uactuals := New_List;
4294 Pformal := First (Parameter_Specifications (P_Op_Spec));
ee6ba406 4295 while Present (Pformal) loop
55868293 4296 Append_To (Uactuals,
4297 Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))));
ee6ba406 4298 Next (Pformal);
4299 end loop;
4300
76a1c25b 4301 -- Make a call to the unprotected version of the subprogram built above
4302 -- for use by the protected version built below.
ee6ba406 4303
4304 if Nkind (Op_Spec) = N_Function_Specification then
4305 if Exc_Safe then
ec97ce79 4306 R := Make_Temporary (Loc, 'R');
ee6ba406 4307 Unprot_Call :=
4308 Make_Object_Declaration (Loc,
4309 Defining_Identifier => R,
4310 Constant_Present => True,
d62940bf 4311 Object_Definition => New_Copy (Result_Definition (N_Op_Spec)),
ee6ba406 4312 Expression =>
4313 Make_Function_Call (Loc,
4314 Name => Make_Identifier (Loc,
55868293 4315 Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
ee6ba406 4316 Parameter_Associations => Uactuals));
ec97ce79 4317
4318 Return_Stmt :=
4319 Make_Simple_Return_Statement (Loc,
83c6c069 4320 Expression => New_Occurrence_Of (R, Loc));
ee6ba406 4321
4322 else
0d85cfbf 4323 Unprot_Call := Make_Simple_Return_Statement (Loc,
ee6ba406 4324 Expression => Make_Function_Call (Loc,
4325 Name =>
4326 Make_Identifier (Loc,
55868293 4327 Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
ee6ba406 4328 Parameter_Associations => Uactuals));
4329 end if;
4330
d2500eb5 4331 Lock_Kind := RE_Lock_Read_Only;
4332
ee6ba406 4333 else
57993a53 4334 Unprot_Call :=
4335 Make_Procedure_Call_Statement (Loc,
4336 Name =>
55868293 4337 Make_Identifier (Loc, Chars (Defining_Unit_Name (N_Op_Spec))),
57993a53 4338 Parameter_Associations => Uactuals);
d2500eb5 4339
4340 Lock_Kind := RE_Lock;
ee6ba406 4341 end if;
4342
2866d595 4343 -- Wrap call in block that will be covered by an at_end handler
ee6ba406 4344
4345 if not Exc_Safe then
4346 Unprot_Call := Make_Block_Statement (Loc,
4347 Handled_Statement_Sequence =>
4348 Make_Handled_Sequence_Of_Statements (Loc,
4349 Statements => New_List (Unprot_Call)));
4350 end if;
4351
4352 -- Make the protected subprogram body. This locks the protected
4353 -- object and calls the unprotected version of the subprogram.
4354
70966f50 4355 case Corresponding_Runtime_Package (Pid) is
4356 when System_Tasking_Protected_Objects_Entries =>
83c6c069 4357 Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entries), Loc);
ee6ba406 4358
70966f50 4359 when System_Tasking_Protected_Objects_Single_Entry =>
83c6c069 4360 Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entry), Loc);
ee6ba406 4361
70966f50 4362 when System_Tasking_Protected_Objects =>
83c6c069 4363 Lock_Name := New_Occurrence_Of (RTE (Lock_Kind), Loc);
70966f50 4364
4365 when others =>
4366 raise Program_Error;
4367 end case;
ee6ba406 4368
4369 Object_Parm :=
4370 Make_Attribute_Reference (Loc,
4371 Prefix =>
4372 Make_Selected_Component (Loc,
55868293 4373 Prefix => Make_Identifier (Loc, Name_uObject),
4374 Selector_Name => Make_Identifier (Loc, Name_uObject)),
ee6ba406 4375 Attribute_Name => Name_Unchecked_Access);
4376
4377 Lock_Stmt := Make_Procedure_Call_Statement (Loc,
4378 Name => Lock_Name,
4379 Parameter_Associations => New_List (Object_Parm));
4380
4381 if Abort_Allowed then
4382 Stmts := New_List (
4383 Make_Procedure_Call_Statement (Loc,
83c6c069 4384 Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
ee6ba406 4385 Parameter_Associations => Empty_List),
4386 Lock_Stmt);
4387
4388 else
4389 Stmts := New_List (Lock_Stmt);
4390 end if;
4391
4392 if not Exc_Safe then
4393 Append (Unprot_Call, Stmts);
4394 else
4395 if Nkind (Op_Spec) = N_Function_Specification then
4396 Pre_Stmts := Stmts;
4397 Stmts := Empty_List;
4398 else
4399 Append (Unprot_Call, Stmts);
4400 end if;
4401
c96806b2 4402 -- Historical note: Previously, call to the cleanup was inserted
8f3b5017 4403 -- here. This is now done by Build_Protected_Subprogram_Call_Cleanup,
4404 -- which is also shared by the 'not Exc_Safe' path.
4405
3c9851e9 4406 Build_Protected_Subprogram_Call_Cleanup (Op_Spec, Pid, Loc, Stmts);
ee6ba406 4407
4408 if Nkind (Op_Spec) = N_Function_Specification then
4409 Append (Return_Stmt, Stmts);
4410 Append (Make_Block_Statement (Loc,
4411 Declarations => New_List (Unprot_Call),
4412 Handled_Statement_Sequence =>
4413 Make_Handled_Sequence_Of_Statements (Loc,
4414 Statements => Stmts)), Pre_Stmts);
4415 Stmts := Pre_Stmts;
4416 end if;
4417 end if;
4418
4419 Sub_Body :=
4420 Make_Subprogram_Body (Loc,
4421 Declarations => Empty_List,
4422 Specification => P_Op_Spec,
4423 Handled_Statement_Sequence =>
4424 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
4425
8f3b5017 4426 -- Mark this subprogram as a protected subprogram body so that the
4427 -- cleanup will be inserted. This is done only in the 'not Exc_Safe'
4428 -- path as otherwise the cleanup has already been inserted.
4429
ee6ba406 4430 if not Exc_Safe then
4431 Set_Is_Protected_Subprogram_Body (Sub_Body);
4432 end if;
4433
4434 return Sub_Body;
4435 end Build_Protected_Subprogram_Body;
4436
4437 -------------------------------------
4438 -- Build_Protected_Subprogram_Call --
4439 -------------------------------------
4440
4441 procedure Build_Protected_Subprogram_Call
4442 (N : Node_Id;
4443 Name : Node_Id;
4444 Rec : Node_Id;
4445 External : Boolean := True)
4446 is
4447 Loc : constant Source_Ptr := Sloc (N);
9dfe12ae 4448 Sub : constant Entity_Id := Entity (Name);
ee6ba406 4449 New_Sub : Node_Id;
4450 Params : List_Id;
4451
4452 begin
4453 if External then
4454 New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
4455 else
4456 New_Sub :=
4457 New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
4458 end if;
4459
4460 if Present (Parameter_Associations (N)) then
4461 Params := New_Copy_List_Tree (Parameter_Associations (N));
4462 else
4463 Params := New_List;
4464 end if;
4465
82ae9906 4466 -- If the type is an untagged derived type, convert to the root type,
4467 -- which is the one on which the operations are defined.
4468
4469 if Nkind (Rec) = N_Unchecked_Type_Conversion
4470 and then not Is_Tagged_Type (Etype (Rec))
4471 and then Is_Derived_Type (Etype (Rec))
4472 then
4473 Set_Etype (Rec, Root_Type (Etype (Rec)));
4474 Set_Subtype_Mark (Rec,
4475 New_Occurrence_Of (Root_Type (Etype (Rec)), Sloc (N)));
4476 end if;
4477
ee6ba406 4478 Prepend (Rec, Params);
4479
4480 if Ekind (Sub) = E_Procedure then
4481 Rewrite (N,
4482 Make_Procedure_Call_Statement (Loc,
4483 Name => New_Sub,
4484 Parameter_Associations => Params));
4485
4486 else
4487 pragma Assert (Ekind (Sub) = E_Function);
4488 Rewrite (N,
4489 Make_Function_Call (Loc,
0fa54be6 4490 Name => New_Sub,
ee6ba406 4491 Parameter_Associations => Params));
199ab4c3 4492
4493 -- Preserve type of call for subsequent processing (required for
4494 -- call to Wrap_Transient_Expression in the case of a shared passive
4495 -- protected).
4496
4497 Set_Etype (N, Etype (New_Sub));
ee6ba406 4498 end if;
4499
4500 if External
4501 and then Nkind (Rec) = N_Unchecked_Type_Conversion
4502 and then Is_Entity_Name (Expression (Rec))
4503 and then Is_Shared_Passive (Entity (Expression (Rec)))
4504 then
4505 Add_Shared_Var_Lock_Procs (N);
4506 end if;
ee6ba406 4507 end Build_Protected_Subprogram_Call;
4508
3c9851e9 4509 ---------------------------------------------
4510 -- Build_Protected_Subprogram_Call_Cleanup --
4511 ---------------------------------------------
4512
4513 procedure Build_Protected_Subprogram_Call_Cleanup
4514 (Op_Spec : Node_Id;
4515 Conc_Typ : Node_Id;
4516 Loc : Source_Ptr;
4517 Stmts : List_Id)
4518 is
4519 Nam : Node_Id;
4520
4521 begin
4522 -- If the associated protected object has entries, a protected
4523 -- procedure has to service entry queues. In this case generate:
4524
4525 -- Service_Entries (_object._object'Access);
4526
4527 if Nkind (Op_Spec) = N_Procedure_Specification
4528 and then Has_Entries (Conc_Typ)
4529 then
4530 case Corresponding_Runtime_Package (Conc_Typ) is
4531 when System_Tasking_Protected_Objects_Entries =>
83c6c069 4532 Nam := New_Occurrence_Of (RTE (RE_Service_Entries), Loc);
3c9851e9 4533
4534 when System_Tasking_Protected_Objects_Single_Entry =>
83c6c069 4535 Nam := New_Occurrence_Of (RTE (RE_Service_Entry), Loc);
3c9851e9 4536
4537 when others =>
4538 raise Program_Error;
4539 end case;
4540
4541 Append_To (Stmts,
4542 Make_Procedure_Call_Statement (Loc,
4543 Name => Nam,
4544 Parameter_Associations => New_List (
4545 Make_Attribute_Reference (Loc,
4546 Prefix =>
4547 Make_Selected_Component (Loc,
4548 Prefix => Make_Identifier (Loc, Name_uObject),
4549 Selector_Name => Make_Identifier (Loc, Name_uObject)),
4550 Attribute_Name => Name_Unchecked_Access))));
4551
4552 else
4553 -- Generate:
4554 -- Unlock (_object._object'Access);
4555
4556 case Corresponding_Runtime_Package (Conc_Typ) is
4557 when System_Tasking_Protected_Objects_Entries =>
83c6c069 4558 Nam := New_Occurrence_Of (RTE (RE_Unlock_Entries), Loc);
3c9851e9 4559
4560 when System_Tasking_Protected_Objects_Single_Entry =>
83c6c069 4561 Nam := New_Occurrence_Of (RTE (RE_Unlock_Entry), Loc);
3c9851e9 4562
4563 when System_Tasking_Protected_Objects =>
83c6c069 4564 Nam := New_Occurrence_Of (RTE (RE_Unlock), Loc);
3c9851e9 4565
4566 when others =>
4567 raise Program_Error;
4568 end case;
4569
4570 Append_To (Stmts,
4571 Make_Procedure_Call_Statement (Loc,
4572 Name => Nam,
4573 Parameter_Associations => New_List (
4574 Make_Attribute_Reference (Loc,
4575 Prefix =>
4576 Make_Selected_Component (Loc,
4577 Prefix => Make_Identifier (Loc, Name_uObject),
4578 Selector_Name => Make_Identifier (Loc, Name_uObject)),
4579 Attribute_Name => Name_Unchecked_Access))));
4580 end if;
4581
4582 -- Generate:
4583 -- Abort_Undefer;
4584
4585 if Abort_Allowed then
4586 Append_To (Stmts,
4587 Make_Procedure_Call_Statement (Loc,
4588 Name =>
83c6c069 4589 New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
3c9851e9 4590 Parameter_Associations => Empty_List));
4591 end if;
4592 end Build_Protected_Subprogram_Call_Cleanup;
4593
ee6ba406 4594 -------------------------
4595 -- Build_Selected_Name --
4596 -------------------------
4597
4598 function Build_Selected_Name
76a1c25b 4599 (Prefix : Entity_Id;
4600 Selector : Entity_Id;
4601 Append_Char : Character := ' ') return Name_Id
ee6ba406 4602 is
4603 Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
4604 Select_Len : Natural;
4605
4606 begin
76a1c25b 4607 Get_Name_String (Chars (Selector));
ee6ba406 4608 Select_Len := Name_Len;
4609 Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
76a1c25b 4610 Get_Name_String (Chars (Prefix));
ee6ba406 4611
4612 -- If scope is anonymous type, discard suffix to recover name of
4613 -- single protected object. Otherwise use protected type name.
4614
4615 if Name_Buffer (Name_Len) = 'T' then
4616 Name_Len := Name_Len - 1;
4617 end if;
4618
0c4c5759 4619 Add_Str_To_Name_Buffer ("__");
ee6ba406 4620 for J in 1 .. Select_Len loop
0c4c5759 4621 Add_Char_To_Name_Buffer (Select_Buffer (J));
ee6ba406 4622 end loop;
4623
76a1c25b 4624 -- Now add the Append_Char if specified. The encoding to follow
4625 -- depends on the type of entity. If Append_Char is either 'N' or 'P',
4626 -- then the entity is associated to a protected type subprogram.
4627 -- Otherwise, it is a protected type entry. For each case, the
4628 -- encoding to follow for the suffix is documented in exp_dbug.ads.
4629
4630 -- It would be better to encapsulate this as a routine in Exp_Dbug ???
4631
ee6ba406 4632 if Append_Char /= ' ' then
76a1c25b 4633 if Append_Char = 'P' or Append_Char = 'N' then
0c4c5759 4634 Add_Char_To_Name_Buffer (Append_Char);
76a1c25b 4635 return Name_Find;
4636 else
0c4c5759 4637 Add_Str_To_Name_Buffer ((1 => '_', 2 => Append_Char));
76a1c25b 4638 return New_External_Name (Name_Find, ' ', -1);
4639 end if;
4640 else
4641 return Name_Find;
ee6ba406 4642 end if;
ee6ba406 4643 end Build_Selected_Name;
4644
4645 -----------------------------
4646 -- Build_Simple_Entry_Call --
4647 -----------------------------
4648
4649 -- A task entry call is converted to a call to Call_Simple
4650
4651 -- declare
4652 -- P : parms := (parm, parm, parm);
4653 -- begin
4654 -- Call_Simple (acceptor-task, entry-index, P'Address);
4655 -- parm := P.param;
4656 -- parm := P.param;
4657 -- ...
4658 -- end;
4659
4660 -- Here Pnn is an aggregate of the type constructed for the entry to hold
4661 -- the parameters, and the constructed aggregate value contains either the
4662 -- parameters or, in the case of non-elementary types, references to these
4663 -- parameters. Then the address of this aggregate is passed to the runtime
4664 -- routine, along with the task id value and the task entry index value.
4665 -- Pnn is only required if parameters are present.
4666
4667 -- The assignments after the call are present only in the case of in-out
4668 -- or out parameters for elementary types, and are used to assign back the
4669 -- resulting values of such parameters.
4670
4671 -- Note: the reason that we insert a block here is that in the context
4672 -- of selects, conditional entry calls etc. the entry call statement
4673 -- appears on its own, not as an element of a list.
4674
4675 -- A protected entry call is converted to a Protected_Entry_Call:
4676
4677 -- declare
4678 -- P : E1_Params := (param, param, param);
4679 -- Pnn : Boolean;
4680 -- Bnn : Communications_Block;
4681
4682 -- declare
4683 -- P : E1_Params := (param, param, param);
4684 -- Bnn : Communications_Block;
4685
4686 -- begin
4687 -- Protected_Entry_Call (
4688 -- Object => po._object'Access,
4689 -- E => <entry index>;
4690 -- Uninterpreted_Data => P'Address;
4691 -- Mode => Simple_Call;
4692 -- Block => Bnn);
4693 -- parm := P.param;
4694 -- parm := P.param;
4695 -- ...
4696 -- end;
4697
4698 procedure Build_Simple_Entry_Call
4699 (N : Node_Id;
4700 Concval : Node_Id;
4701 Ename : Node_Id;
4702 Index : Node_Id)
4703 is
4704 begin
4705 Expand_Call (N);
4706
9f76f439 4707 -- If call has been inlined, nothing left to do
4708
4709 if Nkind (N) = N_Block_Statement then
4710 return;
4711 end if;
4712
ee6ba406 4713 -- Convert entry call to Call_Simple call
4714
4715 declare
4716 Loc : constant Source_Ptr := Sloc (N);
4717 Parms : constant List_Id := Parameter_Associations (N);
9dfe12ae 4718 Stats : constant List_Id := New_List;
76a1c25b 4719 Actual : Node_Id;
4720 Call : Node_Id;
4721 Comm_Name : Entity_Id;
ee6ba406 4722 Conctyp : Node_Id;
76a1c25b 4723 Decls : List_Id;
ee6ba406 4724 Ent : Entity_Id;
4725 Ent_Acc : Entity_Id;
76a1c25b 4726 Formal : Node_Id;
4727 Iface_Tag : Entity_Id;
4728 Iface_Typ : Entity_Id;
4729 N_Node : Node_Id;
4730 N_Var : Node_Id;
ee6ba406 4731 P : Entity_Id;
ee6ba406 4732 Parm1 : Node_Id;
4733 Parm2 : Node_Id;
4734 Parm3 : Node_Id;
76a1c25b 4735 Pdecl : Node_Id;
4736 Plist : List_Id;
4737 X : Entity_Id;
4738 Xdecl : Node_Id;
ee6ba406 4739
4740 begin
4741 -- Simple entry and entry family cases merge here
4742
4743 Ent := Entity (Ename);
4744 Ent_Acc := Entry_Parameters_Type (Ent);
4745 Conctyp := Etype (Concval);
4746
4747 -- If prefix is an access type, dereference to obtain the task type
4748
4749 if Is_Access_Type (Conctyp) then
4750 Conctyp := Designated_Type (Conctyp);
4751 end if;
4752
2866d595 4753 -- Special case for protected subprogram calls
ee6ba406 4754
4755 if Is_Protected_Type (Conctyp)
4756 and then Is_Subprogram (Entity (Ename))
4757 then
632a8995 4758 if not Is_Eliminated (Entity (Ename)) then
4759 Build_Protected_Subprogram_Call
4760 (N, Ename, Convert_Concurrent (Concval, Conctyp));
4761 Analyze (N);
4762 end if;
4763
ee6ba406 4764 return;
4765 end if;
4766
4767 -- First parameter is the Task_Id value from the task value or the
4768 -- Object from the protected object value, obtained by selecting
4769 -- the _Task_Id or _Object from the result of doing an unchecked
4770 -- conversion to convert the value to the corresponding record type.
4771
57993a53 4772 if Nkind (Concval) = N_Function_Call
4773 and then Is_Task_Type (Conctyp)
de54c5ab 4774 and then Ada_Version >= Ada_2005
57993a53 4775 then
4776 declare
ec97ce79 4777 ExpR : constant Node_Id := Relocate_Node (Concval);
4778 Obj : constant Entity_Id := Make_Temporary (Loc, 'F', ExpR);
57993a53 4779 Decl : Node_Id;
4780
4781 begin
4782 Decl :=
4783 Make_Object_Declaration (Loc,
4784 Defining_Identifier => Obj,
4785 Object_Definition => New_Occurrence_Of (Conctyp, Loc),
ec97ce79 4786 Expression => ExpR);
57993a53 4787 Set_Etype (Obj, Conctyp);
4788 Decls := New_List (Decl);
4789 Rewrite (Concval, New_Occurrence_Of (Obj, Loc));
4790 end;
4791
4792 else
4793 Decls := New_List;
4794 end if;
4795
ee6ba406 4796 Parm1 := Concurrent_Ref (Concval);
4797
4798 -- Second parameter is the entry index, computed by the routine
4799 -- provided for this purpose. The value of this expression is
4800 -- assigned to an intermediate variable to assure that any entry
4801 -- family index expressions are evaluated before the entry
4802 -- parameters.
4803
615d1802 4804 if not Is_Protected_Type (Conctyp)
4805 or else
4806 Corresponding_Runtime_Package (Conctyp) =
4807 System_Tasking_Protected_Objects_Entries
ee6ba406 4808 then
4809 X := Make_Defining_Identifier (Loc, Name_uX);
4810
4811 Xdecl :=
4812 Make_Object_Declaration (Loc,
4813 Defining_Identifier => X,
4814 Object_Definition =>
83c6c069 4815 New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc),
ee6ba406 4816 Expression => Actual_Index_Expression (
4817 Loc, Entity (Ename), Index, Concval));
4818
57993a53 4819 Append_To (Decls, Xdecl);
83c6c069 4820 Parm2 := New_Occurrence_Of (X, Loc);
ee6ba406 4821
4822 else
4823 Xdecl := Empty;
ee6ba406 4824 Parm2 := Empty;
4825 end if;
4826
4827 -- The third parameter is the packaged parameters. If there are
76a1c25b 4828 -- none, then it is just the null address, since nothing is passed.
ee6ba406 4829
4830 if No (Parms) then
83c6c069 4831 Parm3 := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
ee6ba406 4832 P := Empty;
4833
4834 -- Case of parameters present, where third argument is the address
4835 -- of a packaged record containing the required parameter values.
4836
4837 else
76a1c25b 4838 -- First build a list of parameter values, which are references to
4839 -- objects of the parameter types.
ee6ba406 4840
4841 Plist := New_List;
4842
4843 Actual := First_Actual (N);
4844 Formal := First_Formal (Ent);
ee6ba406 4845 while Present (Actual) loop
4846
849fc00e 4847 -- If it is a by-copy type, copy it to a new variable. The
ee6ba406 4848 -- packaged record has a field that points to this variable.
4849
4850 if Is_By_Copy_Type (Etype (Actual)) then
4851 N_Node :=
4852 Make_Object_Declaration (Loc,
ec97ce79 4853 Defining_Identifier => Make_Temporary (Loc, 'J'),
4854 Aliased_Present => True,
4855 Object_Definition =>
83c6c069 4856 New_Occurrence_Of (Etype (Formal), Loc));
ee6ba406 4857
cb5f80c1 4858 -- Mark the object as not needing initialization since the
4859 -- initialization is performed separately, avoiding errors
4860 -- on cases such as formals of null-excluding access types.
4861
4862 Set_No_Initialization (N_Node);
4863
849fc00e 4864 -- We must make a separate assignment statement for the
4865 -- case of limited types. We cannot assign it unless the
5809835d 4866 -- Assignment_OK flag is set first. An out formal of an
849fc00e 4867 -- access type or whose type has a Default_Value must also
4868 -- be initialized from the actual (see RM 6.4.1 (13-13.1)),
4869 -- but no constraint, predicate, or null-exclusion check is
4870 -- applied before the call.
ee6ba406 4871
d1662b94 4872 if Ekind (Formal) /= E_Out_Parameter
4873 or else Is_Access_Type (Etype (Formal))
849fc00e 4874 or else
4875 (Is_Scalar_Type (Etype (Formal))
4876 and then
4877 Present (Default_Aspect_Value (Etype (Formal))))
d1662b94 4878 then
ee6ba406 4879 N_Var :=
83c6c069 4880 New_Occurrence_Of (Defining_Identifier (N_Node), Loc);
ee6ba406 4881 Set_Assignment_OK (N_Var);
4882 Append_To (Stats,
4883 Make_Assignment_Statement (Loc,
849fc00e 4884 Name => N_Var,
ee6ba406 4885 Expression => Relocate_Node (Actual)));
2c70d7c1 4886
849fc00e 4887 -- Mark the object as internal, so we don't later reset
4888 -- No_Initialization flag in Default_Initialize_Object,
4889 -- which would lead to needless default initialization.
4890 -- We don't set this outside the if statement, because
4891 -- out scalar parameters without Default_Value do require
4892 -- default initialization if Initialize_Scalars applies.
4893
4894 Set_Is_Internal (Defining_Identifier (N_Node));
4895
2c70d7c1 4896 -- If actual is an out parameter of a null-excluding
4897 -- access type, there is access check on entry, so set
4898 -- Suppress_Assignment_Checks on the generated statement
4899 -- that assigns the actual to the parameter block
4900
552cedee 4901 Set_Suppress_Assignment_Checks (Last (Stats));
ee6ba406 4902 end if;
4903
4904 Append (N_Node, Decls);
4905
4906 Append_To (Plist,
4907 Make_Attribute_Reference (Loc,
4908 Attribute_Name => Name_Unchecked_Access,
849fc00e 4909 Prefix =>
4910 New_Occurrence_Of
4911 (Defining_Identifier (N_Node), Loc)));
efe19947 4912
ee6ba406 4913 else
76a1c25b 4914 -- Interface class-wide formal
4915
de54c5ab 4916 if Ada_Version >= Ada_2005
76a1c25b 4917 and then Ekind (Etype (Formal)) = E_Class_Wide_Type
4918 and then Is_Interface (Etype (Formal))
4919 then
4920 Iface_Typ := Etype (Etype (Formal));
4921
4922 -- Generate:
4923 -- formal_iface_type! (actual.iface_tag)'reference
4924
4925 Iface_Tag :=
4926 Find_Interface_Tag (Etype (Actual), Iface_Typ);
4927 pragma Assert (Present (Iface_Tag));
4928
4929 Append_To (Plist,
4930 Make_Reference (Loc,
4931 Unchecked_Convert_To (Iface_Typ,
4932 Make_Selected_Component (Loc,
849fc00e 4933 Prefix =>
76a1c25b 4934 Relocate_Node (Actual),
4935 Selector_Name =>
83c6c069 4936 New_Occurrence_Of (Iface_Tag, Loc)))));
76a1c25b 4937 else
4938 -- Generate:
4939 -- actual'reference
4940
4941 Append_To (Plist,
4942 Make_Reference (Loc, Relocate_Node (Actual)));
4943 end if;
ee6ba406 4944 end if;
4945
4946 Next_Actual (Actual);
4947 Next_Formal_With_Extras (Formal);
4948 end loop;
4949
4950 -- Now build the declaration of parameters initialized with the
4951 -- aggregate containing this constructed parameter list.
4952
4953 P := Make_Defining_Identifier (Loc, Name_uP);
4954
4955 Pdecl :=
4956 Make_Object_Declaration (Loc,
4957 Defining_Identifier => P,
10970cab 4958 Object_Definition =>
83c6c069 4959 New_Occurrence_Of (Designated_Type (Ent_Acc), Loc),
10970cab 4960 Expression =>
ee6ba406 4961 Make_Aggregate (Loc, Expressions => Plist));
4962
4963 Parm3 :=
4964 Make_Attribute_Reference (Loc,
849fc00e 4965 Prefix => New_Occurrence_Of (P, Loc),
5809835d 4966 Attribute_Name => Name_Address);
ee6ba406 4967
4968 Append (Pdecl, Decls);
4969 end if;
4970
4971 -- Now we can create the call, case of protected type
4972
4973 if Is_Protected_Type (Conctyp) then
70966f50 4974 case Corresponding_Runtime_Package (Conctyp) is
4975 when System_Tasking_Protected_Objects_Entries =>
ee6ba406 4976
70966f50 4977 -- Change the type of the index declaration
ee6ba406 4978
70966f50 4979 Set_Object_Definition (Xdecl,
83c6c069 4980 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc));
ee6ba406 4981
70966f50 4982 -- Some additional declarations for protected entry calls
ee6ba406 4983
70966f50 4984 if No (Decls) then
4985 Decls := New_List;
4986 end if;
ee6ba406 4987
70966f50 4988 -- Bnn : Communications_Block;
ee6ba406 4989
ec97ce79 4990 Comm_Name := Make_Temporary (Loc, 'B');
ee6ba406 4991
70966f50 4992 Append_To (Decls,
4993 Make_Object_Declaration (Loc,
4994 Defining_Identifier => Comm_Name,
ec97ce79 4995 Object_Definition =>
83c6c069 4996 New_Occurrence_Of
4997 (RTE (RE_Communication_Block), Loc)));
ee6ba406 4998
70966f50 4999 -- Some additional statements for protected entry calls
ee6ba406 5000
70966f50 5001 -- Protected_Entry_Call (
5002 -- Object => po._object'Access,
5003 -- E => <entry index>;
5004 -- Uninterpreted_Data => P'Address;
5005 -- Mode => Simple_Call;
5006 -- Block => Bnn);
ee6ba406 5007
70966f50 5008 Call :=
5009 Make_Procedure_Call_Statement (Loc,
5010 Name =>
83c6c069 5011 New_Occurrence_Of (RTE (RE_Protected_Entry_Call), Loc),
ee6ba406 5012
70966f50 5013 Parameter_Associations => New_List (
5014 Make_Attribute_Reference (Loc,
5015 Attribute_Name => Name_Unchecked_Access,
5016 Prefix => Parm1),
5017 Parm2,
5018 Parm3,
83c6c069 5019 New_Occurrence_Of (RTE (RE_Simple_Call), Loc),
70966f50 5020 New_Occurrence_Of (Comm_Name, Loc)));
5021
5022 when System_Tasking_Protected_Objects_Single_Entry =>
5023 -- Protected_Single_Entry_Call (
5024 -- Object => po._object'Access,
615d1802 5025 -- Uninterpreted_Data => P'Address);
70966f50 5026
5027 Call :=
5028 Make_Procedure_Call_Statement (Loc,
849fc00e 5029 Name =>
5030 New_Occurrence_Of
5031 (RTE (RE_Protected_Single_Entry_Call), Loc),
70966f50 5032
5033 Parameter_Associations => New_List (
5034 Make_Attribute_Reference (Loc,
5035 Attribute_Name => Name_Unchecked_Access,
5036 Prefix => Parm1),
615d1802 5037 Parm3));
ee6ba406 5038
70966f50 5039 when others =>
5040 raise Program_Error;
5041 end case;
ee6ba406 5042
5043 -- Case of task type
5044
5045 else
5046 Call :=
5047 Make_Procedure_Call_Statement (Loc,
849fc00e 5048 Name =>
5049 New_Occurrence_Of (RTE (RE_Call_Simple), Loc),
ee6ba406 5050 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
5051
5052 end if;
5053
5054 Append_To (Stats, Call);
5055
76a1c25b 5056 -- If there are out or in/out parameters by copy add assignment
5057 -- statements for the result values.
ee6ba406 5058
5059 if Present (Parms) then
5060 Actual := First_Actual (N);
5061 Formal := First_Formal (Ent);
5062
5063 Set_Assignment_OK (Actual);
5064 while Present (Actual) loop
36ac5fbb 5065 if Is_By_Copy_Type (Etype (Actual))
ee6ba406 5066 and then Ekind (Formal) /= E_In_Parameter
5067 then
5068 N_Node :=
5069 Make_Assignment_Statement (Loc,
849fc00e 5070 Name => New_Copy (Actual),
ee6ba406 5071 Expression =>
5072 Make_Explicit_Dereference (Loc,
5073 Make_Selected_Component (Loc,
849fc00e 5074 Prefix => New_Occurrence_Of (P, Loc),
ee6ba406 5075 Selector_Name =>
5076 Make_Identifier (Loc, Chars (Formal)))));
5077
76a1c25b 5078 -- In all cases (including limited private types) we want
5079 -- the assignment to be valid.
ee6ba406 5080
5081 Set_Assignment_OK (Name (N_Node));
5082
5083 -- If the call is the triggering alternative in an
76a1c25b 5084 -- asynchronous select, or the entry_call alternative of a
5085 -- conditional entry call, the assignments for in-out
5086 -- parameters are incorporated into the statement list that
5087 -- follows, so that there are executed only if the entry
5088 -- call succeeds.
ee6ba406 5089
5090 if (Nkind (Parent (N)) = N_Triggering_Alternative
5091 and then N = Triggering_Statement (Parent (N)))
5092 or else
5093 (Nkind (Parent (N)) = N_Entry_Call_Alternative
5094 and then N = Entry_Call_Statement (Parent (N)))
5095 then
5096 if No (Statements (Parent (N))) then
5097 Set_Statements (Parent (N), New_List);
5098 end if;
5099
5100 Prepend (N_Node, Statements (Parent (N)));
5101
5102 else
5103 Insert_After (Call, N_Node);
5104 end if;
5105 end if;
5106
5107 Next_Actual (Actual);
5108 Next_Formal_With_Extras (Formal);
5109 end loop;
5110 end if;
5111
5112 -- Finally, create block and analyze it
5113
5114 Rewrite (N,
5115 Make_Block_Statement (Loc,
85377c9b 5116 Declarations => Decls,
ee6ba406 5117 Handled_Statement_Sequence =>
5118 Make_Handled_Sequence_Of_Statements (Loc,
5119 Statements => Stats)));
5120
5121 Analyze (N);
5122 end;
ee6ba406 5123 end Build_Simple_Entry_Call;
5124
5125 --------------------------------
5126 -- Build_Task_Activation_Call --
5127 --------------------------------
5128
5129 procedure Build_Task_Activation_Call (N : Node_Id) is
4961db87 5130 Loc : constant Source_Ptr := Sloc (N);
5131 Chain : Entity_Id;
5132 Call : Node_Id;
5133 Name : Node_Id;
5134 P : Node_Id;
ee6ba406 5135
5136 begin
d4f55b2a 5137 -- For sequential elaboration policy, all the tasks will be activated at
5138 -- the end of the elaboration.
4c1fd062 5139
d4f55b2a 5140 if Partition_Elaboration_Policy = 'S' then
4c1fd062 5141 return;
5142 end if;
5143
ee6ba406 5144 -- Get the activation chain entity. Except in the case of a package
cb5f80c1 5145 -- body, this is in the node that was passed. For a package body, we
ee6ba406 5146 -- have to find the corresponding package declaration node.
5147
5148 if Nkind (N) = N_Package_Body then
5149 P := Corresponding_Spec (N);
ee6ba406 5150 loop
5151 P := Parent (P);
5152 exit when Nkind (P) = N_Package_Declaration;
5153 end loop;
5154
5155 Chain := Activation_Chain_Entity (P);
5156
5157 else
5158 Chain := Activation_Chain_Entity (N);
5159 end if;
5160
5161 if Present (Chain) then
d4f55b2a 5162 if Restricted_Profile then
83c6c069 5163 Name := New_Occurrence_Of
5164 (RTE (RE_Activate_Restricted_Tasks), Loc);
d4f55b2a 5165 else
83c6c069 5166 Name := New_Occurrence_Of
5167 (RTE (RE_Activate_Tasks), Loc);
d4f55b2a 5168 end if;
ee6ba406 5169
5170 Call :=
5171 Make_Procedure_Call_Statement (Loc,
849fc00e 5172 Name => Name,
ee6ba406 5173 Parameter_Associations =>
5174 New_List (Make_Attribute_Reference (Loc,
85377c9b 5175 Prefix => New_Occurrence_Of (Chain, Loc),
ee6ba406 5176 Attribute_Name => Name_Unchecked_Access)));
5177
5178 if Nkind (N) = N_Package_Declaration then
5179 if Present (Corresponding_Body (N)) then
5180 null;
5181
5182 elsif Present (Private_Declarations (Specification (N))) then
5183 Append (Call, Private_Declarations (Specification (N)));
5184
5185 else
5186 Append (Call, Visible_Declarations (Specification (N)));
5187 end if;
5188
5189 else
5190 if Present (Handled_Statement_Sequence (N)) then
5191
10970cab 5192 -- The call goes at the start of the statement sequence after
5193 -- the start of exception range label if one is present.
ee6ba406 5194
5195 declare
5196 Stm : Node_Id;
5197
5198 begin
5199 Stm := First (Statements (Handled_Statement_Sequence (N)));
5200
4961db87 5201 -- A special case, skip exception range label if one is
5202 -- present (from front end zcx processing).
5203
ee6ba406 5204 if Nkind (Stm) = N_Label and then Exception_Junk (Stm) then
5205 Next (Stm);
5206 end if;
5207
4961db87 5208 -- Another special case, if the first statement is a block
5209 -- from optimization of a local raise to a goto, then the
5210 -- call goes inside this block.
5211
5212 if Nkind (Stm) = N_Block_Statement
5213 and then Exception_Junk (Stm)
5214 then
5215 Stm :=
5216 First (Statements (Handled_Statement_Sequence (Stm)));
5217 end if;
5218
5219 -- Insertion point is after any exception label pushes,
5220 -- since we want it covered by any local handlers.
5221
5222 while Nkind (Stm) in N_Push_xxx_Label loop
5223 Next (Stm);
5224 end loop;
5225
5226 -- Now we have the proper insertion point
5227
ee6ba406 5228 Insert_Before (Stm, Call);
5229 end;
5230
5231 else
5232 Set_Handled_Statement_Sequence (N,
5233 Make_Handled_Sequence_Of_Statements (Loc,
10970cab 5234 Statements => New_List (Call)));
ee6ba406 5235 end if;
5236 end if;
5237
5238 Analyze (Call);
5239 Check_Task_Activation (N);
5240 end if;
ee6ba406 5241 end Build_Task_Activation_Call;
5242
5243 -------------------------------
5244 -- Build_Task_Allocate_Block --
5245 -------------------------------
5246
5247 procedure Build_Task_Allocate_Block
5248 (Actions : List_Id;
5249 N : Node_Id;
5250 Args : List_Id)
5251 is
9dfe12ae 5252 T : constant Entity_Id := Entity (Expression (N));
5253 Init : constant Entity_Id := Base_Init_Proc (T);
5254 Loc : constant Source_Ptr := Sloc (N);
5255 Chain : constant Entity_Id :=
5256 Make_Defining_Identifier (Loc, Name_uChain);
ec97ce79 5257 Blkent : constant Entity_Id := Make_Temporary (Loc, 'A');
ee6ba406 5258 Block : Node_Id;
5259
5260 begin
ee6ba406 5261 Block :=
5262 Make_Block_Statement (Loc,
83c6c069 5263 Identifier => New_Occurrence_Of (Blkent, Loc),
ee6ba406 5264 Declarations => New_List (
5265
5266 -- _Chain : Activation_Chain;
5267
5268 Make_Object_Declaration (Loc,
5269 Defining_Identifier => Chain,
43602818 5270 Aliased_Present => True,
ee6ba406 5271 Object_Definition =>
83c6c069 5272 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
ee6ba406 5273
5274 Handled_Statement_Sequence =>
5275 Make_Handled_Sequence_Of_Statements (Loc,
5276
5277 Statements => New_List (
5278
10970cab 5279 -- Init (Args);
ee6ba406 5280
5281 Make_Procedure_Call_Statement (Loc,
83c6c069 5282 Name => New_Occurrence_Of (Init, Loc),
ee6ba406 5283 Parameter_Associations => Args),
5284
10970cab 5285 -- Activate_Tasks (_Chain);
ee6ba406 5286
5287 Make_Procedure_Call_Statement (Loc,
83c6c069 5288 Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
ee6ba406 5289 Parameter_Associations => New_List (
5290 Make_Attribute_Reference (Loc,
83c6c069 5291 Prefix => New_Occurrence_Of (Chain, Loc),
ee6ba406 5292 Attribute_Name => Name_Unchecked_Access))))),
5293
5294 Has_Created_Identifier => True,
5295 Is_Task_Allocation_Block => True);
5296
5297 Append_To (Actions,
5298 Make_Implicit_Label_Declaration (Loc,
5299 Defining_Identifier => Blkent,
5300 Label_Construct => Block));
5301
5302 Append_To (Actions, Block);
5303
5304 Set_Activation_Chain_Entity (Block, Chain);
ee6ba406 5305 end Build_Task_Allocate_Block;
5306
bdd64cbe 5307 -----------------------------------------------
5308 -- Build_Task_Allocate_Block_With_Init_Stmts --
5309 -----------------------------------------------
5310
5311 procedure Build_Task_Allocate_Block_With_Init_Stmts
5312 (Actions : List_Id;
5313 N : Node_Id;
5314 Init_Stmts : List_Id)
5315 is
5316 Loc : constant Source_Ptr := Sloc (N);
5317 Chain : constant Entity_Id :=
5318 Make_Defining_Identifier (Loc, Name_uChain);
ec97ce79 5319 Blkent : constant Entity_Id := Make_Temporary (Loc, 'A');
bdd64cbe 5320 Block : Node_Id;
5321
5322 begin
bdd64cbe 5323 Append_To (Init_Stmts,
5324 Make_Procedure_Call_Statement (Loc,
83c6c069 5325 Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
bdd64cbe 5326 Parameter_Associations => New_List (
5327 Make_Attribute_Reference (Loc,
83c6c069 5328 Prefix => New_Occurrence_Of (Chain, Loc),
bdd64cbe 5329 Attribute_Name => Name_Unchecked_Access))));
5330
5331 Block :=
5332 Make_Block_Statement (Loc,
83c6c069 5333 Identifier => New_Occurrence_Of (Blkent, Loc),
bdd64cbe 5334 Declarations => New_List (
5335
5336 -- _Chain : Activation_Chain;
5337
5338 Make_Object_Declaration (Loc,
5339 Defining_Identifier => Chain,
10970cab 5340 Aliased_Present => True,
bdd64cbe 5341 Object_Definition =>
83c6c069 5342 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
bdd64cbe 5343
5344 Handled_Statement_Sequence =>
5345 Make_Handled_Sequence_Of_Statements (Loc, Init_Stmts),
5346
5347 Has_Created_Identifier => True,
5348 Is_Task_Allocation_Block => True);
5349
5350 Append_To (Actions,
5351 Make_Implicit_Label_Declaration (Loc,
5352 Defining_Identifier => Blkent,
5353 Label_Construct => Block));
5354
5355 Append_To (Actions, Block);
5356
5357 Set_Activation_Chain_Entity (Block, Chain);
5358 end Build_Task_Allocate_Block_With_Init_Stmts;
5359
ee6ba406 5360 -----------------------------------
5361 -- Build_Task_Proc_Specification --
5362 -----------------------------------
5363
5364 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
57993a53 5365 Loc : constant Source_Ptr := Sloc (T);
5366 Spec_Id : Entity_Id;
ee6ba406 5367
5368 begin
aaf44d5a 5369 -- Case of explicit task type, suffix TB
5370
c975df51 5371 if Comes_From_Source (T) then
c975df51 5372 Spec_Id :=
10970cab 5373 Make_Defining_Identifier (Loc, New_External_Name (Chars (T), "TB"));
aaf44d5a 5374
5375 -- Case of anonymous task type, suffix B
5376
c975df51 5377 else
c975df51 5378 Spec_Id :=
10970cab 5379 Make_Defining_Identifier (Loc, New_External_Name (Chars (T), 'B'));
c975df51 5380 end if;
5381
57993a53 5382 Set_Is_Internal (Spec_Id);
ee6ba406 5383
5384 -- Associate the procedure with the task, if this is the declaration
5385 -- (and not the body) of the procedure.
5386
4660e715 5387 if No (Task_Body_Procedure (T)) then
57993a53 5388 Set_Task_Body_Procedure (T, Spec_Id);
ee6ba406 5389 end if;
5390
5391 return
5392 Make_Procedure_Specification (Loc,
57993a53 5393 Defining_Unit_Name => Spec_Id,
5394 Parameter_Specifications => New_List (
5395 Make_Parameter_Specification (Loc,
5396 Defining_Identifier =>
5397 Make_Defining_Identifier (Loc, Name_uTask),
5398 Parameter_Type =>
5399 Make_Access_Definition (Loc,
5400 Subtype_Mark =>
83c6c069 5401 New_Occurrence_Of (Corresponding_Record_Type (T), Loc)))));
ee6ba406 5402 end Build_Task_Proc_Specification;
5403
5404 ---------------------------------------
5405 -- Build_Unprotected_Subprogram_Body --
5406 ---------------------------------------
5407
5408 function Build_Unprotected_Subprogram_Body
bdd64cbe 5409 (N : Node_Id;
5410 Pid : Node_Id) return Node_Id
ee6ba406 5411 is
57993a53 5412 Decls : constant List_Id := Declarations (N);
ee6ba406 5413
5414 begin
3ff5e35d 5415 -- Add renamings for the Protection object, discriminals, privals, and
2c145f84 5416 -- the entry index constant for use by debugger.
57993a53 5417
5418 Debug_Private_Data_Declarations (Decls);
5419
76a1c25b 5420 -- Make an unprotected version of the subprogram for use within the same
5421 -- object, with a new name and an additional parameter representing the
5422 -- object.
ee6ba406 5423
ee6ba406 5424 return
57993a53 5425 Make_Subprogram_Body (Sloc (N),
5426 Specification =>
5427 Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode),
5428 Declarations => Decls,
5429 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
ee6ba406 5430 end Build_Unprotected_Subprogram_Body;
5431
5432 ----------------------------
5433 -- Collect_Entry_Families --
5434 ----------------------------
5435
5436 procedure Collect_Entry_Families
5437 (Loc : Source_Ptr;
5438 Cdecls : List_Id;
5439 Current_Node : in out Node_Id;
5440 Conctyp : Entity_Id)
5441 is
5442 Efam : Entity_Id;
5443 Efam_Decl : Node_Id;
5444 Efam_Type : Entity_Id;
5445
5446 begin
5447 Efam := First_Entity (Conctyp);
ee6ba406 5448 while Present (Efam) loop
ee6ba406 5449 if Ekind (Efam) = E_Entry_Family then
ec97ce79 5450 Efam_Type := Make_Temporary (Loc, 'F');
ee6ba406 5451
76a1c25b 5452 declare
5453 Bas : Entity_Id :=
ee6ba406 5454 Base_Type
849fc00e 5455 (Etype (Discrete_Subtype_Definition (Parent (Efam))));
57993a53 5456
76a1c25b 5457 Bas_Decl : Node_Id := Empty;
5458 Lo, Hi : Node_Id;
5459
5460 begin
5461 Get_Index_Bounds
5462 (Discrete_Subtype_Definition (Parent (Efam)), Lo, Hi);
cb5f80c1 5463
5464 if Is_Potentially_Large_Family (Bas, Conctyp, Lo, Hi) then
ec97ce79 5465 Bas := Make_Temporary (Loc, 'B');
57993a53 5466
76a1c25b 5467 Bas_Decl :=
5468 Make_Subtype_Declaration (Loc,
5469 Defining_Identifier => Bas,
57993a53 5470 Subtype_Indication =>
76a1c25b 5471 Make_Subtype_Indication (Loc,
5472 Subtype_Mark =>
5473 New_Occurrence_Of (Standard_Integer, Loc),
57993a53 5474 Constraint =>
76a1c25b 5475 Make_Range_Constraint (Loc,
5476 Range_Expression => Make_Range (Loc,
5477 Make_Integer_Literal
5478 (Loc, -Entry_Family_Bound),
5479 Make_Integer_Literal
5480 (Loc, Entry_Family_Bound - 1)))));
5481
5482 Insert_After (Current_Node, Bas_Decl);
5483 Current_Node := Bas_Decl;
5484 Analyze (Bas_Decl);
5485 end if;
5486
5487 Efam_Decl :=
5488 Make_Full_Type_Declaration (Loc,
5489 Defining_Identifier => Efam_Type,
5490 Type_Definition =>
5491 Make_Unconstrained_Array_Definition (Loc,
5492 Subtype_Marks =>
5493 (New_List (New_Occurrence_Of (Bas, Loc))),
ee6ba406 5494
b5ff3ed8 5495 Component_Definition =>
0914a918 5496 Make_Component_Definition (Loc,
5497 Aliased_Present => False,
5498 Subtype_Indication =>
83c6c069 5499 New_Occurrence_Of (Standard_Character, Loc))));
76a1c25b 5500 end;
ee6ba406 5501
5502 Insert_After (Current_Node, Efam_Decl);
5503 Current_Node := Efam_Decl;
5504 Analyze (Efam_Decl);
5505
5506 Append_To (Cdecls,
5507 Make_Component_Declaration (Loc,
10970cab 5508 Defining_Identifier =>
ee6ba406 5509 Make_Defining_Identifier (Loc, Chars (Efam)),
5510
b5ff3ed8 5511 Component_Definition =>
5512 Make_Component_Definition (Loc,
5513 Aliased_Present => False,
5514 Subtype_Indication =>
5515 Make_Subtype_Indication (Loc,
5516 Subtype_Mark =>
5517 New_Occurrence_Of (Efam_Type, Loc),
0914a918 5518
10970cab 5519 Constraint =>
b5ff3ed8 5520 Make_Index_Or_Discriminant_Constraint (Loc,
5521 Constraints => New_List (
5522 New_Occurrence_Of
5523 (Etype (Discrete_Subtype_Definition
10970cab 5524 (Parent (Efam))), Loc)))))));
b5ff3ed8 5525
ee6ba406 5526 end if;
5527
5528 Next_Entity (Efam);
5529 end loop;
5530 end Collect_Entry_Families;
5531
57993a53 5532 -----------------------
5533 -- Concurrent_Object --
5534 -----------------------
5535
5536 function Concurrent_Object
5537 (Spec_Id : Entity_Id;
5538 Conc_Typ : Entity_Id) return Entity_Id
5539 is
5540 begin
5541 -- Parameter _O or _object
5542
5543 if Is_Protected_Type (Conc_Typ) then
5544 return First_Formal (Protected_Body_Subprogram (Spec_Id));
5545
5546 -- Parameter _task
5547
5548 else
5549 pragma Assert (Is_Task_Type (Conc_Typ));
5550 return First_Formal (Task_Body_Procedure (Conc_Typ));
5551 end if;
5552 end Concurrent_Object;
5553
5554 ----------------------
5555 -- Copy_Result_Type --
5556 ----------------------
5557
4961db87 5558 function Copy_Result_Type (Res : Node_Id) return Node_Id is
5559 New_Res : constant Node_Id := New_Copy_Tree (Res);
5560 Par_Spec : Node_Id;
5561 Formal : Entity_Id;
5562
5563 begin
85377c9b 5564 -- If the result type is an access_to_subprogram, we must create new
5565 -- entities for its spec.
4961db87 5566
d333ad56 5567 if Nkind (New_Res) = N_Access_Definition
5568 and then Present (Access_To_Subprogram_Definition (New_Res))
5569 then
4961db87 5570 -- Provide new entities for the formals
5571
5572 Par_Spec := First (Parameter_Specifications
5573 (Access_To_Subprogram_Definition (New_Res)));
5574 while Present (Par_Spec) loop
5575 Formal := Defining_Identifier (Par_Spec);
5576 Set_Defining_Identifier (Par_Spec,
5577 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)));
5578 Next (Par_Spec);
5579 end loop;
5580 end if;
5581
5582 return New_Res;
5583 end Copy_Result_Type;
5584
ee6ba406 5585 --------------------
5586 -- Concurrent_Ref --
5587 --------------------
5588
76a1c25b 5589 -- The expression returned for a reference to a concurrent object has the
5590 -- form:
ee6ba406 5591
5592 -- taskV!(name)._Task_Id
5593
5594 -- for a task, and
5595
5596 -- objectV!(name)._Object
5597
2866d595 5598 -- for a protected object. For the case of an access to a concurrent
5599 -- object, there is an extra explicit dereference:
ee6ba406 5600
5601 -- taskV!(name.all)._Task_Id
5602 -- objectV!(name.all)._Object
5603
5604 -- here taskV and objectV are the types for the associated records, which
76a1c25b 5605 -- contain the required _Task_Id and _Object fields for tasks and protected
5606 -- objects, respectively.
ee6ba406 5607
5608 -- For the case of a task type name, the expression is
5609
5610 -- Self;
5611
5612 -- i.e. a call to the Self function which returns precisely this Task_Id
5613
5614 -- For the case of a protected type name, the expression is
5615
5616 -- objectR
5617
bf3e1520 5618 -- which is a renaming of the _object field of the current object
76a1c25b 5619 -- record, passed into protected operations as a parameter.
ee6ba406 5620
5621 function Concurrent_Ref (N : Node_Id) return Node_Id is
5622 Loc : constant Source_Ptr := Sloc (N);
5623 Ntyp : constant Entity_Id := Etype (N);
5624 Dtyp : Entity_Id;
5625 Sel : Name_Id;
5626
5627 function Is_Current_Task (T : Entity_Id) return Boolean;
5628 -- Check whether the reference is to the immediately enclosing task
5629 -- type, or to an outer one (rare but legal).
5630
5631 ---------------------
5632 -- Is_Current_Task --
5633 ---------------------
5634
5635 function Is_Current_Task (T : Entity_Id) return Boolean is
5636 Scop : Entity_Id;
5637
5638 begin
5639 Scop := Current_Scope;
c0688d2b 5640 while Present (Scop) and then Scop /= Standard_Standard loop
ee6ba406 5641 if Scop = T then
5642 return True;
5643
5644 elsif Is_Task_Type (Scop) then
5645 return False;
5646
5647 -- If this is a procedure nested within the task type, we must
5648 -- assume that it can be called from an inner task, and therefore
5649 -- cannot treat it as a local reference.
5650
10970cab 5651 elsif Is_Overloadable (Scop) and then In_Open_Scopes (T) then
ee6ba406 5652 return False;
5653
5654 else
5655 Scop := Scope (Scop);
5656 end if;
5657 end loop;
5658
76a1c25b 5659 -- We know that we are within the task body, so should have found it
5660 -- in scope.
ee6ba406 5661
5662 raise Program_Error;
5663 end Is_Current_Task;
5664
5665 -- Start of processing for Concurrent_Ref
5666
5667 begin
5668 if Is_Access_Type (Ntyp) then
5669 Dtyp := Designated_Type (Ntyp);
5670
5671 if Is_Protected_Type (Dtyp) then
5672 Sel := Name_uObject;
5673 else
5674 Sel := Name_uTask_Id;
5675 end if;
5676
5677 return
5678 Make_Selected_Component (Loc,
10970cab 5679 Prefix =>
ee6ba406 5680 Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
5681 Make_Explicit_Dereference (Loc, N)),
5682 Selector_Name => Make_Identifier (Loc, Sel));
5683
85377c9b 5684 elsif Is_Entity_Name (N) and then Is_Concurrent_Type (Entity (N)) then
ee6ba406 5685 if Is_Task_Type (Entity (N)) then
5686
5687 if Is_Current_Task (Entity (N)) then
5688 return
5689 Make_Function_Call (Loc,
83c6c069 5690 Name => New_Occurrence_Of (RTE (RE_Self), Loc));
ee6ba406 5691
5692 else
5693 declare
5694 Decl : Node_Id;
ec97ce79 5695 T_Self : constant Entity_Id := Make_Temporary (Loc, 'T');
76a1c25b 5696 T_Body : constant Node_Id :=
5697 Parent (Corresponding_Body (Parent (Entity (N))));
ee6ba406 5698
5699 begin
ec97ce79 5700 Decl :=
5701 Make_Object_Declaration (Loc,
5702 Defining_Identifier => T_Self,
5703 Object_Definition =>
5704 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
5705 Expression =>
5706 Make_Function_Call (Loc,
83c6c069 5707 Name => New_Occurrence_Of (RTE (RE_Self), Loc)));
ee6ba406 5708 Prepend (Decl, Declarations (T_Body));
5709 Analyze (Decl);
5710 Set_Scope (T_Self, Entity (N));
5711 return New_Occurrence_Of (T_Self, Loc);
5712 end;
5713 end if;
5714
5715 else
5716 pragma Assert (Is_Protected_Type (Entity (N)));
57993a53 5717
ee6ba406 5718 return
83c6c069 5719 New_Occurrence_Of (Find_Protection_Object (Current_Scope), Loc);
ee6ba406 5720 end if;
5721
5722 else
ee6ba406 5723 if Is_Protected_Type (Ntyp) then
5724 Sel := Name_uObject;
5809835d 5725 elsif Is_Task_Type (Ntyp) then
ee6ba406 5726 Sel := Name_uTask_Id;
5809835d 5727 else
5728 raise Program_Error;
ee6ba406 5729 end if;
5730
5731 return
5732 Make_Selected_Component (Loc,
55868293 5733 Prefix =>
ee6ba406 5734 Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
5735 New_Copy_Tree (N)),
5736 Selector_Name => Make_Identifier (Loc, Sel));
5737 end if;
5738 end Concurrent_Ref;
5739
5740 ------------------------
5741 -- Convert_Concurrent --
5742 ------------------------
5743
5744 function Convert_Concurrent
bdd64cbe 5745 (N : Node_Id;
5746 Typ : Entity_Id) return Node_Id
ee6ba406 5747 is
5748 begin
5749 if not Is_Concurrent_Type (Typ) then
5750 return N;
5751 else
5752 return
82ae9906 5753 Unchecked_Convert_To
5754 (Corresponding_Record_Type (Typ), New_Copy_Tree (N));
ee6ba406 5755 end if;
5756 end Convert_Concurrent;
5757
57993a53 5758 -------------------------------------
5759 -- Debug_Private_Data_Declarations --
5760 -------------------------------------
5761
5762 procedure Debug_Private_Data_Declarations (Decls : List_Id) is
5763 Debug_Nod : Node_Id;
5764 Decl : Node_Id;
5765
5766 begin
5767 Decl := First (Decls);
85377c9b 5768 while Present (Decl) and then not Comes_From_Source (Decl) loop
c0688d2b 5769
57993a53 5770 -- Declaration for concurrent entity _object and its access type,
5771 -- along with the entry index subtype:
5772 -- type prot_typVP is access prot_typV;
5773 -- _object : prot_typVP := prot_typV (_O);
5774 -- subtype Jnn is <Type of Index> range Low .. High;
5775
5776 if Nkind_In (Decl, N_Full_Type_Declaration, N_Object_Declaration) then
5777 Set_Debug_Info_Needed (Defining_Identifier (Decl));
5778
3ff5e35d 5779 -- Declaration for the Protection object, discriminals, privals, and
57993a53 5780 -- entry index constant:
5781 -- conc_typR : protection_typ renames _object._object;
5782 -- discr_nameD : discr_typ renames _object.discr_name;
5783 -- discr_nameD : discr_typ renames _task.discr_name;
5784 -- prival_name : comp_typ renames _object.comp_name;
5785 -- J : constant Jnn :=
5786 -- Jnn'Val (_E - <Index expression> + Jnn'Pos (Jnn'First));
5787
5788 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
5789 Set_Debug_Info_Needed (Defining_Identifier (Decl));
5790 Debug_Nod := Debug_Renaming_Declaration (Decl);
5791
5792 if Present (Debug_Nod) then
5793 Insert_After (Decl, Debug_Nod);
5794 end if;
5795 end if;
5796
5797 Next (Decl);
5798 end loop;
5799 end Debug_Private_Data_Declarations;
5800
e3cb8202 5801 ------------------------------
5802 -- Ensure_Statement_Present --
5803 ------------------------------
5804
5805 procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id) is
3a72f9c3 5806 Stmt : Node_Id;
2beb22b1 5807
e3cb8202 5808 begin
5809 if Opt.Suppress_Control_Flow_Optimizations
e22bc81a 5810 and then Is_Empty_List (Statements (Alt))
e3cb8202 5811 then
3a72f9c3 5812 Stmt := Make_Null_Statement (Loc);
5813
5814 -- Mark NULL statement as coming from source so that it is not
5815 -- eliminated by GIGI.
5816
39a0c1d3 5817 -- Another covert channel. If this is a requirement, it must be
2beb22b1 5818 -- documented in sinfo/einfo ???
5819
3a72f9c3 5820 Set_Comes_From_Source (Stmt, True);
5821
5822 Set_Statements (Alt, New_List (Stmt));
e3cb8202 5823 end if;
5824 end Ensure_Statement_Present;
5825
ee6ba406 5826 ----------------------------
5827 -- Entry_Index_Expression --
5828 ----------------------------
5829
5830 function Entry_Index_Expression
5831 (Sloc : Source_Ptr;
5832 Ent : Entity_Id;
5833 Index : Node_Id;
bdd64cbe 5834 Ttyp : Entity_Id) return Node_Id
ee6ba406 5835 is
5836 Expr : Node_Id;
5837 Num : Node_Id;
5838 Lo : Node_Id;
5839 Hi : Node_Id;
5840 Prev : Entity_Id;
5841 S : Node_Id;
5842
5843 begin
76a1c25b 5844 -- The queues of entries and entry families appear in textual order in
5845 -- the associated record. The entry index is computed as the sum of the
5846 -- number of queues for all entries that precede the designated one, to
5847 -- which is added the index expression, if this expression denotes a
5848 -- member of a family.
ee6ba406 5849
2866d595 5850 -- The following is a place holder for the count of simple entries
ee6ba406 5851
5852 Num := Make_Integer_Literal (Sloc, 1);
5853
76a1c25b 5854 -- We construct an expression which is a series of addition operations.
5855 -- The first operand is the number of single entries that precede this
5856 -- one, the second operand is the index value relative to the start of
5857 -- the referenced family, and the remaining operands are the lengths of
5858 -- the entry families that precede this entry, i.e. the constructed
5859 -- expression is:
ee6ba406 5860
5861 -- number_simple_entries +
5862 -- (s'pos (index-value) - s'pos (family'first)) + 1 +
5863 -- family'length + ...
5864
5865 -- where index-value is the given index value, and s is the index
5866 -- subtype (we have to use pos because the subtype might be an
76a1c25b 5867 -- enumeration type preventing direct subtraction). Note that the task
5868 -- entry array is one-indexed.
ee6ba406 5869
5870 -- The upper bound of the entry family may be a discriminant, so we
5871 -- retrieve the lower bound explicitly to compute offset, rather than
5872 -- using the index subtype which may mention a discriminant.
5873
5874 if Present (Index) then
5875 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
5876
5877 Expr :=
5878 Make_Op_Add (Sloc,
5879 Left_Opnd => Num,
ee6ba406 5880 Right_Opnd =>
c0688d2b 5881 Family_Offset
5882 (Sloc,
5883 Make_Attribute_Reference (Sloc,
5884 Attribute_Name => Name_Pos,
5885 Prefix => New_Occurrence_Of (Base_Type (S), Sloc),
5886 Expressions => New_List (Relocate_Node (Index))),
5887 Type_Low_Bound (S),
5888 Ttyp,
5889 False));
ee6ba406 5890 else
5891 Expr := Num;
5892 end if;
5893
2866d595 5894 -- Now add lengths of preceding entries and entry families
ee6ba406 5895
5896 Prev := First_Entity (Ttyp);
ee6ba406 5897 while Chars (Prev) /= Chars (Ent)
5898 or else (Ekind (Prev) /= Ekind (Ent))
5899 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
5900 loop
5901 if Ekind (Prev) = E_Entry then
5902 Set_Intval (Num, Intval (Num) + 1);
5903
5904 elsif Ekind (Prev) = E_Entry_Family then
c0688d2b 5905 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
ee6ba406 5906 Lo := Type_Low_Bound (S);
5907 Hi := Type_High_Bound (S);
5908
5909 Expr :=
5910 Make_Op_Add (Sloc,
c0688d2b 5911 Left_Opnd => Expr,
5912 Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp, False));
ee6ba406 5913
2866d595 5914 -- Other components are anonymous types to be ignored
ee6ba406 5915
5916 else
5917 null;
5918 end if;
5919
5920 Next_Entity (Prev);
5921 end loop;
5922
5923 return Expr;
5924 end Entry_Index_Expression;
5925
5926 ---------------------------
5927 -- Establish_Task_Master --
5928 ---------------------------
5929
5930 procedure Establish_Task_Master (N : Node_Id) is
5931 Call : Node_Id;
192b8dab 5932
ee6ba406 5933 begin
1e16c51c 5934 if Restriction_Active (No_Task_Hierarchy) = False then
ee6ba406 5935 Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
192b8dab 5936
10970cab 5937 -- The block may have no declarations (and nevertheless be a task
5938 -- master) if it contains a call that may return an object that
192b8dab 5939 -- contains tasks.
5940
5941 if No (Declarations (N)) then
5942 Set_Declarations (N, New_List (Call));
5943 else
5944 Prepend_To (Declarations (N), Call);
5945 end if;
5946
ee6ba406 5947 Analyze (Call);
5948 end if;
5949 end Establish_Task_Master;
5950
5951 --------------------------------
5952 -- Expand_Accept_Declarations --
5953 --------------------------------
5954
5955 -- Part of the expansion of an accept statement involves the creation of
5956 -- a declaration that can be referenced from the statement sequence of
5957 -- the accept:
5958
5959 -- Ann : Address;
5960
5961 -- This declaration is inserted immediately before the accept statement
5962 -- and it is important that it be inserted before the statements of the
5963 -- statement sequence are analyzed. Thus it would be too late to create
5964 -- this declaration in the Expand_N_Accept_Statement routine, which is
5965 -- why there is a separate procedure to be called directly from Sem_Ch9.
5966
5967 -- Ann is used to hold the address of the record containing the parameters
5968 -- (see Expand_N_Entry_Call for more details on how this record is built).
5969 -- References to the parameters do an unchecked conversion of this address
5970 -- to a pointer to the required record type, and then access the field that
5971 -- holds the value of the required parameter. The entity for the address
5972 -- variable is held as the top stack element (i.e. the last element) of the
5973 -- Accept_Address stack in the corresponding entry entity, and this element
5974 -- must be set in place before the statements are processed.
5975
5976 -- The above description applies to the case of a stand alone accept
5977 -- statement, i.e. one not appearing as part of a select alternative.
5978
5979 -- For the case of an accept that appears as part of a select alternative
5980 -- of a selective accept, we must still create the declaration right away,
5981 -- since Ann is needed immediately, but there is an important difference:
5982
5983 -- The declaration is inserted before the selective accept, not before
5984 -- the accept statement (which is not part of a list anyway, and so would
5985 -- not accommodate inserted declarations)
5986
5987 -- We only need one address variable for the entire selective accept. So
5988 -- the Ann declaration is created only for the first accept alternative,
5989 -- and subsequent accept alternatives reference the same Ann variable.
5990
5991 -- We can distinguish the two cases by seeing whether the accept statement
5992 -- is part of a list. If not, then it must be in an accept alternative.
5993
76a1c25b 5994 -- To expand the requeue statement, a label is provided at the end of the
5995 -- accept statement or alternative of which it is a part, so that the
5996 -- statement can be skipped after the requeue is complete. This label is
5997 -- created here rather than during the expansion of the accept statement,
5998 -- because it will be needed by any requeue statements within the accept,
5999 -- which are expanded before the accept.
ee6ba406 6000
6001 procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
6002 Loc : constant Source_Ptr := Sloc (N);
d333ad56 6003 Stats : constant Node_Id := Handled_Statement_Sequence (N);
6004 Ann : Entity_Id := Empty;
ee6ba406 6005 Adecl : Node_Id;
ee6ba406 6006 Lab : Node_Id;
6007 Ldecl : Node_Id;
6008 Ldecl2 : Node_Id;
6009
6010 begin
a33565dd 6011 if Expander_Active then
680a0a68 6012
d333ad56 6013 -- If we have no handled statement sequence, we may need to build
6014 -- a dummy sequence consisting of a null statement. This can be
6015 -- skipped if the trivial accept optimization is permitted.
6016
6017 if not Trivial_Accept_OK
c0688d2b 6018 and then (No (Stats) or else Null_Statements (Statements (Stats)))
ee6ba406 6019 then
6020 Set_Handled_Statement_Sequence (N,
6021 Make_Handled_Sequence_Of_Statements (Loc,
0f3b1f49 6022 Statements => New_List (Make_Null_Statement (Loc))));
ee6ba406 6023 end if;
6024
6025 -- Create and declare two labels to be placed at the end of the
6026 -- accept statement. The first label is used to allow requeues to
76a1c25b 6027 -- skip the remainder of entry processing. The second label is used
6028 -- to skip the remainder of entry processing if the rendezvous
ee6ba406 6029 -- completes in the middle of the accept body.
6030
6031 if Present (Handled_Statement_Sequence (N)) then
ec97ce79 6032 declare
6033 Ent : Entity_Id;
6034
6035 begin
6036 Ent := Make_Temporary (Loc, 'L');
83c6c069 6037 Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
ec97ce79 6038 Ldecl :=
6039 Make_Implicit_Label_Declaration (Loc,
6040 Defining_Identifier => Ent,
6041 Label_Construct => Lab);
6042 Append (Lab, Statements (Handled_Statement_Sequence (N)));
6043
6044 Ent := Make_Temporary (Loc, 'L');
83c6c069 6045 Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
ec97ce79 6046 Ldecl2 :=
6047 Make_Implicit_Label_Declaration (Loc,
6048 Defining_Identifier => Ent,
6049 Label_Construct => Lab);
6050 Append (Lab, Statements (Handled_Statement_Sequence (N)));
6051 end;
ee6ba406 6052
6053 else
85377c9b 6054 Ldecl := Empty;
ee6ba406 6055 Ldecl2 := Empty;
6056 end if;
6057
6058 -- Case of stand alone accept statement
6059
6060 if Is_List_Member (N) then
6061
6062 if Present (Handled_Statement_Sequence (N)) then
ec97ce79 6063 Ann := Make_Temporary (Loc, 'A');
ee6ba406 6064
6065 Adecl :=
6066 Make_Object_Declaration (Loc,
6067 Defining_Identifier => Ann,
85377c9b 6068 Object_Definition =>
83c6c069 6069 New_Occurrence_Of (RTE (RE_Address), Loc));
ee6ba406 6070
85377c9b 6071 Insert_Before_And_Analyze (N, Adecl);
6072 Insert_Before_And_Analyze (N, Ldecl);
6073 Insert_Before_And_Analyze (N, Ldecl2);
ee6ba406 6074 end if;
6075
6076 -- Case of accept statement which is in an accept alternative
6077
6078 else
6079 declare
6080 Acc_Alt : constant Node_Id := Parent (N);
6081 Sel_Acc : constant Node_Id := Parent (Acc_Alt);
6082 Alt : Node_Id;
6083
6084 begin
6085 pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
6086 pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
6087
2866d595 6088 -- ??? Consider a single label for select statements
ee6ba406 6089
6090 if Present (Handled_Statement_Sequence (N)) then
6091 Prepend (Ldecl2,
6092 Statements (Handled_Statement_Sequence (N)));
6093 Analyze (Ldecl2);
6094
6095 Prepend (Ldecl,
6096 Statements (Handled_Statement_Sequence (N)));
6097 Analyze (Ldecl);
6098 end if;
6099
6100 -- Find first accept alternative of the selective accept. A
6101 -- valid selective accept must have at least one accept in it.
6102
6103 Alt := First (Select_Alternatives (Sel_Acc));
6104
6105 while Nkind (Alt) /= N_Accept_Alternative loop
6106 Next (Alt);
6107 end loop;
6108
10970cab 6109 -- If this is the first accept statement, then we have to
6110 -- create the Ann variable, as for the stand alone case, except
6111 -- that it is inserted before the selective accept. Similarly,
6112 -- a label for requeue expansion must be declared.
ee6ba406 6113
6114 if N = Accept_Statement (Alt) then
ec97ce79 6115 Ann := Make_Temporary (Loc, 'A');
ee6ba406 6116 Adecl :=
6117 Make_Object_Declaration (Loc,
6118 Defining_Identifier => Ann,
85377c9b 6119 Object_Definition =>
83c6c069 6120 New_Occurrence_Of (RTE (RE_Address), Loc));
ee6ba406 6121
85377c9b 6122 Insert_Before_And_Analyze (Sel_Acc, Adecl);
ee6ba406 6123
10970cab 6124 -- If this is not the first accept statement, then find the Ann
76a1c25b 6125 -- variable allocated by the first accept and use it.
ee6ba406 6126
6127 else
6128 Ann :=
6129 Node (Last_Elmt (Accept_Address
6130 (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
6131 end if;
6132 end;
6133 end if;
6134
6135 -- Merge here with Ann either created or referenced, and Adecl
6136 -- pointing to the corresponding declaration. Remaining processing
6137 -- is the same for the two cases.
6138
6139 if Present (Ann) then
6140 Append_Elmt (Ann, Accept_Address (Ent));
70966f50 6141 Set_Debug_Info_Needed (Ann);
9dfe12ae 6142 end if;
6143
76a1c25b 6144 -- Create renaming declarations for the entry formals. Each reference
6145 -- to a formal becomes a dereference of a component of the parameter
6146 -- block, whose address is held in Ann. These declarations are
6147 -- eventually inserted into the accept block, and analyzed there so
6148 -- that they have the proper scope for gdb and do not conflict with
6149 -- other declarations.
9dfe12ae 6150
6151 if Present (Parameter_Specifications (N))
6152 and then Present (Handled_Statement_Sequence (N))
6153 then
6154 declare
b76dc1f0 6155 Comp : Entity_Id;
6156 Decl : Node_Id;
6157 Formal : Entity_Id;
6158 New_F : Entity_Id;
6159 Renamed_Formal : Node_Id;
9dfe12ae 6160
6161 begin
4961db87 6162 Push_Scope (Ent);
9dfe12ae 6163 Formal := First_Formal (Ent);
6164
6165 while Present (Formal) loop
76a1c25b 6166 Comp := Entry_Component (Formal);
85377c9b 6167 New_F := Make_Defining_Identifier (Loc, Chars (Formal));
76a1c25b 6168
9dfe12ae 6169 Set_Etype (New_F, Etype (Formal));
6170 Set_Scope (New_F, Ent);
70966f50 6171
7cab648c 6172 -- Now we set debug info needed on New_F even though it does
6173 -- not come from source, so that the debugger will get the
6174 -- right information for these generated names.
70966f50 6175
6176 Set_Debug_Info_Needed (New_F);
9dfe12ae 6177
6178 if Ekind (Formal) = E_In_Parameter then
6179 Set_Ekind (New_F, E_Constant);
6180 else
6181 Set_Ekind (New_F, E_Variable);
6182 Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
6183 end if;
6184
6185 Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
6186
b76dc1f0 6187 Renamed_Formal :=
6188 Make_Selected_Component (Loc,
6189 Prefix =>
6190 Unchecked_Convert_To (
6191 Entry_Parameters_Type (Ent),
83c6c069 6192 New_Occurrence_Of (Ann, Loc)),
b76dc1f0 6193 Selector_Name =>
83c6c069 6194 New_Occurrence_Of (Comp, Loc));
b76dc1f0 6195
9dfe12ae 6196 Decl :=
b76dc1f0 6197 Build_Renamed_Formal_Declaration
6198 (New_F, Formal, Comp, Renamed_Formal);
9dfe12ae 6199
6200 if No (Declarations (N)) then
6201 Set_Declarations (N, New_List);
6202 end if;
6203
6204 Append (Decl, Declarations (N));
6205 Set_Renamed_Object (Formal, New_F);
6206 Next_Formal (Formal);
6207 end loop;
6208
6209 End_Scope;
6210 end;
ee6ba406 6211 end if;
6212 end if;
6213 end Expand_Accept_Declarations;
6214
6215 ---------------------------------------------
6216 -- Expand_Access_Protected_Subprogram_Type --
6217 ---------------------------------------------
6218
6219 procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
6220 Loc : constant Source_Ptr := Sloc (N);
6221 Comps : List_Id;
6222 T : constant Entity_Id := Defining_Identifier (N);
6223 D_T : constant Entity_Id := Designated_Type (T);
ec97ce79 6224 D_T2 : constant Entity_Id := Make_Temporary (Loc, 'D');
6225 E_T : constant Entity_Id := Make_Temporary (Loc, 'E');
ee6ba406 6226 P_List : constant List_Id := Build_Protected_Spec
57993a53 6227 (N, RTE (RE_Address), D_T, False);
ee6ba406 6228 Decl1 : Node_Id;
6229 Decl2 : Node_Id;
6230 Def1 : Node_Id;
6231
6232 begin
f74a743d 6233 -- Create access to subprogram with full signature
ee6ba406 6234
f74a743d 6235 if Etype (D_T) /= Standard_Void_Type then
ee6ba406 6236 Def1 :=
6237 Make_Access_Function_Definition (Loc,
6238 Parameter_Specifications => P_List,
57993a53 6239 Result_Definition =>
4961db87 6240 Copy_Result_Type (Result_Definition (Type_Definition (N))));
ee6ba406 6241
6242 else
6243 Def1 :=
6244 Make_Access_Procedure_Definition (Loc,
6245 Parameter_Specifications => P_List);
6246 end if;
6247
6248 Decl1 :=
6249 Make_Full_Type_Declaration (Loc,
6250 Defining_Identifier => D_T2,
85377c9b 6251 Type_Definition => Def1);
ee6ba406 6252
85377c9b 6253 Insert_After_And_Analyze (N, Decl1);
ee6ba406 6254
ac1200d2 6255 -- Associate the access to subprogram with its original access to
6256 -- protected subprogram type. Needed by the backend to know that this
6257 -- type corresponds with an access to protected subprogram type.
6258
6259 Set_Original_Access_Type (D_T2, T);
6260
76a1c25b 6261 -- Create Equivalent_Type, a record with two components for an access to
6262 -- object and an access to subprogram.
ee6ba406 6263
6264 Comps := New_List (
6265 Make_Component_Declaration (Loc,
9765de15 6266 Defining_Identifier => Make_Temporary (Loc, 'P'),
b5ff3ed8 6267 Component_Definition =>
6268 Make_Component_Definition (Loc,
85377c9b 6269 Aliased_Present => False,
b5ff3ed8 6270 Subtype_Indication =>
6271 New_Occurrence_Of (RTE (RE_Address), Loc))),
ee6ba406 6272
6273 Make_Component_Declaration (Loc,
ec97ce79 6274 Defining_Identifier => Make_Temporary (Loc, 'S'),
b5ff3ed8 6275 Component_Definition =>
6276 Make_Component_Definition (Loc,
ec97ce79 6277 Aliased_Present => False,
b5ff3ed8 6278 Subtype_Indication => New_Occurrence_Of (D_T2, Loc))));
ee6ba406 6279
6280 Decl2 :=
6281 Make_Full_Type_Declaration (Loc,
6282 Defining_Identifier => E_T,
9765de15 6283 Type_Definition =>
ee6ba406 6284 Make_Record_Definition (Loc,
6285 Component_List =>
9765de15 6286 Make_Component_List (Loc, Component_Items => Comps)));
ee6ba406 6287
85377c9b 6288 Insert_After_And_Analyze (Decl1, Decl2);
ee6ba406 6289 Set_Equivalent_Type (T, E_T);
ee6ba406 6290 end Expand_Access_Protected_Subprogram_Type;
6291
6292 --------------------------
6293 -- Expand_Entry_Barrier --
6294 --------------------------
6295
6296 procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
57993a53 6297 Cond : constant Node_Id :=
9dfe12ae 6298 Condition (Entry_Body_Formal_Part (N));
57993a53 6299 Prot : constant Entity_Id := Scope (Ent);
6300 Spec_Decl : constant Node_Id := Parent (Prot);
28191f15 6301 Func : Entity_Id := Empty;
ee6ba406 6302 B_F : Node_Id;
ee6ba406 6303 Body_Decl : Node_Id;
ee6ba406 6304
d3db6e37 6305 function Is_Global_Entity (N : Node_Id) return Traverse_Result;
6306 -- Check whether entity in Barrier is external to protected type.
6307 -- If so, barrier may not be properly synchronized.
6308
6432a7c1 6309 function Is_Pure_Barrier (N : Node_Id) return Traverse_Result;
06e99eb0 6310 -- Check whether N follows the Pure_Barriers restriction. Return OK if
6432a7c1 6311 -- so.
6312
6313 function Is_Simple_Barrier_Name (N : Node_Id) return Boolean;
06e99eb0 6314 -- Check whether entity name N denotes a component of the protected
6432a7c1 6315 -- object. This is used to check the Simple_Barrier restriction.
6316
d3db6e37 6317 ----------------------
6318 -- Is_Global_Entity --
6319 ----------------------
6320
6321 function Is_Global_Entity (N : Node_Id) return Traverse_Result is
6322 E : Entity_Id;
6323 S : Entity_Id;
e25b2537 6324
d3db6e37 6325 begin
6326 if Is_Entity_Name (N) and then Present (Entity (N)) then
6327 E := Entity (N);
6328 S := Scope (E);
6329
6330 if Ekind (E) = E_Variable then
28191f15 6331
6332 -- If the variable is local to the barrier function generated
6333 -- during expansion, it is ok. If expansion is not performed,
6334 -- then Func is Empty so this test cannot succeed.
6335
d3db6e37 6336 if Scope (E) = Func then
6337 null;
6338
6339 -- A protected call from a barrier to another object is ok
6340
6341 elsif Ekind (Etype (E)) = E_Protected_Type then
6342 null;
6343
6344 -- If the variable is within the package body we consider
6345 -- this safe. This is a common (if dubious) idiom.
6346
6347 elsif S = Scope (Prot)
e25b2537 6348 and then Ekind_In (S, E_Package, E_Generic_Package)
d3db6e37 6349 and then Nkind (Parent (E)) = N_Object_Declaration
6350 and then Nkind (Parent (Parent (E))) = N_Package_Body
6351 then
6352 null;
6353
6354 else
1581f2d7 6355 Error_Msg_N ("potentially unsynchronized barrier??", N);
6356 Error_Msg_N ("\& should be private component of type??", N);
d3db6e37 6357 end if;
6358 end if;
6359 end if;
6360
6361 return OK;
6362 end Is_Global_Entity;
6363
6364 procedure Check_Unprotected_Barrier is
e25b2537 6365 new Traverse_Proc (Is_Global_Entity);
6366
6432a7c1 6367 ----------------------------
6368 -- Is_Simple_Barrier_Name --
6369 ----------------------------
6370
6371 function Is_Simple_Barrier_Name (N : Node_Id) return Boolean is
6372 Renamed : Node_Id;
6432a7c1 6373
fbc5a5a6 6374 begin
6432a7c1 6375 -- Check for case of _object.all.field (note that the explicit
06e99eb0 6376 -- dereference gets inserted by analyze/expand of _object.field).
6432a7c1 6377
fbc5a5a6 6378 if Expander_Active then
6432a7c1 6379 Renamed := Renamed_Object (Entity (N));
fbc5a5a6 6380
6381 return
6382 Present (Renamed)
6383 and then Nkind (Renamed) = N_Selected_Component
6384 and then Chars (Prefix (Prefix (Renamed))) = Name_uObject;
6385 else
6386 return Scope (Entity (N)) = Current_Scope;
6432a7c1 6387 end if;
6388 end Is_Simple_Barrier_Name;
6389
6390 ---------------------
6391 -- Is_Pure_Barrier --
6392 ---------------------
6393
6394 function Is_Pure_Barrier (N : Node_Id) return Traverse_Result is
6395 begin
6396 case Nkind (N) is
fbc5a5a6 6397 when N_Expanded_Name |
6398 N_Identifier =>
6432a7c1 6399 if No (Entity (N)) then
6400 return Abandon;
6401 end if;
6402
6403 case Ekind (Entity (N)) is
fbc5a5a6 6404 when E_Constant |
6405 E_Discriminant |
6406 E_Named_Integer |
6407 E_Named_Real |
6408 E_Enumeration_Literal =>
6432a7c1 6409 return OK;
6410
6411 when E_Variable =>
6412 if Is_Simple_Barrier_Name (N) then
6413 return OK;
6414 end if;
6415
6416 when others =>
6417 null;
6418 end case;
6419
fbc5a5a6 6420 when N_Integer_Literal |
6421 N_Real_Literal |
6422 N_Character_Literal =>
6432a7c1 6423 return OK;
6424
fbc5a5a6 6425 when N_Op_Boolean |
6426 N_Op_Not =>
6432a7c1 6427 if Ekind (Entity (N)) = E_Operator then
6428 return OK;
6429 end if;
6430
6431 when N_Short_Circuit =>
6432 return OK;
6433
6434 when others =>
6435 null;
6436 end case;
6437
6438 return Abandon;
6439 end Is_Pure_Barrier;
6440
6441 function Check_Pure_Barriers is new Traverse_Func (Is_Pure_Barrier);
6442
e25b2537 6443 -- Start of processing for Expand_Entry_Barrier
d3db6e37 6444
ee6ba406 6445 begin
9dfe12ae 6446 if No_Run_Time_Mode then
6447 Error_Msg_CRT ("entry barrier", N);
6448 return;
6449 end if;
6450
76a1c25b 6451 -- The body of the entry barrier must be analyzed in the context of the
6452 -- protected object, but its scope is external to it, just as any other
6453 -- unprotected version of a protected operation. The specification has
6454 -- been produced when the protected type declaration was elaborated. We
6455 -- build the body, insert it in the enclosing scope, but analyze it in
57993a53 6456 -- the current context. A more uniform approach would be to treat the
ee6ba406 6457 -- barrier just as a protected function, and discard the protected
6458 -- version of it because it is never called.
6459
a33565dd 6460 if Expander_Active then
2f06c88a 6461 B_F := Build_Barrier_Function (N, Ent, Prot);
ee6ba406 6462 Func := Barrier_Function (Ent);
6463 Set_Corresponding_Spec (B_F, Func);
6464
6465 Body_Decl := Parent (Corresponding_Body (Spec_Decl));
6466
6467 if Nkind (Parent (Body_Decl)) = N_Subunit then
6468 Body_Decl := Corresponding_Stub (Parent (Body_Decl));
6469 end if;
6470
6471 Insert_Before_And_Analyze (Body_Decl, B_F);
6472
f15731c4 6473 Set_Discriminals (Spec_Decl);
ee6ba406 6474 Set_Scope (Func, Scope (Prot));
9dfe12ae 6475
ee6ba406 6476 else
752e1833 6477 Analyze_And_Resolve (Cond, Any_Boolean);
ee6ba406 6478 end if;
6479
6432a7c1 6480 -- Check Pure_Barriers restriction
6481
6482 if Check_Pure_Barriers (Cond) = Abandon then
6483 Check_Restriction (Pure_Barriers, Cond);
6484 end if;
6485
76a1c25b 6486 -- The Ravenscar profile restricts barriers to simple variables declared
6487 -- within the protected object. We also allow Boolean constants, since
6488 -- these appear in several published examples and are also allowed by
10970cab 6489 -- other compilers.
ee6ba406 6490
76a1c25b 6491 -- Note that after analysis variables in this context will be replaced
6492 -- by the corresponding prival, that is to say a renaming of a selected
6493 -- component of the form _Object.Var. If expansion is disabled, as
6494 -- within a generic, we check that the entity appears in the current
6495 -- scope.
ee6ba406 6496
6497 if Is_Entity_Name (Cond) then
0d85cfbf 6498
6499 -- A small optimization of useless renamings. If the scope of the
6500 -- entity of the condition is not the barrier function, then the
6501 -- condition does not reference any of the generated renamings
6502 -- within the function.
6503
a33565dd 6504 if Expander_Active and then Scope (Entity (Cond)) /= Func then
0d85cfbf 6505 Set_Declarations (B_F, Empty_List);
6506 end if;
6507
ee6ba406 6508 if Entity (Cond) = Standard_False
6509 or else
6510 Entity (Cond) = Standard_True
6511 then
6512 return;
6513
6432a7c1 6514 elsif Is_Simple_Barrier_Name (Cond) then
ee6ba406 6515 return;
6516 end if;
6517 end if;
6518
a9f3e0f0 6519 -- It is not a boolean variable or literal, so check the restriction.
6520 -- Note that it is safe to be calling Check_Restriction from here, even
6521 -- though this is part of the expander, since Expand_Entry_Barrier is
6522 -- called from Sem_Ch9 even in -gnatc mode.
ee6ba406 6523
93735cb8 6524 Check_Restriction (Simple_Barriers, Cond);
a9f3e0f0 6525
6526 -- Emit warning if barrier contains global entities and is thus
6527 -- potentially unsynchronized.
6528
d3db6e37 6529 Check_Unprotected_Barrier (Cond);
ee6ba406 6530 end Expand_Entry_Barrier;
6531
ee6ba406 6532 ------------------------------
6533 -- Expand_N_Abort_Statement --
6534 ------------------------------
6535
6536 -- Expand abort T1, T2, .. Tn; into:
6537 -- Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
6538
6539 procedure Expand_N_Abort_Statement (N : Node_Id) is
6540 Loc : constant Source_Ptr := Sloc (N);
6541 Tlist : constant List_Id := Names (N);
6542 Count : Nat;
6543 Aggr : Node_Id;
6544 Tasknm : Node_Id;
6545
6546 begin
6547 Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
6548 Count := 0;
6549
6550 Tasknm := First (Tlist);
6551
6552 while Present (Tasknm) loop
6553 Count := Count + 1;
76a1c25b 6554
10970cab 6555 -- A task interface class-wide type object is being aborted. Retrieve
6556 -- its _task_id by calling a dispatching routine.
76a1c25b 6557
de54c5ab 6558 if Ada_Version >= Ada_2005
76a1c25b 6559 and then Ekind (Etype (Tasknm)) = E_Class_Wide_Type
4961db87 6560 and then Is_Interface (Etype (Tasknm))
76a1c25b 6561 and then Is_Task_Interface (Etype (Tasknm))
6562 then
6563 Append_To (Component_Associations (Aggr),
6564 Make_Component_Association (Loc,
85377c9b 6565 Choices => New_List (Make_Integer_Literal (Loc, Count)),
76a1c25b 6566 Expression =>
6567
4961db87 6568 -- Task_Id (Tasknm._disp_get_task_id)
76a1c25b 6569
4961db87 6570 Make_Unchecked_Type_Conversion (Loc,
6571 Subtype_Mark =>
83c6c069 6572 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
85377c9b 6573 Expression =>
4961db87 6574 Make_Selected_Component (Loc,
55868293 6575 Prefix => New_Copy_Tree (Tasknm),
4961db87 6576 Selector_Name =>
6577 Make_Identifier (Loc, Name_uDisp_Get_Task_Id)))));
76a1c25b 6578
6579 else
6580 Append_To (Component_Associations (Aggr),
6581 Make_Component_Association (Loc,
85377c9b 6582 Choices => New_List (Make_Integer_Literal (Loc, Count)),
76a1c25b 6583 Expression => Concurrent_Ref (Tasknm)));
6584 end if;
6585
ee6ba406 6586 Next (Tasknm);
6587 end loop;
6588
6589 Rewrite (N,
6590 Make_Procedure_Call_Statement (Loc,
83c6c069 6591 Name => New_Occurrence_Of (RTE (RE_Abort_Tasks), Loc),
ee6ba406 6592 Parameter_Associations => New_List (
6593 Make_Qualified_Expression (Loc,
83c6c069 6594 Subtype_Mark => New_Occurrence_Of (RTE (RE_Task_List), Loc),
85377c9b 6595 Expression => Aggr))));
ee6ba406 6596
6597 Analyze (N);
ee6ba406 6598 end Expand_N_Abort_Statement;
6599
6600 -------------------------------
6601 -- Expand_N_Accept_Statement --
6602 -------------------------------
6603
10970cab 6604 -- This procedure handles expansion of accept statements that stand alone,
6605 -- i.e. they are not part of an accept alternative. The expansion of
6606 -- accept statement in accept alternatives is handled by the routines
ee6ba406 6607 -- Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
6608 -- following description applies only to stand alone accept statements.
6609
10970cab 6610 -- If there is no handled statement sequence, or only null statements, then
6611 -- this is called a trivial accept, and the expansion is:
ee6ba406 6612
6613 -- Accept_Trivial (entry-index)
6614
6615 -- If there is a handled statement sequence, then the expansion is:
6616
6617 -- Ann : Address;
6618 -- {Lnn : Label}
6619
6620 -- begin
6621 -- begin
6622 -- Accept_Call (entry-index, Ann);
9dfe12ae 6623 -- Renaming_Declarations for formals
ee6ba406 6624 -- <statement sequence from N_Accept_Statement node>
6625 -- Complete_Rendezvous;
6626 -- <<Lnn>>
6627 --
6628 -- exception
6629 -- when ... =>
6630 -- <exception handler from N_Accept_Statement node>
6631 -- Complete_Rendezvous;
6632 -- when ... =>
6633 -- <exception handler from N_Accept_Statement node>
6634 -- Complete_Rendezvous;
6635 -- ...
6636 -- end;
6637
6638 -- exception
6639 -- when all others =>
6640 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
6641 -- end;
6642
76a1c25b 6643 -- The first three declarations were already inserted ahead of the accept
6644 -- statement by the Expand_Accept_Declarations procedure, which was called
36b938a3 6645 -- directly from the semantics during analysis of the accept statement,
76a1c25b 6646 -- before analyzing its contained statements.
ee6ba406 6647
6648 -- The declarations from the N_Accept_Statement, as noted in Sinfo, come
6649 -- from possible expansion activity (the original source of course does
6650 -- not have any declarations associated with the accept statement, since
6651 -- an accept statement has no declarative part). In particular, if the
6652 -- expander is active, the first such declaration is the declaration of
6653 -- the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
10970cab 6654
ee6ba406 6655 -- The two blocks are merged into a single block if the inner block has
6656 -- no exception handlers, but otherwise two blocks are required, since
6657 -- exceptions might be raised in the exception handlers of the inner
6658 -- block, and Exceptional_Complete_Rendezvous must be called.
6659
6660 procedure Expand_N_Accept_Statement (N : Node_Id) is
6661 Loc : constant Source_Ptr := Sloc (N);
6662 Stats : constant Node_Id := Handled_Statement_Sequence (N);
6663 Ename : constant Node_Id := Entry_Direct_Name (N);
6664 Eindx : constant Node_Id := Entry_Index (N);
6665 Eent : constant Entity_Id := Entity (Ename);
6666 Acstack : constant Elist_Id := Accept_Address (Eent);
6667 Ann : constant Entity_Id := Node (Last_Elmt (Acstack));
6668 Ttyp : constant Entity_Id := Etype (Scope (Eent));
9dfe12ae 6669 Blkent : Entity_Id;
ee6ba406 6670 Call : Node_Id;
6671 Block : Node_Id;
6672
ee6ba406 6673 begin
85377c9b 6674 -- If the accept statement is not part of a list, then its parent must
6675 -- be an accept alternative, and, as described above, we do not do any
ee6ba406 6676 -- expansion for such accept statements at this level.
6677
6678 if not Is_List_Member (N) then
6679 pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
6680 return;
6681
6682 -- Trivial accept case (no statement sequence, or null statements).
6683 -- If the accept statement has declarations, then just insert them
6684 -- before the procedure call.
6685
d333ad56 6686 elsif Trivial_Accept_OK
ee6ba406 6687 and then (No (Stats) or else Null_Statements (Statements (Stats)))
6688 then
9dfe12ae 6689 -- Remove declarations for renamings, because the parameter block
6690 -- will not be assigned.
6691
6692 declare
6693 D : Node_Id;
6694 Next_D : Node_Id;
6695
6696 begin
6697 D := First (Declarations (N));
9dfe12ae 6698 while Present (D) loop
6699 Next_D := Next (D);
6700 if Nkind (D) = N_Object_Renaming_Declaration then
6701 Remove (D);
6702 end if;
6703
6704 D := Next_D;
6705 end loop;
6706 end;
6707
ee6ba406 6708 if Present (Declarations (N)) then
6709 Insert_Actions (N, Declarations (N));
6710 end if;
6711
6712 Rewrite (N,
6713 Make_Procedure_Call_Statement (Loc,
83c6c069 6714 Name => New_Occurrence_Of (RTE (RE_Accept_Trivial), Loc),
ee6ba406 6715 Parameter_Associations => New_List (
6716 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
6717
6718 Analyze (N);
6719
6720 -- Discard Entry_Address that was created for it, so it will not be
6721 -- emitted if this accept statement is in the statement part of a
6722 -- delay alternative.
6723
6724 if Present (Stats) then
6725 Remove_Last_Elmt (Acstack);
6726 end if;
6727
6728 -- Case of statement sequence present
6729
6730 else
6731 -- Construct the block, using the declarations from the accept
6732 -- statement if any to initialize the declarations of the block.
6733
ec97ce79 6734 Blkent := Make_Temporary (Loc, 'A');
9dfe12ae 6735 Set_Ekind (Blkent, E_Block);
6736 Set_Etype (Blkent, Standard_Void_Type);
6737 Set_Scope (Blkent, Current_Scope);
6738
ee6ba406 6739 Block :=
6740 Make_Block_Statement (Loc,
83c6c069 6741 Identifier => New_Occurrence_Of (Blkent, Loc),
ee6ba406 6742 Declarations => Declarations (N),
6743 Handled_Statement_Sequence => Build_Accept_Body (N));
6744
daa209ae 6745 -- For the analysis of the generated declarations, the parent node
6746 -- must be properly set.
6747
6748 Set_Parent (Block, Parent (N));
6749
76a1c25b 6750 -- Prepend call to Accept_Call to main statement sequence If the
6751 -- accept has exception handlers, the statement sequence is wrapped
6752 -- in a block. Insert call and renaming declarations in the
6753 -- declarations of the block, so they are elaborated before the
6754 -- handlers.
ee6ba406 6755
6756 Call :=
6757 Make_Procedure_Call_Statement (Loc,
83c6c069 6758 Name => New_Occurrence_Of (RTE (RE_Accept_Call), Loc),
ee6ba406 6759 Parameter_Associations => New_List (
6760 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
83c6c069 6761 New_Occurrence_Of (Ann, Loc)));
ee6ba406 6762
9dfe12ae 6763 if Parent (Stats) = N then
6764 Prepend (Call, Statements (Stats));
6765 else
85377c9b 6766 Set_Declarations (Parent (Stats), New_List (Call));
9dfe12ae 6767 end if;
6768
ee6ba406 6769 Analyze (Call);
6770
4961db87 6771 Push_Scope (Blkent);
9dfe12ae 6772
6773 declare
6774 D : Node_Id;
6775 Next_D : Node_Id;
6776 Typ : Entity_Id;
76a1c25b 6777
9dfe12ae 6778 begin
6779 D := First (Declarations (N));
9dfe12ae 6780 while Present (D) loop
6781 Next_D := Next (D);
6782
6783 if Nkind (D) = N_Object_Renaming_Declaration then
76a1c25b 6784
6785 -- The renaming declarations for the formals were created
6786 -- during analysis of the accept statement, and attached to
6787 -- the list of declarations. Place them now in the context
6788 -- of the accept block or subprogram.
9dfe12ae 6789
6790 Remove (D);
6791 Typ := Entity (Subtype_Mark (D));
6792 Insert_After (Call, D);
6793 Analyze (D);
6794
76a1c25b 6795 -- If the formal is class_wide, it does not have an actual
6796 -- subtype. The analysis of the renaming declaration creates
6797 -- one, but we need to retain the class-wide nature of the
6798 -- entity.
9dfe12ae 6799
6800 if Is_Class_Wide_Type (Typ) then
6801 Set_Etype (Defining_Identifier (D), Typ);
6802 end if;
6803
6804 end if;
6805
6806 D := Next_D;
6807 end loop;
6808 end;
6809
6810 End_Scope;
6811
ee6ba406 6812 -- Replace the accept statement by the new block
6813
6814 Rewrite (N, Block);
6815 Analyze (N);
6816
6817 -- Last step is to unstack the Accept_Address value
6818
6819 Remove_Last_Elmt (Acstack);
6820 end if;
ee6ba406 6821 end Expand_N_Accept_Statement;
6822
6823 ----------------------------------
6824 -- Expand_N_Asynchronous_Select --
6825 ----------------------------------
6826
d62940bf 6827 -- This procedure assumes that the trigger statement is an entry call or
6828 -- a dispatching procedure call. A delay alternative should already have
6829 -- been expanded into an entry call to the appropriate delay object Wait
6830 -- entry.
ee6ba406 6831
2866d595 6832 -- If the trigger is a task entry call, the select is implemented with
6833 -- a Task_Entry_Call:
ee6ba406 6834
6835 -- declare
6836 -- B : Boolean;
6837 -- C : Boolean;
6838 -- P : parms := (parm, parm, parm);
9dfe12ae 6839
2866d595 6840 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
9dfe12ae 6841
ee6ba406 6842 -- procedure _clean is
6843 -- begin
6844 -- ...
6845 -- Cancel_Task_Entry_Call (C);
6846 -- ...
6847 -- end _clean;
9dfe12ae 6848
ee6ba406 6849 -- begin
6850 -- Abort_Defer;
6851 -- Task_Entry_Call
5809835d 6852 -- (<acceptor-task>, -- Acceptor
6853 -- <entry-index>, -- E
6854 -- P'Address, -- Uninterpreted_Data
6855 -- Asynchronous_Call, -- Mode
6856 -- B); -- Rendezvous_Successful
9dfe12ae 6857
ee6ba406 6858 -- begin
6859 -- begin
6860 -- Abort_Undefer;
d62940bf 6861 -- <abortable-part>
ee6ba406 6862 -- at end
5809835d 6863 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
ee6ba406 6864 -- end;
6865 -- exception
d62940bf 6866 -- when Abort_Signal => Abort_Undefer;
ee6ba406 6867 -- end;
d62940bf 6868
ee6ba406 6869 -- parm := P.param;
6870 -- parm := P.param;
6871 -- ...
6872 -- if not C then
d62940bf 6873 -- <triggered-statements>
ee6ba406 6874 -- end if;
6875 -- end;
6876
5809835d 6877 -- Note that Build_Simple_Entry_Call is used to expand the entry of the
6878 -- asynchronous entry call (by Expand_N_Entry_Call_Statement procedure)
6879 -- as follows:
ee6ba406 6880
6881 -- declare
6882 -- P : parms := (parm, parm, parm);
6883 -- begin
6884 -- Call_Simple (acceptor-task, entry-index, P'Address);
6885 -- parm := P.param;
6886 -- parm := P.param;
6887 -- ...
6888 -- end;
6889
6890 -- so the task at hand is to convert the latter expansion into the former
6891
5809835d 6892 -- If the trigger is a protected entry call, the select is implemented
6893 -- with Protected_Entry_Call:
ee6ba406 6894
6895 -- declare
6896 -- P : E1_Params := (param, param, param);
6897 -- Bnn : Communications_Block;
9dfe12ae 6898
ee6ba406 6899 -- begin
6900 -- declare
5809835d 6901
d333ad56 6902 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
5809835d 6903
ee6ba406 6904 -- procedure _clean is
6905 -- begin
6906 -- ...
6907 -- if Enqueued (Bnn) then
6908 -- Cancel_Protected_Entry_Call (Bnn);
6909 -- end if;
6910 -- ...
6911 -- end _clean;
9dfe12ae 6912
ee6ba406 6913 -- begin
6914 -- begin
5809835d 6915 -- Protected_Entry_Call
6916 -- (po._object'Access, -- Object
6917 -- <entry index>, -- E
6918 -- P'Address, -- Uninterpreted_Data
6919 -- Asynchronous_Call, -- Mode
6920 -- Bnn); -- Block
6921
ee6ba406 6922 -- if Enqueued (Bnn) then
d62940bf 6923 -- <abortable-part>
ee6ba406 6924 -- end if;
6925 -- at end
5809835d 6926 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
ee6ba406 6927 -- end;
6928 -- exception
d62940bf 6929 -- when Abort_Signal => Abort_Undefer;
ee6ba406 6930 -- end;
9dfe12ae 6931
ee6ba406 6932 -- if not Cancelled (Bnn) then
d62940bf 6933 -- <triggered-statements>
ee6ba406 6934 -- end if;
6935 -- end;
6936
5809835d 6937 -- Build_Simple_Entry_Call is used to expand the all to a simple protected
6938 -- entry call:
ee6ba406 6939
6940 -- declare
6941 -- P : E1_Params := (param, param, param);
6942 -- Bnn : Communications_Block;
6943
6944 -- begin
5809835d 6945 -- Protected_Entry_Call
6946 -- (po._object'Access, -- Object
6947 -- <entry index>, -- E
6948 -- P'Address, -- Uninterpreted_Data
6949 -- Simple_Call, -- Mode
6950 -- Bnn); -- Block
ee6ba406 6951 -- parm := P.param;
6952 -- parm := P.param;
6953 -- ...
6954 -- end;
6955
d62940bf 6956 -- Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
6957 -- expanded into:
6958
952af0b9 6959 -- declare
6960 -- B : Boolean := False;
6961 -- Bnn : Communication_Block;
6962 -- C : Ada.Tags.Prim_Op_Kind;
5809835d 6963 -- D : System.Storage_Elements.Dummy_Communication_Block;
952af0b9 6964 -- K : Ada.Tags.Tagged_Kind :=
6965 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
6966 -- P : Parameters := (Param1 .. ParamN);
6967 -- S : Integer;
6968 -- U : Boolean;
d62940bf 6969
952af0b9 6970 -- begin
37c6e44c 6971 -- if K = Ada.Tags.TK_Limited_Tagged
6972 -- or else K = Ada.Tags.TK_Tagged
6973 -- then
952af0b9 6974 -- <dispatching-call>;
6975 -- <triggering-statements>;
d62940bf 6976
952af0b9 6977 -- else
5809835d 6978 -- S :=
6979 -- Ada.Tags.Get_Offset_Index
6980 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
952af0b9 6981
6982 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
6983
6984 -- if C = POK_Protected_Entry then
6985 -- declare
6986 -- procedure _clean is
6987 -- begin
6988 -- if Enqueued (Bnn) then
6989 -- Cancel_Protected_Entry_Call (Bnn);
6990 -- end if;
6991 -- end _clean;
6992
6993 -- begin
6994 -- begin
6995 -- _Disp_Asynchronous_Select
5809835d 6996 -- (<object>, S, P'Address, D, B);
4961db87 6997 -- Bnn := Communication_Block (D);
952af0b9 6998
6999 -- Param1 := P.Param1;
7000 -- ...
7001 -- ParamN := P.ParamN;
7002
7003 -- if Enqueued (Bnn) then
7004 -- <abortable-statements>
7005 -- end if;
7006 -- at end
5809835d 7007 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
952af0b9 7008 -- end;
7009 -- exception
7010 -- when Abort_Signal => Abort_Undefer;
7011 -- end;
7012
7013 -- if not Cancelled (Bnn) then
7014 -- <triggering-statements>
7015 -- end if;
7016
7017 -- elsif C = POK_Task_Entry then
7018 -- declare
7019 -- procedure _clean is
7020 -- begin
7021 -- Cancel_Task_Entry_Call (U);
7022 -- end _clean;
7023
7024 -- begin
7025 -- Abort_Defer;
7026
7027 -- _Disp_Asynchronous_Select
5809835d 7028 -- (<object>, S, P'Address, D, B);
4961db87 7029 -- Bnn := Communication_Bloc (D);
952af0b9 7030
7031 -- Param1 := P.Param1;
7032 -- ...
7033 -- ParamN := P.ParamN;
7034
7035 -- begin
7036 -- begin
7037 -- Abort_Undefer;
7038 -- <abortable-statements>
7039 -- at end
5809835d 7040 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
952af0b9 7041 -- end;
7042 -- exception
7043 -- when Abort_Signal => Abort_Undefer;
7044 -- end;
7045
7046 -- if not U then
7047 -- <triggering-statements>
7048 -- end if;
7049 -- end;
7050
7051 -- else
7052 -- <dispatching-call>;
7053 -- <triggering-statements>
7054 -- end if;
7055 -- end if;
7056 -- end;
d62940bf 7057
2866d595 7058 -- The job is to convert this to the asynchronous form
ee6ba406 7059
10970cab 7060 -- If the trigger is a delay statement, it will have been expanded into
7061 -- a call to one of the GNARL delay procedures. This routine will convert
2866d595 7062 -- this into a protected entry call on a delay object and then continue
7063 -- processing as for a protected entry call trigger. This requires
7064 -- declaring a Delay_Block object and adding a pointer to this object to
7065 -- the parameter list of the delay procedure to form the parameter list of
7066 -- the entry call. This object is used by the runtime to queue the delay
7067 -- request.
ee6ba406 7068
5809835d 7069 -- For a description of the use of P and the assignments after the call,
7070 -- see Expand_N_Entry_Call_Statement.
ee6ba406 7071
7072 procedure Expand_N_Asynchronous_Select (N : Node_Id) is
0703c8dc 7073 Loc : constant Source_Ptr := Sloc (N);
7074 Abrt : constant Node_Id := Abortable_Part (N);
7075 Trig : constant Node_Id := Triggering_Alternative (N);
ee6ba406 7076
76a1c25b 7077 Abort_Block_Ent : Entity_Id;
7078 Abortable_Block : Node_Id;
7079 Actuals : List_Id;
0703c8dc 7080 Astats : List_Id;
e3cb8202 7081 Blk_Ent : constant Entity_Id := Make_Temporary (Loc, 'A');
76a1c25b 7082 Blk_Typ : Entity_Id;
7083 Call : Node_Id;
7084 Call_Ent : Entity_Id;
7085 Cancel_Param : Entity_Id;
7086 Cleanup_Block : Node_Id;
7087 Cleanup_Block_Ent : Entity_Id;
7088 Cleanup_Stmts : List_Id;
952af0b9 7089 Conc_Typ_Stmts : List_Id;
76a1c25b 7090 Concval : Node_Id;
7091 Dblock_Ent : Entity_Id;
7092 Decl : Node_Id;
7093 Decls : List_Id;
7094 Ecall : Node_Id;
7095 Ename : Node_Id;
7096 Enqueue_Call : Node_Id;
7097 Formals : List_Id;
7098 Hdle : List_Id;
9935a51f 7099 Handler_Stmt : Node_Id;
76a1c25b 7100 Index : Node_Id;
952af0b9 7101 Lim_Typ_Stmts : List_Id;
76a1c25b 7102 N_Orig : Node_Id;
7103 Obj : Entity_Id;
7104 Param : Node_Id;
7105 Params : List_Id;
7106 Pdef : Entity_Id;
7107 ProtE_Stmts : List_Id;
7108 ProtP_Stmts : List_Id;
7109 Stmt : Node_Id;
7110 Stmts : List_Id;
76a1c25b 7111 TaskE_Stmts : List_Id;
0703c8dc 7112 Tstats : List_Id;
ee6ba406 7113
d62940bf 7114 B : Entity_Id; -- Call status flag
7115 Bnn : Entity_Id; -- Communication block
7116 C : Entity_Id; -- Call kind
952af0b9 7117 K : Entity_Id; -- Tagged kind
76a1c25b 7118 P : Entity_Id; -- Parameter block
d62940bf 7119 S : Entity_Id; -- Primitive operation slot
76a1c25b 7120 T : Entity_Id; -- Additional status flag
d62940bf 7121
ab638c49 7122 procedure Rewrite_Abortable_Part;
7123 -- If the trigger is a dispatching call, the expansion inserts multiple
7124 -- copies of the abortable part. This is both inefficient, and may lead
7125 -- to duplicate definitions that the back-end will reject, when the
7126 -- abortable part includes loops. This procedure rewrites the abortable
7127 -- part into a call to a generated procedure.
7128
7129 ----------------------------
7130 -- Rewrite_Abortable_Part --
7131 ----------------------------
7132
7133 procedure Rewrite_Abortable_Part is
7134 Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
7135 Decl : Node_Id;
7136
7137 begin
7138 Decl :=
7139 Make_Subprogram_Body (Loc,
7140 Specification =>
7141 Make_Procedure_Specification (Loc, Defining_Unit_Name => Proc),
7142 Declarations => New_List,
7143 Handled_Statement_Sequence =>
7144 Make_Handled_Sequence_Of_Statements (Loc, Astats));
7145 Insert_Before (N, Decl);
7146 Analyze (Decl);
7147
7148 -- Rewrite abortable part into a call to this procedure.
7149
7150 Astats :=
7151 New_List (
7152 Make_Procedure_Call_Statement (Loc,
7153 Name => New_Occurrence_Of (Proc, Loc)));
7154 end Rewrite_Abortable_Part;
7155
ee6ba406 7156 begin
f239f5be 7157 Process_Statements_For_Controlled_Objects (Trig);
7158 Process_Statements_For_Controlled_Objects (Abrt);
7159
e3cb8202 7160 Ecall := Triggering_Statement (Trig);
7161
7162 Ensure_Statement_Present (Sloc (Ecall), Trig);
7163
0703c8dc 7164 -- Retrieve Astats and Tstats now because the finalization machinery may
7165 -- wrap them in blocks.
7166
7167 Astats := Statements (Abrt);
7168 Tstats := Statements (Trig);
7169
ee6ba406 7170 -- The arguments in the call may require dynamic allocation, and the
7171 -- call statement may have been transformed into a block. The block
7172 -- may contain additional declarations for internal entities, and the
7173 -- original call is found by sequential search.
7174
7175 if Nkind (Ecall) = N_Block_Statement then
7176 Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
5809835d 7177 while not Nkind_In (Ecall, N_Procedure_Call_Statement,
7178 N_Entry_Call_Statement)
ee6ba406 7179 loop
7180 Next (Ecall);
7181 end loop;
7182 end if;
7183
d62940bf 7184 -- This is either a dispatching call or a delay statement used as a
7185 -- trigger which was expanded into a procedure call.
ee6ba406 7186
7187 if Nkind (Ecall) = N_Procedure_Call_Statement then
de54c5ab 7188 if Ada_Version >= Ada_2005
d62940bf 7189 and then
357dd91a 7190 (No (Original_Node (Ecall))
ab638c49 7191 or else not Nkind_In (Original_Node (Ecall),
7192 N_Delay_Relative_Statement,
7193 N_Delay_Until_Statement))
d62940bf 7194 then
7195 Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
ee6ba406 7196
ab638c49 7197 Rewrite_Abortable_Part;
d62940bf 7198 Decls := New_List;
7199 Stmts := New_List;
ee6ba406 7200
d62940bf 7201 -- Call status flag processing, generate:
7202 -- B : Boolean := False;
ee6ba406 7203
952af0b9 7204 B := Build_B (Loc, Decls);
ee6ba406 7205
d62940bf 7206 -- Communication block processing, generate:
7207 -- Bnn : Communication_Block;
ee6ba406 7208
ec97ce79 7209 Bnn := Make_Temporary (Loc, 'B');
d62940bf 7210 Append_To (Decls,
7211 Make_Object_Declaration (Loc,
ec97ce79 7212 Defining_Identifier => Bnn,
7213 Object_Definition =>
83c6c069 7214 New_Occurrence_Of (RTE (RE_Communication_Block), Loc)));
ee6ba406 7215
d62940bf 7216 -- Call kind processing, generate:
7217 -- C : Ada.Tags.Prim_Op_Kind;
ee6ba406 7218
952af0b9 7219 C := Build_C (Loc, Decls);
7220
7221 -- Tagged kind processing, generate:
7222 -- K : Ada.Tags.Tagged_Kind :=
7223 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7224
4961db87 7225 -- Dummy communication block, generate:
7226 -- D : Dummy_Communication_Block;
7227
7228 Append_To (Decls,
7229 Make_Object_Declaration (Loc,
7230 Defining_Identifier =>
7231 Make_Defining_Identifier (Loc, Name_uD),
ab638c49 7232 Object_Definition =>
83c6c069 7233 New_Occurrence_Of
ab638c49 7234 (RTE (RE_Dummy_Communication_Block), Loc)));
4961db87 7235
952af0b9 7236 K := Build_K (Loc, Decls, Obj);
ee6ba406 7237
d62940bf 7238 -- Parameter block processing
ee6ba406 7239
d62940bf 7240 Blk_Typ := Build_Parameter_Block
7241 (Loc, Actuals, Formals, Decls);
7242 P := Parameter_Block_Pack
7243 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
ee6ba406 7244
d62940bf 7245 -- Dispatch table slot processing, generate:
952af0b9 7246 -- S : Integer;
ee6ba406 7247
952af0b9 7248 S := Build_S (Loc, Decls);
ee6ba406 7249
d62940bf 7250 -- Additional status flag processing, generate:
ec97ce79 7251 -- Tnn : Boolean;
ee6ba406 7252
ec97ce79 7253 T := Make_Temporary (Loc, 'T');
d62940bf 7254 Append_To (Decls,
7255 Make_Object_Declaration (Loc,
ec97ce79 7256 Defining_Identifier => T,
7257 Object_Definition =>
83c6c069 7258 New_Occurrence_Of (Standard_Boolean, Loc)));
ee6ba406 7259
5809835d 7260 ------------------------------
7261 -- Protected entry handling --
7262 ------------------------------
d62940bf 7263
7264 -- Generate:
7265 -- Param1 := P.Param1;
7266 -- ...
7267 -- ParamN := P.ParamN;
7268
76a1c25b 7269 Cleanup_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
d62940bf 7270
7271 -- Generate:
4961db87 7272 -- Bnn := Communication_Block (D);
7273
7274 Prepend_To (Cleanup_Stmts,
7275 Make_Assignment_Statement (Loc,
83c6c069 7276 Name => New_Occurrence_Of (Bnn, Loc),
4961db87 7277 Expression =>
7278 Make_Unchecked_Type_Conversion (Loc,
7279 Subtype_Mark =>
83c6c069 7280 New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
55868293 7281 Expression => Make_Identifier (Loc, Name_uD))));
4961db87 7282
7283 -- Generate:
5809835d 7284 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
d62940bf 7285
7286 Prepend_To (Cleanup_Stmts,
7287 Make_Procedure_Call_Statement (Loc,
7288 Name =>
83c6c069 7289 New_Occurrence_Of
ab638c49 7290 (Find_Prim_Op
7291 (Etype (Etype (Obj)), Name_uDisp_Asynchronous_Select),
7292 Loc),
d62940bf 7293 Parameter_Associations =>
7294 New_List (
5809835d 7295 New_Copy_Tree (Obj), -- <object>
83c6c069 7296 New_Occurrence_Of (S, Loc), -- S
5809835d 7297 Make_Attribute_Reference (Loc, -- P'Address
83c6c069 7298 Prefix => New_Occurrence_Of (P, Loc),
85377c9b 7299 Attribute_Name => Name_Address),
5809835d 7300 Make_Identifier (Loc, Name_uD), -- D
83c6c069 7301 New_Occurrence_Of (B, Loc)))); -- B
d62940bf 7302
7303 -- Generate:
7304 -- if Enqueued (Bnn) then
76a1c25b 7305 -- <abortable-statements>
d62940bf 7306 -- end if;
7307
d62940bf 7308 Append_To (Cleanup_Stmts,
85377c9b 7309 Make_Implicit_If_Statement (N,
d62940bf 7310 Condition =>
7311 Make_Function_Call (Loc,
7312 Name =>
83c6c069 7313 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
d62940bf 7314 Parameter_Associations =>
83c6c069 7315 New_List (New_Occurrence_Of (Bnn, Loc))),
d62940bf 7316
7317 Then_Statements =>
76a1c25b 7318 New_Copy_List_Tree (Astats)));
d62940bf 7319
7320 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7321 -- will then generate a _clean for the communication block Bnn.
7322
7323 -- Generate:
7324 -- declare
7325 -- procedure _clean is
7326 -- begin
7327 -- if Enqueued (Bnn) then
7328 -- Cancel_Protected_Entry_Call (Bnn);
7329 -- end if;
7330 -- end _clean;
7331 -- begin
7332 -- Cleanup_Stmts
7333 -- at end
7334 -- _clean;
7335 -- end;
7336
ec97ce79 7337 Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
952af0b9 7338 Cleanup_Block :=
7339 Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, Bnn);
d62940bf 7340
76a1c25b 7341 -- Wrap the cleanup block in an exception handling block
d62940bf 7342
7343 -- Generate:
7344 -- begin
7345 -- Cleanup_Block
7346 -- exception
7347 -- when Abort_Signal => Abort_Undefer;
7348 -- end;
7349
ec97ce79 7350 Abort_Block_Ent := Make_Temporary (Loc, 'A');
d62940bf 7351 ProtE_Stmts :=
7352 New_List (
76a1c25b 7353 Make_Implicit_Label_Declaration (Loc,
85377c9b 7354 Defining_Identifier => Abort_Block_Ent),
76a1c25b 7355
952af0b9 7356 Build_Abort_Block
7357 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
d62940bf 7358
7359 -- Generate:
7360 -- if not Cancelled (Bnn) then
76a1c25b 7361 -- <triggering-statements>
d62940bf 7362 -- end if;
7363
d62940bf 7364 Append_To (ProtE_Stmts,
85377c9b 7365 Make_Implicit_If_Statement (N,
d62940bf 7366 Condition =>
7367 Make_Op_Not (Loc,
7368 Right_Opnd =>
7369 Make_Function_Call (Loc,
7370 Name =>
83c6c069 7371 New_Occurrence_Of (RTE (RE_Cancelled), Loc),
d62940bf 7372 Parameter_Associations =>
83c6c069 7373 New_List (New_Occurrence_Of (Bnn, Loc)))),
d62940bf 7374
7375 Then_Statements =>
76a1c25b 7376 New_Copy_List_Tree (Tstats)));
d62940bf 7377
5809835d 7378 -------------------------
7379 -- Task entry handling --
7380 -------------------------
d62940bf 7381
7382 -- Generate:
7383 -- Param1 := P.Param1;
7384 -- ...
7385 -- ParamN := P.ParamN;
7386
76a1c25b 7387 TaskE_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
d62940bf 7388
7389 -- Generate:
4961db87 7390 -- Bnn := Communication_Block (D);
7391
7392 Append_To (TaskE_Stmts,
7393 Make_Assignment_Statement (Loc,
7394 Name =>
83c6c069 7395 New_Occurrence_Of (Bnn, Loc),
4961db87 7396 Expression =>
7397 Make_Unchecked_Type_Conversion (Loc,
7398 Subtype_Mark =>
83c6c069 7399 New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
55868293 7400 Expression => Make_Identifier (Loc, Name_uD))));
4961db87 7401
7402 -- Generate:
5809835d 7403 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
d62940bf 7404
7405 Prepend_To (TaskE_Stmts,
7406 Make_Procedure_Call_Statement (Loc,
7407 Name =>
83c6c069 7408 New_Occurrence_Of (
76a1c25b 7409 Find_Prim_Op (Etype (Etype (Obj)),
7410 Name_uDisp_Asynchronous_Select),
952af0b9 7411 Loc),
85377c9b 7412
d62940bf 7413 Parameter_Associations =>
7414 New_List (
5809835d 7415 New_Copy_Tree (Obj), -- <object>
83c6c069 7416 New_Occurrence_Of (S, Loc), -- S
5809835d 7417 Make_Attribute_Reference (Loc, -- P'Address
83c6c069 7418 Prefix => New_Occurrence_Of (P, Loc),
85377c9b 7419 Attribute_Name => Name_Address),
5809835d 7420 Make_Identifier (Loc, Name_uD), -- D
83c6c069 7421 New_Occurrence_Of (B, Loc)))); -- B
d62940bf 7422
7423 -- Generate:
7424 -- Abort_Defer;
7425
7426 Prepend_To (TaskE_Stmts,
7427 Make_Procedure_Call_Statement (Loc,
83c6c069 7428 Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
85377c9b 7429 Parameter_Associations => No_List));
d62940bf 7430
7431 -- Generate:
7432 -- Abort_Undefer;
76a1c25b 7433 -- <abortable-statements>
d62940bf 7434
76a1c25b 7435 Cleanup_Stmts := New_Copy_List_Tree (Astats);
d62940bf 7436
76a1c25b 7437 Prepend_To (Cleanup_Stmts,
7438 Make_Procedure_Call_Statement (Loc,
83c6c069 7439 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
85377c9b 7440 Parameter_Associations => No_List));
d62940bf 7441
7442 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7443 -- will generate a _clean for the additional status flag.
7444
7445 -- Generate:
7446 -- declare
7447 -- procedure _clean is
7448 -- begin
7449 -- Cancel_Task_Entry_Call (U);
7450 -- end _clean;
7451 -- begin
7452 -- Cleanup_Stmts
7453 -- at end
7454 -- _clean;
7455 -- end;
7456
ec97ce79 7457 Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
952af0b9 7458 Cleanup_Block :=
7459 Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, T);
d62940bf 7460
7461 -- Wrap the cleanup block in an exception handling block
7462
7463 -- Generate:
7464 -- begin
7465 -- Cleanup_Block
7466 -- exception
7467 -- when Abort_Signal => Abort_Undefer;
7468 -- end;
7469
ec97ce79 7470 Abort_Block_Ent := Make_Temporary (Loc, 'A');
76a1c25b 7471
d62940bf 7472 Append_To (TaskE_Stmts,
76a1c25b 7473 Make_Implicit_Label_Declaration (Loc,
ec97ce79 7474 Defining_Identifier => Abort_Block_Ent));
76a1c25b 7475
7476 Append_To (TaskE_Stmts,
952af0b9 7477 Build_Abort_Block
7478 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
d62940bf 7479
7480 -- Generate:
76a1c25b 7481 -- if not T then
7482 -- <triggering-statements>
d62940bf 7483 -- end if;
7484
d62940bf 7485 Append_To (TaskE_Stmts,
85377c9b 7486 Make_Implicit_If_Statement (N,
d62940bf 7487 Condition =>
83c6c069 7488 Make_Op_Not (Loc, Right_Opnd => New_Occurrence_Of (T, Loc)),
76a1c25b 7489
d62940bf 7490 Then_Statements =>
76a1c25b 7491 New_Copy_List_Tree (Tstats)));
d62940bf 7492
5809835d 7493 ----------------------------------
7494 -- Protected procedure handling --
7495 ----------------------------------
d62940bf 7496
7497 -- Generate:
7498 -- <dispatching-call>;
76a1c25b 7499 -- <triggering-statements>
d62940bf 7500
76a1c25b 7501 ProtP_Stmts := New_Copy_List_Tree (Tstats);
7502 Prepend_To (ProtP_Stmts, New_Copy_Tree (Ecall));
d62940bf 7503
952af0b9 7504 -- Generate:
5809835d 7505 -- S := Ada.Tags.Get_Offset_Index
7506 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
952af0b9 7507
5809835d 7508 Conc_Typ_Stmts :=
7509 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
952af0b9 7510
7511 -- Generate:
7512 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
7513
7514 Append_To (Conc_Typ_Stmts,
7515 Make_Procedure_Call_Statement (Loc,
7516 Name =>
83c6c069 7517 New_Occurrence_Of
ab638c49 7518 (Find_Prim_Op (Etype (Etype (Obj)),
7519 Name_uDisp_Get_Prim_Op_Kind),
7520 Loc),
952af0b9 7521 Parameter_Associations =>
7522 New_List (
5809835d 7523 New_Copy_Tree (Obj),
83c6c069 7524 New_Occurrence_Of (S, Loc),
7525 New_Occurrence_Of (C, Loc))));
952af0b9 7526
d62940bf 7527 -- Generate:
7528 -- if C = POK_Procedure_Entry then
7529 -- ProtE_Stmts
7530 -- elsif C = POK_Task_Entry then
7531 -- TaskE_Stmts
7532 -- else
7533 -- ProtP_Stmts
7534 -- end if;
7535
952af0b9 7536 Append_To (Conc_Typ_Stmts,
85377c9b 7537 Make_Implicit_If_Statement (N,
d62940bf 7538 Condition =>
7539 Make_Op_Eq (Loc,
85377c9b 7540 Left_Opnd =>
83c6c069 7541 New_Occurrence_Of (C, Loc),
d62940bf 7542 Right_Opnd =>
83c6c069 7543 New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
d62940bf 7544
7545 Then_Statements =>
7546 ProtE_Stmts,
7547
7548 Elsif_Parts =>
7549 New_List (
7550 Make_Elsif_Part (Loc,
7551 Condition =>
7552 Make_Op_Eq (Loc,
85377c9b 7553 Left_Opnd =>
83c6c069 7554 New_Occurrence_Of (C, Loc),
d62940bf 7555 Right_Opnd =>
83c6c069 7556 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc)),
76a1c25b 7557
d62940bf 7558 Then_Statements =>
7559 TaskE_Stmts)),
7560
7561 Else_Statements =>
7562 ProtP_Stmts));
7563
952af0b9 7564 -- Generate:
7565 -- <dispatching-call>;
7566 -- <triggering-statements>
7567
7568 Lim_Typ_Stmts := New_Copy_List_Tree (Tstats);
7569 Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Ecall));
7570
7571 -- Generate:
37c6e44c 7572 -- if K = Ada.Tags.TK_Limited_Tagged
7573 -- or else K = Ada.Tags.TK_Tagged
7574 -- then
952af0b9 7575 -- Lim_Typ_Stmts
7576 -- else
7577 -- Conc_Typ_Stmts
7578 -- end if;
7579
7580 Append_To (Stmts,
85377c9b 7581 Make_Implicit_If_Statement (N,
37c6e44c 7582 Condition => Build_Dispatching_Tag_Check (K, N),
7583 Then_Statements => Lim_Typ_Stmts,
7584 Else_Statements => Conc_Typ_Stmts));
952af0b9 7585
d62940bf 7586 Rewrite (N,
7587 Make_Block_Statement (Loc,
7588 Declarations =>
7589 Decls,
7590 Handled_Statement_Sequence =>
7591 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7592
7593 Analyze (N);
7594 return;
7595
7596 -- Delay triggering statement processing
7597
7598 else
7599 -- Add a Delay_Block object to the parameter list of the delay
7600 -- procedure to form the parameter list of the Wait entry call.
7601
ec97ce79 7602 Dblock_Ent := Make_Temporary (Loc, 'D');
d62940bf 7603
7604 Pdef := Entity (Name (Ecall));
7605
7606 if Is_RTE (Pdef, RO_CA_Delay_For) then
7607 Enqueue_Call :=
83c6c069 7608 New_Occurrence_Of (RTE (RE_Enqueue_Duration), Loc);
d62940bf 7609
7610 elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
7611 Enqueue_Call :=
83c6c069 7612 New_Occurrence_Of (RTE (RE_Enqueue_Calendar), Loc);
d62940bf 7613
7614 else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
83c6c069 7615 Enqueue_Call := New_Occurrence_Of (RTE (RE_Enqueue_RT), Loc);
d62940bf 7616 end if;
7617
7618 Append_To (Parameter_Associations (Ecall),
7619 Make_Attribute_Reference (Loc,
83c6c069 7620 Prefix => New_Occurrence_Of (Dblock_Ent, Loc),
d62940bf 7621 Attribute_Name => Name_Unchecked_Access));
7622
7623 -- Create the inner block to protect the abortable part
7624
9935a51f 7625 Hdle := New_List (Build_Abort_Block_Handler (Loc));
d62940bf 7626
7627 Prepend_To (Astats,
7628 Make_Procedure_Call_Statement (Loc,
83c6c069 7629 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc)));
d62940bf 7630
7631 Abortable_Block :=
7632 Make_Block_Statement (Loc,
83c6c069 7633 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
d62940bf 7634 Handled_Statement_Sequence =>
7635 Make_Handled_Sequence_Of_Statements (Loc,
7636 Statements => Astats),
ab638c49 7637 Has_Created_Identifier => True,
d62940bf 7638 Is_Asynchronous_Call_Block => True);
7639
7640 -- Append call to if Enqueue (When, DB'Unchecked_Access) then
7641
7642 Rewrite (Ecall,
7643 Make_Implicit_If_Statement (N,
85377c9b 7644 Condition =>
7645 Make_Function_Call (Loc,
7646 Name => Enqueue_Call,
7647 Parameter_Associations => Parameter_Associations (Ecall)),
d62940bf 7648 Then_Statements =>
7649 New_List (Make_Block_Statement (Loc,
7650 Handled_Statement_Sequence =>
7651 Make_Handled_Sequence_Of_Statements (Loc,
7652 Statements => New_List (
7653 Make_Implicit_Label_Declaration (Loc,
7654 Defining_Identifier => Blk_Ent,
7655 Label_Construct => Abortable_Block),
7656 Abortable_Block),
7657 Exception_Handlers => Hdle)))));
7658
7659 Stmts := New_List (Ecall);
7660
7661 -- Construct statement sequence for new block
7662
7663 Append_To (Stmts,
7664 Make_Implicit_If_Statement (N,
85377c9b 7665 Condition =>
7666 Make_Function_Call (Loc,
83c6c069 7667 Name => New_Occurrence_Of (
85377c9b 7668 RTE (RE_Timed_Out), Loc),
7669 Parameter_Associations => New_List (
7670 Make_Attribute_Reference (Loc,
83c6c069 7671 Prefix => New_Occurrence_Of (Dblock_Ent, Loc),
85377c9b 7672 Attribute_Name => Name_Unchecked_Access))),
d62940bf 7673 Then_Statements => Tstats));
7674
7675 -- The result is the new block
ee6ba406 7676
d62940bf 7677 Set_Entry_Cancel_Parameter (Blk_Ent, Dblock_Ent);
7678
7679 Rewrite (N,
7680 Make_Block_Statement (Loc,
7681 Declarations => New_List (
7682 Make_Object_Declaration (Loc,
7683 Defining_Identifier => Dblock_Ent,
85377c9b 7684 Aliased_Present => True,
ab638c49 7685 Object_Definition =>
83c6c069 7686 New_Occurrence_Of (RTE (RE_Delay_Block), Loc))),
d62940bf 7687
7688 Handled_Statement_Sequence =>
7689 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7690
7691 Analyze (N);
7692 return;
7693 end if;
76a1c25b 7694
ee6ba406 7695 else
7696 N_Orig := N;
7697 end if;
7698
7699 Extract_Entry (Ecall, Concval, Ename, Index);
7700 Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
7701
7702 Stmts := Statements (Handled_Statement_Sequence (Ecall));
7703 Decls := Declarations (Ecall);
7704
7705 if Is_Protected_Type (Etype (Concval)) then
7706
7707 -- Get the declarations of the block expanded from the entry call
7708
7709 Decl := First (Decls);
7710 while Present (Decl)
ab638c49 7711 and then (Nkind (Decl) /= N_Object_Declaration
7712 or else not Is_RTE (Etype (Object_Definition (Decl)),
7713 RE_Communication_Block))
ee6ba406 7714 loop
7715 Next (Decl);
7716 end loop;
7717
7718 pragma Assert (Present (Decl));
7719 Cancel_Param := Defining_Identifier (Decl);
7720
d62940bf 7721 -- Change the mode of the Protected_Entry_Call call
7722
ee6ba406 7723 -- Protected_Entry_Call (
7724 -- Object => po._object'Access,
7725 -- E => <entry index>;
7726 -- Uninterpreted_Data => P'Address;
7727 -- Mode => Asynchronous_Call;
7728 -- Block => Bnn);
7729
d62940bf 7730 -- Skip assignments to temporaries created for in-out parameters
7731
ee6ba406 7732 -- This makes unwarranted assumptions about the shape of the expanded
7733 -- tree for the call, and should be cleaned up ???
7734
ab638c49 7735 Stmt := First (Stmts);
ee6ba406 7736 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7737 Next (Stmt);
7738 end loop;
7739
7740 Call := Stmt;
7741
d62940bf 7742 Param := First (Parameter_Associations (Call));
7743 while Present (Param)
7744 and then not Is_RTE (Etype (Param), RE_Call_Modes)
ee6ba406 7745 loop
d62940bf 7746 Next (Param);
ee6ba406 7747 end loop;
7748
d62940bf 7749 pragma Assert (Present (Param));
83c6c069 7750 Rewrite (Param, New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
d62940bf 7751 Analyze (Param);
ee6ba406 7752
d62940bf 7753 -- Append an if statement to execute the abortable part
7754
7755 -- Generate:
7756 -- if Enqueued (Bnn) then
ee6ba406 7757
7758 Append_To (Stmts,
7759 Make_Implicit_If_Statement (N,
85377c9b 7760 Condition =>
7761 Make_Function_Call (Loc,
83c6c069 7762 Name => New_Occurrence_Of (RTE (RE_Enqueued), Loc),
85377c9b 7763 Parameter_Associations => New_List (
83c6c069 7764 New_Occurrence_Of (Cancel_Param, Loc))),
ee6ba406 7765 Then_Statements => Astats));
7766
7767 Abortable_Block :=
7768 Make_Block_Statement (Loc,
83c6c069 7769 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
ee6ba406 7770 Handled_Statement_Sequence =>
85377c9b 7771 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts),
ee6ba406 7772 Has_Created_Identifier => True,
7773 Is_Asynchronous_Call_Block => True);
7774
36ac5fbb 7775 if Exception_Mechanism = Back_End_Exceptions then
d03bfaa1 7776
36ac5fbb 7777 -- Aborts are not deferred at beginning of exception handlers
7778 -- in ZCX.
d03bfaa1 7779
36ac5fbb 7780 Handler_Stmt := Make_Null_Statement (Loc);
d03bfaa1 7781
4961db87 7782 else
9935a51f 7783 Handler_Stmt := Make_Procedure_Call_Statement (Loc,
36ac5fbb 7784 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
7785 Parameter_Associations => No_List);
ee6ba406 7786 end if;
7787
7788 Stmts := New_List (
7789 Make_Block_Statement (Loc,
7790 Handled_Statement_Sequence =>
7791 Make_Handled_Sequence_Of_Statements (Loc,
7792 Statements => New_List (
7793 Make_Implicit_Label_Declaration (Loc,
d62940bf 7794 Defining_Identifier => Blk_Ent,
ee6ba406 7795 Label_Construct => Abortable_Block),
7796 Abortable_Block),
7797
7798 -- exception
7799
7800 Exception_Handlers => New_List (
cb5f80c1 7801 Make_Implicit_Exception_Handler (Loc,
ee6ba406 7802
7803 -- when Abort_Signal =>
7804 -- Abort_Undefer.all;
7805
7806 Exception_Choices =>
83c6c069 7807 New_List (New_Occurrence_Of (Stand.Abort_Signal, Loc)),
9935a51f 7808 Statements => New_List (Handler_Stmt))))),
ee6ba406 7809
7810 -- if not Cancelled (Bnn) then
7811 -- triggered statements
7812 -- end if;
7813
7814 Make_Implicit_If_Statement (N,
7815 Condition => Make_Op_Not (Loc,
7816 Right_Opnd =>
7817 Make_Function_Call (Loc,
7818 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
7819 Parameter_Associations => New_List (
7820 New_Occurrence_Of (Cancel_Param, Loc)))),
7821 Then_Statements => Tstats));
7822
7823 -- Asynchronous task entry call
7824
7825 else
7826 if No (Decls) then
7827 Decls := New_List;
7828 end if;
7829
7830 B := Make_Defining_Identifier (Loc, Name_uB);
7831
7832 -- Insert declaration of B in declarations of existing block
7833
7834 Prepend_To (Decls,
7835 Make_Object_Declaration (Loc,
7836 Defining_Identifier => B,
83c6c069 7837 Object_Definition =>
7838 New_Occurrence_Of (Standard_Boolean, Loc)));
ee6ba406 7839
7840 Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
7841
7842 -- Insert declaration of C in declarations of existing block
7843
7844 Prepend_To (Decls,
7845 Make_Object_Declaration (Loc,
7846 Defining_Identifier => Cancel_Param,
83c6c069 7847 Object_Definition =>
7848 New_Occurrence_Of (Standard_Boolean, Loc)));
ee6ba406 7849
2866d595 7850 -- Remove and save the call to Call_Simple
ee6ba406 7851
7852 Stmt := First (Stmts);
7853
7854 -- Skip assignments to temporaries created for in-out parameters.
7855 -- This makes unwarranted assumptions about the shape of the expanded
7856 -- tree for the call, and should be cleaned up ???
7857
7858 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7859 Next (Stmt);
7860 end loop;
7861
7862 Call := Stmt;
7863
2866d595 7864 -- Create the inner block to protect the abortable part
ee6ba406 7865
ab8a61d0 7866 Hdle := New_List (Build_Abort_Block_Handler (Loc));
ee6ba406 7867
7868 Prepend_To (Astats,
7869 Make_Procedure_Call_Statement (Loc,
83c6c069 7870 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc)));
ee6ba406 7871
7872 Abortable_Block :=
7873 Make_Block_Statement (Loc,
83c6c069 7874 Identifier => New_Occurrence_Of (Blk_Ent, Loc),
ee6ba406 7875 Handled_Statement_Sequence =>
85377c9b 7876 Make_Handled_Sequence_Of_Statements (Loc, Statements => Astats),
7877 Has_Created_Identifier => True,
ee6ba406 7878 Is_Asynchronous_Call_Block => True);
7879
7880 Insert_After (Call,
7881 Make_Block_Statement (Loc,
7882 Handled_Statement_Sequence =>
7883 Make_Handled_Sequence_Of_Statements (Loc,
7884 Statements => New_List (
7885 Make_Implicit_Label_Declaration (Loc,
85377c9b 7886 Defining_Identifier => Blk_Ent,
7887 Label_Construct => Abortable_Block),
ee6ba406 7888 Abortable_Block),
7889 Exception_Handlers => Hdle)));
7890
7891 -- Create new call statement
7892
d62940bf 7893 Params := Parameter_Associations (Call);
7894
7895 Append_To (Params,
83c6c069 7896 New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
7897 Append_To (Params, New_Occurrence_Of (B, Loc));
d62940bf 7898
ee6ba406 7899 Rewrite (Call,
7900 Make_Procedure_Call_Statement (Loc,
83c6c069 7901 Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
d62940bf 7902 Parameter_Associations => Params));
ee6ba406 7903
7904 -- Construct statement sequence for new block
7905
7906 Append_To (Stmts,
7907 Make_Implicit_If_Statement (N,
d62940bf 7908 Condition =>
83c6c069 7909 Make_Op_Not (Loc, New_Occurrence_Of (Cancel_Param, Loc)),
ee6ba406 7910 Then_Statements => Tstats));
7911
4660e715 7912 -- Protected the call against abort
ee6ba406 7913
7914 Prepend_To (Stmts,
7915 Make_Procedure_Call_Statement (Loc,
83c6c069 7916 Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
ee6ba406 7917 Parameter_Associations => Empty_List));
7918 end if;
7919
d62940bf 7920 Set_Entry_Cancel_Parameter (Blk_Ent, Cancel_Param);
ee6ba406 7921
7922 -- The result is the new block
7923
7924 Rewrite (N_Orig,
7925 Make_Block_Statement (Loc,
7926 Declarations => Decls,
7927 Handled_Statement_Sequence =>
7928 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7929
7930 Analyze (N_Orig);
ee6ba406 7931 end Expand_N_Asynchronous_Select;
7932
7933 -------------------------------------
7934 -- Expand_N_Conditional_Entry_Call --
7935 -------------------------------------
7936
7937 -- The conditional task entry call is converted to a call to
7938 -- Task_Entry_Call:
7939
7940 -- declare
7941 -- B : Boolean;
7942 -- P : parms := (parm, parm, parm);
7943
7944 -- begin
7945 -- Task_Entry_Call
5809835d 7946 -- (<acceptor-task>, -- Acceptor
7947 -- <entry-index>, -- E
7948 -- P'Address, -- Uninterpreted_Data
7949 -- Conditional_Call, -- Mode
7950 -- B); -- Rendezvous_Successful
ee6ba406 7951 -- parm := P.param;
7952 -- parm := P.param;
7953 -- ...
7954 -- if B then
7955 -- normal-statements
7956 -- else
7957 -- else-statements
7958 -- end if;
7959 -- end;
7960
5809835d 7961 -- For a description of the use of P and the assignments after the call,
7962 -- see Expand_N_Entry_Call_Statement. Note that the entry call of the
7963 -- conditional entry call has already been expanded (by the Expand_N_Entry
7964 -- _Call_Statement procedure) as follows:
ee6ba406 7965
7966 -- declare
7967 -- P : parms := (parm, parm, parm);
7968 -- begin
7969 -- ... info for in-out parameters
7970 -- Call_Simple (acceptor-task, entry-index, P'Address);
7971 -- parm := P.param;
7972 -- parm := P.param;
7973 -- ...
7974 -- end;
7975
7976 -- so the task at hand is to convert the latter expansion into the former
7977
7978 -- The conditional protected entry call is converted to a call to
7979 -- Protected_Entry_Call:
7980
7981 -- declare
7982 -- P : parms := (parm, parm, parm);
7983 -- Bnn : Communications_Block;
7984
7985 -- begin
5809835d 7986 -- Protected_Entry_Call
7987 -- (po._object'Access, -- Object
7988 -- <entry index>, -- E
7989 -- P'Address, -- Uninterpreted_Data
7990 -- Conditional_Call, -- Mode
7991 -- Bnn); -- Block
ee6ba406 7992 -- parm := P.param;
7993 -- parm := P.param;
7994 -- ...
7995 -- if Cancelled (Bnn) then
7996 -- else-statements
7997 -- else
7998 -- normal-statements
7999 -- end if;
8000 -- end;
8001
d62940bf 8002 -- Ada 2005 (AI-345): A dispatching conditional entry call is converted
8003 -- into:
8004
8005 -- declare
8006 -- B : Boolean := False;
8007 -- C : Ada.Tags.Prim_Op_Kind;
952af0b9 8008 -- K : Ada.Tags.Tagged_Kind :=
8009 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
d62940bf 8010 -- P : Parameters := (Param1 .. ParamN);
952af0b9 8011 -- S : Integer;
d62940bf 8012
8013 -- begin
37c6e44c 8014 -- if K = Ada.Tags.TK_Limited_Tagged
8015 -- or else K = Ada.Tags.TK_Tagged
8016 -- then
952af0b9 8017 -- <dispatching-call>;
8018 -- <triggering-statements>
d62940bf 8019
952af0b9 8020 -- else
5809835d 8021 -- S :=
8022 -- Ada.Tags.Get_Offset_Index
8023 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
d62940bf 8024
5809835d 8025 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
952af0b9 8026
8027 -- if C = POK_Protected_Entry
8028 -- or else C = POK_Task_Entry
d62940bf 8029 -- then
952af0b9 8030 -- Param1 := P.Param1;
8031 -- ...
8032 -- ParamN := P.ParamN;
8033 -- end if;
8034
8035 -- if B then
8036 -- if C = POK_Procedure
8037 -- or else C = POK_Protected_Procedure
8038 -- or else C = POK_Task_Procedure
8039 -- then
8040 -- <dispatching-call>;
8041 -- end if;
8042
8043 -- <triggering-statements>
8044 -- else
8045 -- <else-statements>
d62940bf 8046 -- end if;
d62940bf 8047 -- end if;
8048 -- end;
8049
ee6ba406 8050 procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
8051 Loc : constant Source_Ptr := Sloc (N);
8052 Alt : constant Node_Id := Entry_Call_Alternative (N);
8053 Blk : Node_Id := Entry_Call_Statement (Alt);
ee6ba406 8054
952af0b9 8055 Actuals : List_Id;
8056 Blk_Typ : Entity_Id;
8057 Call : Node_Id;
8058 Call_Ent : Entity_Id;
8059 Conc_Typ_Stmts : List_Id;
8060 Decl : Node_Id;
8061 Decls : List_Id;
8062 Formals : List_Id;
8063 Lim_Typ_Stmts : List_Id;
8064 N_Stats : List_Id;
8065 Obj : Entity_Id;
8066 Param : Node_Id;
8067 Params : List_Id;
8068 Stmt : Node_Id;
8069 Stmts : List_Id;
5809835d 8070 Transient_Blk : Node_Id;
952af0b9 8071 Unpack : List_Id;
8072
8073 B : Entity_Id; -- Call status flag
8074 C : Entity_Id; -- Call kind
8075 K : Entity_Id; -- Tagged kind
8076 P : Entity_Id; -- Parameter block
8077 S : Entity_Id; -- Primitive operation slot
ee6ba406 8078
8079 begin
f239f5be 8080 Process_Statements_For_Controlled_Objects (N);
8081
de54c5ab 8082 if Ada_Version >= Ada_2005
d62940bf 8083 and then Nkind (Blk) = N_Procedure_Call_Statement
8084 then
8085 Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
8086
8087 Decls := New_List;
8088 Stmts := New_List;
8089
8090 -- Call status flag processing, generate:
8091 -- B : Boolean := False;
8092
952af0b9 8093 B := Build_B (Loc, Decls);
d62940bf 8094
8095 -- Call kind processing, generate:
8096 -- C : Ada.Tags.Prim_Op_Kind;
8097
952af0b9 8098 C := Build_C (Loc, Decls);
8099
8100 -- Tagged kind processing, generate:
8101 -- K : Ada.Tags.Tagged_Kind :=
8102 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
8103
8104 K := Build_K (Loc, Decls, Obj);
d62940bf 8105
8106 -- Parameter block processing
8107
8108 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
952af0b9 8109 P := Parameter_Block_Pack
8110 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
d62940bf 8111
8112 -- Dispatch table slot processing, generate:
952af0b9 8113 -- S : Integer;
d62940bf 8114
952af0b9 8115 S := Build_S (Loc, Decls);
d62940bf 8116
8117 -- Generate:
5809835d 8118 -- S := Ada.Tags.Get_Offset_Index
8119 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
d62940bf 8120
5809835d 8121 Conc_Typ_Stmts :=
8122 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
952af0b9 8123
8124 -- Generate:
5809835d 8125 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
952af0b9 8126
8127 Append_To (Conc_Typ_Stmts,
d62940bf 8128 Make_Procedure_Call_Statement (Loc,
8129 Name =>
83c6c069 8130 New_Occurrence_Of (
76a1c25b 8131 Find_Prim_Op (Etype (Etype (Obj)),
8132 Name_uDisp_Conditional_Select),
8133 Loc),
d62940bf 8134 Parameter_Associations =>
8135 New_List (
5809835d 8136 New_Copy_Tree (Obj), -- <object>
83c6c069 8137 New_Occurrence_Of (S, Loc), -- S
5809835d 8138 Make_Attribute_Reference (Loc, -- P'Address
83c6c069 8139 Prefix => New_Occurrence_Of (P, Loc),
85377c9b 8140 Attribute_Name => Name_Address),
83c6c069 8141 New_Occurrence_Of (C, Loc), -- C
8142 New_Occurrence_Of (B, Loc)))); -- B
d62940bf 8143
8144 -- Generate:
8145 -- if C = POK_Protected_Entry
8146 -- or else C = POK_Task_Entry
8147 -- then
8148 -- Param1 := P.Param1;
8149 -- ...
8150 -- ParamN := P.ParamN;
8151 -- end if;
8152
76a1c25b 8153 Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
d62940bf 8154
76a1c25b 8155 -- Generate the if statement only when the packed parameters need
8156 -- explicit assignments to their corresponding actuals.
d62940bf 8157
76a1c25b 8158 if Present (Unpack) then
952af0b9 8159 Append_To (Conc_Typ_Stmts,
85377c9b 8160 Make_Implicit_If_Statement (N,
76a1c25b 8161 Condition =>
8162 Make_Or_Else (Loc,
8163 Left_Opnd =>
8164 Make_Op_Eq (Loc,
8165 Left_Opnd =>
83c6c069 8166 New_Occurrence_Of (C, Loc),
76a1c25b 8167 Right_Opnd =>
83c6c069 8168 New_Occurrence_Of (RTE (
76a1c25b 8169 RE_POK_Protected_Entry), Loc)),
e22bc81a 8170
76a1c25b 8171 Right_Opnd =>
8172 Make_Op_Eq (Loc,
8173 Left_Opnd =>
83c6c069 8174 New_Occurrence_Of (C, Loc),
76a1c25b 8175 Right_Opnd =>
83c6c069 8176 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
76a1c25b 8177
e22bc81a 8178 Then_Statements => Unpack));
76a1c25b 8179 end if;
d62940bf 8180
8181 -- Generate:
8182 -- if B then
8183 -- if C = POK_Procedure
8184 -- or else C = POK_Protected_Procedure
8185 -- or else C = POK_Task_Procedure
8186 -- then
952af0b9 8187 -- <dispatching-call>
d62940bf 8188 -- end if;
8189 -- <normal-statements>
8190 -- else
8191 -- <else-statements>
8192 -- end if;
8193
76a1c25b 8194 N_Stats := New_Copy_List_Tree (Statements (Alt));
d62940bf 8195
8196 Prepend_To (N_Stats,
85377c9b 8197 Make_Implicit_If_Statement (N,
d62940bf 8198 Condition =>
8199 Make_Or_Else (Loc,
8200 Left_Opnd =>
8201 Make_Op_Eq (Loc,
8202 Left_Opnd =>
83c6c069 8203 New_Occurrence_Of (C, Loc),
d62940bf 8204 Right_Opnd =>
83c6c069 8205 New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
d62940bf 8206
8207 Right_Opnd =>
8208 Make_Or_Else (Loc,
8209 Left_Opnd =>
8210 Make_Op_Eq (Loc,
8211 Left_Opnd =>
83c6c069 8212 New_Occurrence_Of (C, Loc),
d62940bf 8213 Right_Opnd =>
83c6c069 8214 New_Occurrence_Of (RTE (
d62940bf 8215 RE_POK_Protected_Procedure), Loc)),
8216
8217 Right_Opnd =>
8218 Make_Op_Eq (Loc,
8219 Left_Opnd =>
83c6c069 8220 New_Occurrence_Of (C, Loc),
d62940bf 8221 Right_Opnd =>
83c6c069 8222 New_Occurrence_Of (RTE (
d62940bf 8223 RE_POK_Task_Procedure), Loc)))),
8224
8225 Then_Statements =>
8226 New_List (Blk)));
8227
952af0b9 8228 Append_To (Conc_Typ_Stmts,
85377c9b 8229 Make_Implicit_If_Statement (N,
83c6c069 8230 Condition => New_Occurrence_Of (B, Loc),
d62940bf 8231 Then_Statements => N_Stats,
8232 Else_Statements => Else_Statements (N)));
8233
952af0b9 8234 -- Generate:
8235 -- <dispatching-call>;
8236 -- <triggering-statements>
8237
8238 Lim_Typ_Stmts := New_Copy_List_Tree (Statements (Alt));
8239 Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Blk));
8240
8241 -- Generate:
37c6e44c 8242 -- if K = Ada.Tags.TK_Limited_Tagged
8243 -- or else K = Ada.Tags.TK_Tagged
8244 -- then
952af0b9 8245 -- Lim_Typ_Stmts
8246 -- else
8247 -- Conc_Typ_Stmts
8248 -- end if;
8249
8250 Append_To (Stmts,
85377c9b 8251 Make_Implicit_If_Statement (N,
37c6e44c 8252 Condition => Build_Dispatching_Tag_Check (K, N),
8253 Then_Statements => Lim_Typ_Stmts,
8254 Else_Statements => Conc_Typ_Stmts));
952af0b9 8255
d62940bf 8256 Rewrite (N,
8257 Make_Block_Statement (Loc,
5809835d 8258 Declarations =>
8259 Decls,
d62940bf 8260 Handled_Statement_Sequence =>
8261 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
8262
85377c9b 8263 -- As described above, the entry alternative is transformed into a
ee6ba406 8264 -- block that contains the gnulli call, and possibly assignment
3d069ad4 8265 -- statements for in-out parameters. The gnulli call may itself be
ee6ba406 8266 -- rewritten into a transient block if some unconstrained parameters
8267 -- require it. We need to retrieve the call to complete its parameter
8268 -- list.
8269
d62940bf 8270 else
8271 Transient_Blk :=
5809835d 8272 First_Real_Statement (Handled_Statement_Sequence (Blk));
ee6ba406 8273
d62940bf 8274 if Present (Transient_Blk)
8275 and then Nkind (Transient_Blk) = N_Block_Statement
8276 then
8277 Blk := Transient_Blk;
8278 end if;
ee6ba406 8279
d62940bf 8280 Stmts := Statements (Handled_Statement_Sequence (Blk));
8281 Stmt := First (Stmts);
8282 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
8283 Next (Stmt);
8284 end loop;
ee6ba406 8285
d62940bf 8286 Call := Stmt;
8287 Params := Parameter_Associations (Call);
ee6ba406 8288
d62940bf 8289 if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
ee6ba406 8290
d62940bf 8291 -- Substitute Conditional_Entry_Call for Simple_Call parameter
ee6ba406 8292
d62940bf 8293 Param := First (Params);
8294 while Present (Param)
8295 and then not Is_RTE (Etype (Param), RE_Call_Modes)
8296 loop
8297 Next (Param);
8298 end loop;
ee6ba406 8299
d62940bf 8300 pragma Assert (Present (Param));
83c6c069 8301 Rewrite (Param,
8302 New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
ee6ba406 8303
d62940bf 8304 Analyze (Param);
ee6ba406 8305
d62940bf 8306 -- Find the Communication_Block parameter for the call to the
8307 -- Cancelled function.
ee6ba406 8308
d62940bf 8309 Decl := First (Declarations (Blk));
8310 while Present (Decl)
8311 and then not Is_RTE (Etype (Object_Definition (Decl)),
8312 RE_Communication_Block)
8313 loop
8314 Next (Decl);
8315 end loop;
ee6ba406 8316
d62940bf 8317 -- Add an if statement to execute the else part if the call
8318 -- does not succeed (as indicated by the Cancelled predicate).
ee6ba406 8319
d62940bf 8320 Append_To (Stmts,
8321 Make_Implicit_If_Statement (N,
8322 Condition => Make_Function_Call (Loc,
83c6c069 8323 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
d62940bf 8324 Parameter_Associations => New_List (
83c6c069 8325 New_Occurrence_Of (Defining_Identifier (Decl), Loc))),
d62940bf 8326 Then_Statements => Else_Statements (N),
8327 Else_Statements => Statements (Alt)));
ee6ba406 8328
d62940bf 8329 else
8330 B := Make_Defining_Identifier (Loc, Name_uB);
ee6ba406 8331
d62940bf 8332 -- Insert declaration of B in declarations of existing block
ee6ba406 8333
d62940bf 8334 if No (Declarations (Blk)) then
8335 Set_Declarations (Blk, New_List);
8336 end if;
ee6ba406 8337
d62940bf 8338 Prepend_To (Declarations (Blk),
8339 Make_Object_Declaration (Loc,
8340 Defining_Identifier => B,
85377c9b 8341 Object_Definition =>
83c6c069 8342 New_Occurrence_Of (Standard_Boolean, Loc)));
ee6ba406 8343
d62940bf 8344 -- Create new call statement
ee6ba406 8345
d62940bf 8346 Append_To (Params,
83c6c069 8347 New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
8348 Append_To (Params, New_Occurrence_Of (B, Loc));
ee6ba406 8349
d62940bf 8350 Rewrite (Call,
8351 Make_Procedure_Call_Statement (Loc,
83c6c069 8352 Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
d62940bf 8353 Parameter_Associations => Params));
ee6ba406 8354
d62940bf 8355 -- Construct statement sequence for new block
ee6ba406 8356
d62940bf 8357 Append_To (Stmts,
8358 Make_Implicit_If_Statement (N,
83c6c069 8359 Condition => New_Occurrence_Of (B, Loc),
d62940bf 8360 Then_Statements => Statements (Alt),
8361 Else_Statements => Else_Statements (N)));
8362 end if;
ee6ba406 8363
d62940bf 8364 -- The result is the new block
ee6ba406 8365
d62940bf 8366 Rewrite (N,
8367 Make_Block_Statement (Loc,
8368 Declarations => Declarations (Blk),
8369 Handled_Statement_Sequence =>
8370 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
ee6ba406 8371 end if;
8372
ee6ba406 8373 Analyze (N);
ee6ba406 8374 end Expand_N_Conditional_Entry_Call;
8375
8376 ---------------------------------------
8377 -- Expand_N_Delay_Relative_Statement --
8378 ---------------------------------------
8379
8380 -- Delay statement is implemented as a procedure call to Delay_For
8381 -- defined in Ada.Calendar.Delays in order to reduce the overhead of
8382 -- simple delays imposed by the use of Protected Objects.
8383
8384 procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
8385 Loc : constant Source_Ptr := Sloc (N);
ee6ba406 8386 begin
8387 Rewrite (N,
8388 Make_Procedure_Call_Statement (Loc,
83c6c069 8389 Name => New_Occurrence_Of (RTE (RO_CA_Delay_For), Loc),
ee6ba406 8390 Parameter_Associations => New_List (Expression (N))));
8391 Analyze (N);
8392 end Expand_N_Delay_Relative_Statement;
8393
8394 ------------------------------------
8395 -- Expand_N_Delay_Until_Statement --
8396 ------------------------------------
8397
8398 -- Delay Until statement is implemented as a procedure call to
8399 -- Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
8400
8401 procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
8402 Loc : constant Source_Ptr := Sloc (N);
8403 Typ : Entity_Id;
8404
8405 begin
8406 if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
8407 Typ := RTE (RO_CA_Delay_Until);
8408 else
8409 Typ := RTE (RO_RT_Delay_Until);
8410 end if;
8411
8412 Rewrite (N,
8413 Make_Procedure_Call_Statement (Loc,
83c6c069 8414 Name => New_Occurrence_Of (Typ, Loc),
ee6ba406 8415 Parameter_Associations => New_List (Expression (N))));
8416
8417 Analyze (N);
8418 end Expand_N_Delay_Until_Statement;
8419
8420 -------------------------
8421 -- Expand_N_Entry_Body --
8422 -------------------------
8423
8424 procedure Expand_N_Entry_Body (N : Node_Id) is
ee6ba406 8425 begin
57993a53 8426 -- Associate discriminals with the next protected operation body to be
8427 -- expanded.
ee6ba406 8428
57993a53 8429 if Present (Next_Protected_Operation (N)) then
8430 Set_Discriminals (Parent (Current_Scope));
ee6ba406 8431 end if;
ee6ba406 8432 end Expand_N_Entry_Body;
8433
8434 -----------------------------------
8435 -- Expand_N_Entry_Call_Statement --
8436 -----------------------------------
8437
57993a53 8438 -- An entry call is expanded into GNARLI calls to implement a simple entry
8439 -- call (see Build_Simple_Entry_Call).
ee6ba406 8440
8441 procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
8442 Concval : Node_Id;
8443 Ename : Node_Id;
8444 Index : Node_Id;
8445
8446 begin
9dfe12ae 8447 if No_Run_Time_Mode then
8448 Error_Msg_CRT ("entry call", N);
8449 return;
8450 end if;
8451
76a1c25b 8452 -- If this entry call is part of an asynchronous select, don't expand it
8453 -- here; it will be expanded with the select statement. Don't expand
8454 -- timed entry calls either, as they are translated into asynchronous
8455 -- entry calls.
ee6ba406 8456
76a1c25b 8457 -- ??? This whole approach is questionable; it may be better to go back
8458 -- to allowing the expansion to take place and then attempting to fix it
8459 -- up in Expand_N_Asynchronous_Select. The tricky part is figuring out
8460 -- whether the expanded call is on a task or protected entry.
ee6ba406 8461
8462 if (Nkind (Parent (N)) /= N_Triggering_Alternative
8463 or else N /= Triggering_Statement (Parent (N)))
8464 and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
8465 or else N /= Entry_Call_Statement (Parent (N))
8466 or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
8467 then
8468 Extract_Entry (N, Concval, Ename, Index);
8469 Build_Simple_Entry_Call (N, Concval, Ename, Index);
8470 end if;
ee6ba406 8471 end Expand_N_Entry_Call_Statement;
8472
8473 --------------------------------
8474 -- Expand_N_Entry_Declaration --
8475 --------------------------------
8476
76a1c25b 8477 -- If there are parameters, then first, each of the formals is marked by
8478 -- setting Is_Entry_Formal. Next a record type is built which is used to
8479 -- hold the parameter values. The name of this record type is entryP where
8480 -- entry is the name of the entry, with an additional corresponding access
8481 -- type called entryPA. The record type has matching components for each
8482 -- formal (the component names are the same as the formal names). For
8483 -- elementary types, the component type matches the formal type. For
8484 -- composite types, an access type is declared (with the name formalA)
8485 -- which designates the formal type, and the type of the component is this
8486 -- access type. Finally the Entry_Component of each formal is set to
8487 -- reference the corresponding record component.
ee6ba406 8488
8489 procedure Expand_N_Entry_Declaration (N : Node_Id) is
8490 Loc : constant Source_Ptr := Sloc (N);
8491 Entry_Ent : constant Entity_Id := Defining_Identifier (N);
8492 Components : List_Id;
8493 Formal : Node_Id;
8494 Ftype : Entity_Id;
8495 Last_Decl : Node_Id;
8496 Component : Entity_Id;
8497 Ctype : Entity_Id;
8498 Decl : Node_Id;
8499 Rec_Ent : Entity_Id;
8500 Acc_Ent : Entity_Id;
8501
8502 begin
8503 Formal := First_Formal (Entry_Ent);
8504 Last_Decl := N;
8505
8506 -- Most processing is done only if parameters are present
8507
8508 if Present (Formal) then
8509 Components := New_List;
8510
8511 -- Loop through formals
8512
8513 while Present (Formal) loop
8514 Set_Is_Entry_Formal (Formal);
8515 Component :=
8516 Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
8517 Set_Entry_Component (Formal, Component);
8518 Set_Entry_Formal (Component, Formal);
8519 Ftype := Etype (Formal);
8520
8521 -- Declare new access type and then append
8522
ec97ce79 8523 Ctype := Make_Temporary (Loc, 'A');
11cf765a 8524 Set_Is_Param_Block_Component_Type (Ctype);
ee6ba406 8525
8526 Decl :=
8527 Make_Full_Type_Declaration (Loc,
8528 Defining_Identifier => Ctype,
8529 Type_Definition =>
8530 Make_Access_To_Object_Definition (Loc,
8531 All_Present => True,
8532 Constant_Present => Ekind (Formal) = E_In_Parameter,
83c6c069 8533 Subtype_Indication => New_Occurrence_Of (Ftype, Loc)));
ee6ba406 8534
8535 Insert_After (Last_Decl, Decl);
8536 Last_Decl := Decl;
8537
8538 Append_To (Components,
8539 Make_Component_Declaration (Loc,
8540 Defining_Identifier => Component,
b5ff3ed8 8541 Component_Definition =>
8542 Make_Component_Definition (Loc,
8543 Aliased_Present => False,
83c6c069 8544 Subtype_Indication => New_Occurrence_Of (Ctype, Loc))));
ee6ba406 8545
8546 Next_Formal_With_Extras (Formal);
8547 end loop;
8548
8549 -- Create the Entry_Parameter_Record declaration
8550
ec97ce79 8551 Rec_Ent := Make_Temporary (Loc, 'P');
ee6ba406 8552
8553 Decl :=
8554 Make_Full_Type_Declaration (Loc,
8555 Defining_Identifier => Rec_Ent,
8556 Type_Definition =>
8557 Make_Record_Definition (Loc,
8558 Component_List =>
8559 Make_Component_List (Loc,
8560 Component_Items => Components)));
8561
8562 Insert_After (Last_Decl, Decl);
8563 Last_Decl := Decl;
8564
8565 -- Construct and link in the corresponding access type
8566
ec97ce79 8567 Acc_Ent := Make_Temporary (Loc, 'A');
ee6ba406 8568
8569 Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
8570
8571 Decl :=
8572 Make_Full_Type_Declaration (Loc,
8573 Defining_Identifier => Acc_Ent,
8574 Type_Definition =>
8575 Make_Access_To_Object_Definition (Loc,
8576 All_Present => True,
83c6c069 8577 Subtype_Indication => New_Occurrence_Of (Rec_Ent, Loc)));
ee6ba406 8578
8579 Insert_After (Last_Decl, Decl);
ee6ba406 8580 end if;
ee6ba406 8581 end Expand_N_Entry_Declaration;
8582
8583 -----------------------------
8584 -- Expand_N_Protected_Body --
8585 -----------------------------
8586
8587 -- Protected bodies are expanded to the completion of the subprograms
76a1c25b 8588 -- created for the corresponding protected type. These are a protected and
8589 -- unprotected version of each protected subprogram in the object, a
8590 -- function to calculate each entry barrier, and a procedure to execute the
8591 -- sequence of statements of each protected entry body. For example, for
8592 -- protected type ptype:
ee6ba406 8593
8594 -- function entB
8595 -- (O : System.Address;
8596 -- E : Protected_Entry_Index)
8597 -- return Boolean
8598 -- is
8599 -- <discriminant renamings>
8600 -- <private object renamings>
8601 -- begin
8602 -- return <barrier expression>;
8603 -- end entB;
8604
8605 -- procedure pprocN (_object : in out poV;...) is
8606 -- <discriminant renamings>
8607 -- <private object renamings>
8608 -- begin
8609 -- <sequence of statements>
8610 -- end pprocN;
8611
d62940bf 8612 -- procedure pprocP (_object : in out poV;...) is
ee6ba406 8613 -- procedure _clean is
8614 -- Pn : Boolean;
8615 -- begin
8616 -- ptypeS (_object, Pn);
8617 -- Unlock (_object._object'Access);
8618 -- Abort_Undefer.all;
8619 -- end _clean;
9dfe12ae 8620
ee6ba406 8621 -- begin
8622 -- Abort_Defer.all;
8623 -- Lock (_object._object'Access);
8624 -- pprocN (_object;...);
8625 -- at end
8626 -- _clean;
8627 -- end pproc;
8628
8629 -- function pfuncN (_object : poV;...) return Return_Type is
8630 -- <discriminant renamings>
8631 -- <private object renamings>
8632 -- begin
8633 -- <sequence of statements>
8634 -- end pfuncN;
8635
d62940bf 8636 -- function pfuncP (_object : poV) return Return_Type is
ee6ba406 8637 -- procedure _clean is
8638 -- begin
8639 -- Unlock (_object._object'Access);
8640 -- Abort_Undefer.all;
8641 -- end _clean;
9dfe12ae 8642
ee6ba406 8643 -- begin
8644 -- Abort_Defer.all;
8645 -- Lock (_object._object'Access);
8646 -- return pfuncN (_object);
9dfe12ae 8647
ee6ba406 8648 -- at end
8649 -- _clean;
8650 -- end pfunc;
8651
8652 -- procedure entE
8653 -- (O : System.Address;
8654 -- P : System.Address;
8655 -- E : Protected_Entry_Index)
8656 -- is
8657 -- <discriminant renamings>
8658 -- <private object renamings>
8659 -- type poVP is access poV;
8660 -- _Object : ptVP := ptVP!(O);
9dfe12ae 8661
ee6ba406 8662 -- begin
8663 -- begin
8664 -- <statement sequence>
8665 -- Complete_Entry_Body (_Object._Object);
8666 -- exception
8667 -- when all others =>
8668 -- Exceptional_Complete_Entry_Body (
8669 -- _Object._Object, Get_GNAT_Exception);
8670 -- end;
8671 -- end entE;
8672
8673 -- The type poV is the record created for the protected type to hold
8674 -- the state of the protected object.
8675
8676 procedure Expand_N_Protected_Body (N : Node_Id) is
a16536f8 8677 Loc : constant Source_Ptr := Sloc (N);
8678 Pid : constant Entity_Id := Corresponding_Spec (N);
f74a743d 8679
7413d80d 8680 Lock_Free_Active : constant Boolean := Uses_Lock_Free (Pid);
7a19298b 8681 -- This flag indicates whether the lock free implementation is active
8682
d2a42b76 8683 Current_Node : Node_Id;
d62940bf 8684 Disp_Op_Body : Node_Id;
ee6ba406 8685 New_Op_Body : Node_Id;
d2a42b76 8686 Op_Body : Node_Id;
d2a42b76 8687 Op_Id : Entity_Id;
ee6ba406 8688
d62940bf 8689 function Build_Dispatching_Subprogram_Body
8690 (N : Node_Id;
8691 Pid : Node_Id;
8692 Prot_Bod : Node_Id) return Node_Id;
8693 -- Build a dispatching version of the protected subprogram body. The
8694 -- newly generated subprogram contains a call to the original protected
8695 -- body. The following code is generated:
8696 --
8697 -- function <protected-function-name> (Param1 .. ParamN) return
8698 -- <return-type> is
8699 -- begin
8700 -- return <protected-function-name>P (Param1 .. ParamN);
8701 -- end <protected-function-name>;
8702 --
8703 -- or
8704 --
8705 -- procedure <protected-procedure-name> (Param1 .. ParamN) is
8706 -- begin
8707 -- <protected-procedure-name>P (Param1 .. ParamN);
8708 -- end <protected-procedure-name>
8709
8710 ---------------------------------------
8711 -- Build_Dispatching_Subprogram_Body --
8712 ---------------------------------------
8713
8714 function Build_Dispatching_Subprogram_Body
8715 (N : Node_Id;
8716 Pid : Node_Id;
8717 Prot_Bod : Node_Id) return Node_Id
8718 is
8719 Loc : constant Source_Ptr := Sloc (N);
8720 Actuals : List_Id;
8721 Formal : Node_Id;
8722 Spec : Node_Id;
8723 Stmts : List_Id;
8724
8725 begin
8726 -- Generate a specification without a letter suffix in order to
8727 -- override an interface function or procedure.
8728
9ee7df75 8729 Spec := Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
d62940bf 8730
9ee7df75 8731 -- The formal parameters become the actuals of the protected function
8732 -- or procedure call.
d62940bf 8733
8734 Actuals := New_List;
8735 Formal := First (Parameter_Specifications (Spec));
d62940bf 8736 while Present (Formal) loop
8737 Append_To (Actuals,
8738 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
d62940bf 8739 Next (Formal);
8740 end loop;
8741
8742 if Nkind (Spec) = N_Procedure_Specification then
8743 Stmts :=
8744 New_List (
8745 Make_Procedure_Call_Statement (Loc,
8746 Name =>
83c6c069 8747 New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
d62940bf 8748 Parameter_Associations => Actuals));
a16536f8 8749
d62940bf 8750 else
8751 pragma Assert (Nkind (Spec) = N_Function_Specification);
8752
8753 Stmts :=
8754 New_List (
0d85cfbf 8755 Make_Simple_Return_Statement (Loc,
d62940bf 8756 Expression =>
8757 Make_Function_Call (Loc,
8758 Name =>
83c6c069 8759 New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
d62940bf 8760 Parameter_Associations => Actuals)));
8761 end if;
8762
8763 return
8764 Make_Subprogram_Body (Loc,
9ee7df75 8765 Declarations => Empty_List,
8766 Specification => Spec,
d62940bf 8767 Handled_Statement_Sequence =>
8768 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
8769 end Build_Dispatching_Subprogram_Body;
8770
8771 -- Start of processing for Expand_N_Protected_Body
8772
ee6ba406 8773 begin
9dfe12ae 8774 if No_Run_Time_Mode then
8775 Error_Msg_CRT ("protected body", N);
8776 return;
8777 end if;
8778
d2a42b76 8779 -- This is the proper body corresponding to a stub. The declarations
8780 -- must be inserted at the point of the stub, which in turn is in the
8781 -- declarative part of the parent unit.
ee6ba406 8782
d2a42b76 8783 if Nkind (Parent (N)) = N_Subunit then
ee6ba406 8784 Current_Node := Corresponding_Stub (Parent (N));
ee6ba406 8785 else
8786 Current_Node := N;
8787 end if;
8788
8789 Op_Body := First (Declarations (N));
8790
8791 -- The protected body is replaced with the bodies of its
8792 -- protected operations, and the declarations for internal objects
8793 -- that may have been created for entry family bounds.
8794
8795 Rewrite (N, Make_Null_Statement (Sloc (N)));
8796 Analyze (N);
8797
8798 while Present (Op_Body) loop
ee6ba406 8799 case Nkind (Op_Body) is
8800 when N_Subprogram_Declaration =>
8801 null;
8802
8803 when N_Subprogram_Body =>
8804
2f29393f 8805 -- Do not create bodies for eliminated operations
ee6ba406 8806
60fd8afc 8807 if not Is_Eliminated (Defining_Entity (Op_Body))
8808 and then not Is_Eliminated (Corresponding_Spec (Op_Body))
8809 then
7413d80d 8810 if Lock_Free_Active then
7a19298b 8811 New_Op_Body :=
8812 Build_Lock_Free_Unprotected_Subprogram_Body
8813 (Op_Body, Pid);
8814 else
8815 New_Op_Body :=
8816 Build_Unprotected_Subprogram_Body (Op_Body, Pid);
8817 end if;
ee6ba406 8818
8819 Insert_After (Current_Node, New_Op_Body);
8820 Current_Node := New_Op_Body;
8821 Analyze (New_Op_Body);
8822
cb5f80c1 8823 -- Build the corresponding protected operation. It may
57993a53 8824 -- appear that this is needed only if this is a visible
cb5f80c1 8825 -- operation of the type, or if it is an interrupt handler,
8826 -- and this was the strategy used previously in GNAT.
7a19298b 8827
2f29393f 8828 -- However, the operation may be exported through a 'Access
8829 -- to an external caller. This is the common idiom in code
8830 -- that uses the Ada 2005 Timing_Events package. As a result
8831 -- we need to produce the protected body for both visible
4606d5a9 8832 -- and private operations, as well as operations that only
8833 -- have a body in the source, and for which we create a
8834 -- declaration in the protected body itself.
ee6ba406 8835
8836 if Present (Corresponding_Spec (Op_Body)) then
7413d80d 8837 if Lock_Free_Active then
7a19298b 8838 New_Op_Body :=
8839 Build_Lock_Free_Protected_Subprogram_Body
8840 (Op_Body, Pid, Specification (New_Op_Body));
8841 else
8842 New_Op_Body :=
8843 Build_Protected_Subprogram_Body
8844 (Op_Body, Pid, Specification (New_Op_Body));
8845 end if;
cb5f80c1 8846
4606d5a9 8847 Insert_After (Current_Node, New_Op_Body);
8848 Analyze (New_Op_Body);
d62940bf 8849
4606d5a9 8850 Current_Node := New_Op_Body;
d62940bf 8851
4606d5a9 8852 -- Generate an overriding primitive operation body for
3fecb07d 8853 -- this subprogram if the protected type implements an
8854 -- interface.
d62940bf 8855
de54c5ab 8856 if Ada_Version >= Ada_2005
c0688d2b 8857 and then
8858 Present (Interfaces (Corresponding_Record_Type (Pid)))
4606d5a9 8859 then
8860 Disp_Op_Body :=
3fecb07d 8861 Build_Dispatching_Subprogram_Body
8862 (Op_Body, Pid, New_Op_Body);
d62940bf 8863
4606d5a9 8864 Insert_After (Current_Node, Disp_Op_Body);
8865 Analyze (Disp_Op_Body);
d62940bf 8866
4606d5a9 8867 Current_Node := Disp_Op_Body;
ee6ba406 8868 end if;
8869 end if;
8870 end if;
8871
8872 when N_Entry_Body =>
8873 Op_Id := Defining_Identifier (Op_Body);
ee6ba406 8874 New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
8875
8876 Insert_After (Current_Node, New_Op_Body);
8877 Current_Node := New_Op_Body;
8878 Analyze (New_Op_Body);
8879
ee6ba406 8880 when N_Implicit_Label_Declaration =>
8881 null;
8882
8883 when N_Itype_Reference =>
8884 Insert_After (Current_Node, New_Copy (Op_Body));
8885
8886 when N_Freeze_Entity =>
8887 New_Op_Body := New_Copy (Op_Body);
8888
8889 if Present (Entity (Op_Body))
8890 and then Freeze_Node (Entity (Op_Body)) = Op_Body
8891 then
8892 Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
8893 end if;
8894
8895 Insert_After (Current_Node, New_Op_Body);
8896 Current_Node := New_Op_Body;
8897 Analyze (New_Op_Body);
8898
8899 when N_Pragma =>
8900 New_Op_Body := New_Copy (Op_Body);
8901 Insert_After (Current_Node, New_Op_Body);
8902 Current_Node := New_Op_Body;
8903 Analyze (New_Op_Body);
8904
8905 when N_Object_Declaration =>
8906 pragma Assert (not Comes_From_Source (Op_Body));
8907 New_Op_Body := New_Copy (Op_Body);
8908 Insert_After (Current_Node, New_Op_Body);
8909 Current_Node := New_Op_Body;
8910 Analyze (New_Op_Body);
8911
8912 when others =>
8913 raise Program_Error;
8914
8915 end case;
8916
8917 Next (Op_Body);
8918 end loop;
8919
3d069ad4 8920 -- Finally, create the body of the function that maps an entry index
3fecb07d 8921 -- into the corresponding body index, except when there is no entry, or
8922 -- in a Ravenscar-like profile.
70966f50 8923
8924 if Corresponding_Runtime_Package (Pid) =
8925 System_Tasking_Protected_Objects_Entries
ee6ba406 8926 then
8927 New_Op_Body := Build_Find_Body_Index (Pid);
8928 Insert_After (Current_Node, New_Op_Body);
9f373bb8 8929 Current_Node := New_Op_Body;
ee6ba406 8930 Analyze (New_Op_Body);
8931 end if;
9f373bb8 8932
d2a42b76 8933 -- Ada 2005 (AI-345): Construct the primitive wrapper bodies after the
8934 -- protected body. At this point all wrapper specs have been created,
76a1c25b 8935 -- frozen and included in the dispatch table for the protected type.
9f373bb8 8936
de54c5ab 8937 if Ada_Version >= Ada_2005 then
d2a42b76 8938 Build_Wrapper_Bodies (Loc, Pid, Current_Node);
9f373bb8 8939 end if;
ee6ba406 8940 end Expand_N_Protected_Body;
8941
8942 -----------------------------------------
8943 -- Expand_N_Protected_Type_Declaration --
8944 -----------------------------------------
8945
8946 -- First we create a corresponding record type declaration used to
8947 -- represent values of this protected type.
8948 -- The general form of this type declaration is
8949
8950 -- type poV (discriminants) is record
8951 -- _Object : aliased <kind>Protection
8952 -- [(<entry count> [, <handler count>])];
8953 -- [entry_family : array (bounds) of Void;]
8954 -- <private data fields>
8955 -- end record;
8956
76a1c25b 8957 -- The discriminants are present only if the corresponding protected type
8958 -- has discriminants, and they exactly mirror the protected type
8959 -- discriminants. The private data fields similarly mirror the private
8960 -- declarations of the protected type.
ee6ba406 8961
76a1c25b 8962 -- The Object field is always present. It contains RTS specific data used
8963 -- to control the protected object. It is declared as Aliased so that it
8964 -- can be passed as a pointer to the RTS. This allows the protected record
8965 -- to be referenced within RTS data structures. An appropriate Protection
8966 -- type and discriminant are generated.
ee6ba406 8967
8968 -- The Service field is present for protected objects with entries. It
76a1c25b 8969 -- contains sufficient information to allow the entry service procedure for
8970 -- this object to be called when the object is not known till runtime.
ee6ba406 8971
8972 -- One entry_family component is present for each entry family in the
8973 -- task definition (see Expand_N_Task_Type_Declaration).
8974
8975 -- When a protected object is declared, an instance of the protected type
76a1c25b 8976 -- value record is created. The elaboration of this declaration creates the
8977 -- correct bounds for the entry families, and also evaluates the priority
8978 -- expression if needed. The initialization routine for the protected type
8979 -- itself then calls Initialize_Protection with appropriate parameters to
8980 -- initialize the value of the Task_Id field. Install_Handlers may be also
8981 -- called if a pragma Attach_Handler applies.
8982
8983 -- Note: this record is passed to the subprograms created by the expansion
8984 -- of protected subprograms and entries. It is an in parameter to protected
8985 -- functions and an in out parameter to procedures and entry bodies. The
8986 -- Entity_Id for this created record type is placed in the
8987 -- Corresponding_Record_Type field of the associated protected type entity.
8988
8989 -- Next we create a procedure specifications for protected subprograms and
8990 -- entry bodies. For each protected subprograms two subprograms are
8991 -- created, an unprotected and a protected version. The unprotected version
8992 -- is called from within other operations of the same protected object.
ee6ba406 8993
8994 -- We also build the call to register the procedure if a pragma
8995 -- Interrupt_Handler applies.
8996
8997 -- A single subprogram is created to service all entry bodies; it has an
76a1c25b 8998 -- additional boolean out parameter indicating that the previous entry call
8999 -- made by the current task was serviced immediately, i.e. not by proxy.
9000 -- The O parameter contains a pointer to a record object of the type
9001 -- described above. An untyped interface is used here to allow this
ee6ba406 9002 -- procedure to be called in places where the type of the object to be
76a1c25b 9003 -- serviced is not known. This must be done, for example, when a call that
9004 -- may have been requeued is cancelled; the corresponding object must be
9005 -- serviced, but which object that is not known till runtime.
ee6ba406 9006
9007 -- procedure ptypeS
9008 -- (O : System.Address; P : out Boolean);
9009 -- procedure pprocN (_object : in out poV);
9010 -- procedure pproc (_object : in out poV);
9011 -- function pfuncN (_object : poV);
9012 -- function pfunc (_object : poV);
9013 -- ...
9014
9015 -- Note that this must come after the record type declaration, since
9016 -- the specs refer to this type.
9017
9018 procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
2f06c88a 9019 Discr_Map : constant Elist_Id := New_Elmt_List;
9020 Loc : constant Source_Ptr := Sloc (N);
9021 Prot_Typ : constant Entity_Id := Defining_Identifier (N);
ee6ba406 9022
7413d80d 9023 Lock_Free_Active : constant Boolean := Uses_Lock_Free (Prot_Typ);
9024 -- This flag indicates whether the lock free implementation is active
9025
a16536f8 9026 Pdef : constant Node_Id := Protected_Definition (N);
ee6ba406 9027 -- This contains two lists; one for visible and one for private decls
9028
2f06c88a 9029 Body_Arr : Node_Id;
9030 Body_Id : Entity_Id;
9dfe12ae 9031 Cdecls : List_Id;
ee6ba406 9032 Comp : Node_Id;
9033 Comp_Id : Entity_Id;
ee6ba406 9034 Current_Node : Node_Id := N;
ee6ba406 9035 E_Count : Int;
2f06c88a 9036 Entries_Aggr : Node_Id;
9037 New_Priv : Node_Id;
ee6ba406 9038 Object_Comp : Node_Id;
2f06c88a 9039 Priv : Node_Id;
9040 Rec_Decl : Node_Id;
9041 Sub : Node_Id;
ee6ba406 9042
e4401d9b 9043 procedure Check_Inlining (Subp : Entity_Id);
9044 -- If the original operation has a pragma Inline, propagate the flag
9045 -- to the internal body, for possible inlining later on. The source
9046 -- operation is invisible to the back-end and is never actually called.
9047
f31be12c 9048 function Discriminated_Size (Comp : Entity_Id) return Boolean;
9049 -- If a component size is not static then a warning will be emitted
9050 -- in Ravenscar or other restricted contexts. When a component is non-
9051 -- static because of a discriminant constraint we can specialize the
9052 -- warning by mentioning discriminants explicitly.
9053
4740c6a2 9054 procedure Expand_Entry_Declaration (Comp : Entity_Id);
9055 -- Create the subprograms for the barrier and for the body, and append
9056 -- then to Entry_Bodies_Array.
9057
0b16c8b7 9058 function Static_Component_Size (Comp : Entity_Id) return Boolean;
9059 -- When compiling under the Ravenscar profile, private components must
9060 -- have a static size, or else a protected object will require heap
9061 -- allocation, violating the corresponding restriction. It is preferable
9062 -- to make this check here, because it provides a better error message
9063 -- than the back-end, which refers to the object as a whole.
9064
ee6ba406 9065 procedure Register_Handler;
76a1c25b 9066 -- For a protected operation that is an interrupt handler, add the
ee6ba406 9067 -- freeze action that will register it as such.
9068
e4401d9b 9069 --------------------
9070 -- Check_Inlining --
9071 --------------------
9072
9073 procedure Check_Inlining (Subp : Entity_Id) is
9074 begin
9075 if Is_Inlined (Subp) then
9076 Set_Is_Inlined (Protected_Body_Subprogram (Subp));
9077 Set_Is_Inlined (Subp, False);
9078 end if;
9079 end Check_Inlining;
9080
f31be12c 9081 ------------------------
9082 -- Discriminated_Size --
9083 ------------------------
9084
edad2f4f 9085 function Discriminated_Size (Comp : Entity_Id) return Boolean is
f31be12c 9086 Typ : constant Entity_Id := Etype (Comp);
9087 Index : Node_Id;
9088
9089 function Non_Static_Bound (Bound : Node_Id) return Boolean;
edad2f4f 9090 -- Check whether the bound of an index is non-static and does denote
9091 -- a discriminant, in which case any protected object of the type
9092 -- will have a non-static size.
f31be12c 9093
9094 ----------------------
9095 -- Non_Static_Bound --
9096 ----------------------
9097
9098 function Non_Static_Bound (Bound : Node_Id) return Boolean is
9099 begin
bf915974 9100 if Is_OK_Static_Expression (Bound) then
f31be12c 9101 return False;
9102
9103 elsif Is_Entity_Name (Bound)
edad2f4f 9104 and then Present (Discriminal_Link (Entity (Bound)))
f31be12c 9105 then
9106 return False;
9107
9108 else
9109 return True;
9110 end if;
9111 end Non_Static_Bound;
9112
edad2f4f 9113 -- Start of processing for Discriminated_Size
9114
f31be12c 9115 begin
9116 if not Is_Array_Type (Typ) then
9117 return False;
9118 end if;
9119
9120 if Ekind (Typ) = E_Array_Subtype then
9121 Index := First_Index (Typ);
9122 while Present (Index) loop
9123 if Non_Static_Bound (Low_Bound (Index))
9124 or else Non_Static_Bound (High_Bound (Index))
9125 then
9126 return False;
9127 end if;
9128
9129 Next_Index (Index);
9130 end loop;
9131
9132 return True;
9133 end if;
9134
9135 return False;
9136 end Discriminated_Size;
9137
9138 ---------------------------
9139 -- Static_Component_Size --
9140 ---------------------------
0b16c8b7 9141
9142 function Static_Component_Size (Comp : Entity_Id) return Boolean is
9143 Typ : constant Entity_Id := Etype (Comp);
9144 C : Entity_Id;
9145
9146 begin
9147 if Is_Scalar_Type (Typ) then
9148 return True;
9149
9150 elsif Is_Array_Type (Typ) then
9151 return Compile_Time_Known_Bounds (Typ);
9152
9153 elsif Is_Record_Type (Typ) then
9154 C := First_Component (Typ);
9155 while Present (C) loop
9156 if not Static_Component_Size (C) then
9157 return False;
9158 end if;
9159
9160 Next_Component (C);
9161 end loop;
9162
9163 return True;
9164
a16536f8 9165 -- Any other type will be checked by the back-end
0b16c8b7 9166
9167 else
9168 return True;
9169 end if;
9170 end Static_Component_Size;
9171
4740c6a2 9172 ------------------------------
9173 -- Expand_Entry_Declaration --
9174 ------------------------------
9175
9176 procedure Expand_Entry_Declaration (Comp : Entity_Id) is
9177 Bdef : Entity_Id;
9178 Edef : Entity_Id;
22372664 9179
4740c6a2 9180 begin
9181 E_Count := E_Count + 1;
9182 Comp_Id := Defining_Identifier (Comp);
9183
9184 Edef :=
9185 Make_Defining_Identifier (Loc,
22372664 9186 Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'E'));
4740c6a2 9187 Sub :=
9188 Make_Subprogram_Declaration (Loc,
9189 Specification =>
9190 Build_Protected_Entry_Specification (Loc, Edef, Comp_Id));
9191
9192 Insert_After (Current_Node, Sub);
9193 Analyze (Sub);
9194
3ff5e35d 9195 -- Build a wrapper procedure to handle contract cases, preconditions,
9196 -- and postconditions.
4740c6a2 9197
3ff5e35d 9198 Build_Contract_Wrapper (Comp_Id, N);
4740c6a2 9199
9200 Set_Protected_Body_Subprogram
9201 (Defining_Identifier (Comp),
9202 Defining_Unit_Name (Specification (Sub)));
9203
9204 Current_Node := Sub;
9205
9206 Bdef :=
9207 Make_Defining_Identifier (Loc,
9208 Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'B'));
9209 Sub :=
9210 Make_Subprogram_Declaration (Loc,
9211 Specification =>
9212 Build_Barrier_Function_Specification (Loc, Bdef));
2f06c88a 9213 Set_Is_Entry_Barrier_Function (Sub);
4740c6a2 9214
9215 Insert_After (Current_Node, Sub);
9216 Analyze (Sub);
9217 Set_Protected_Body_Subprogram (Bdef, Bdef);
9218 Set_Barrier_Function (Comp_Id, Bdef);
9219 Set_Scope (Bdef, Scope (Comp_Id));
9220 Current_Node := Sub;
9221
9222 -- Collect pointers to the protected subprogram and the barrier
9223 -- of the current entry, for insertion into Entry_Bodies_Array.
9224
9225 Append_To (Expressions (Entries_Aggr),
9226 Make_Aggregate (Loc,
9227 Expressions => New_List (
9228 Make_Attribute_Reference (Loc,
83c6c069 9229 Prefix => New_Occurrence_Of (Bdef, Loc),
4740c6a2 9230 Attribute_Name => Name_Unrestricted_Access),
9231 Make_Attribute_Reference (Loc,
83c6c069 9232 Prefix => New_Occurrence_Of (Edef, Loc),
4740c6a2 9233 Attribute_Name => Name_Unrestricted_Access))));
9234 end Expand_Entry_Declaration;
9235
ee6ba406 9236 ----------------------
9237 -- Register_Handler --
9238 ----------------------
9239
9240 procedure Register_Handler is
9241
9242 -- All semantic checks already done in Sem_Prag
9243
9244 Prot_Proc : constant Entity_Id :=
a16536f8 9245 Defining_Unit_Name (Specification (Current_Node));
ee6ba406 9246
9247 Proc_Address : constant Node_Id :=
9248 Make_Attribute_Reference (Loc,
a16536f8 9249 Prefix =>
83c6c069 9250 New_Occurrence_Of (Prot_Proc, Loc),
a16536f8 9251 Attribute_Name => Name_Address);
ee6ba406 9252
9253 RTS_Call : constant Entity_Id :=
9254 Make_Procedure_Call_Statement (Loc,
a16536f8 9255 Name =>
83c6c069 9256 New_Occurrence_Of
a16536f8 9257 (RTE (RE_Register_Interrupt_Handler), Loc),
9258 Parameter_Associations => New_List (Proc_Address));
ee6ba406 9259 begin
9260 Append_Freeze_Action (Prot_Proc, RTS_Call);
9261 end Register_Handler;
9262
9263 -- Start of processing for Expand_N_Protected_Type_Declaration
9264
9265 begin
57993a53 9266 if Present (Corresponding_Record_Type (Prot_Typ)) then
ee6ba406 9267 return;
9268 else
57993a53 9269 Rec_Decl := Build_Corresponding_Record (N, Prot_Typ, Loc);
ee6ba406 9270 end if;
9271
4961db87 9272 Cdecls := Component_Items (Component_List (Type_Definition (Rec_Decl)));
9273
ee6ba406 9274 Qualify_Entity_Names (N);
9275
9276 -- If the type has discriminants, their occurrences in the declaration
9277 -- have been replaced by the corresponding discriminals. For components
9278 -- that are constrained by discriminants, their homologues in the
9279 -- corresponding record type must refer to the discriminants of that
9280 -- record, so we must apply a new renaming to subtypes_indications:
9281
76a1c25b 9282 -- protected discriminant => discriminal => record discriminant
9283
ee6ba406 9284 -- This replacement is not applied to default expressions, for which
9285 -- the discriminal is correct.
9286
57993a53 9287 if Has_Discriminants (Prot_Typ) then
ee6ba406 9288 declare
9289 Disc : Entity_Id;
9290 Decl : Node_Id;
57993a53 9291
ee6ba406 9292 begin
57993a53 9293 Disc := First_Discriminant (Prot_Typ);
ee6ba406 9294 Decl := First (Discriminant_Specifications (Rec_Decl));
ee6ba406 9295 while Present (Disc) loop
9296 Append_Elmt (Discriminal (Disc), Discr_Map);
9297 Append_Elmt (Defining_Identifier (Decl), Discr_Map);
9298 Next_Discriminant (Disc);
9299 Next (Decl);
9300 end loop;
9301 end;
9302 end if;
9303
9dfe12ae 9304 -- Fill in the component declarations
ee6ba406 9305
76a1c25b 9306 -- Add components for entry families. For each entry family, create an
9307 -- anonymous type declaration with the same size, and analyze the type.
ee6ba406 9308
57993a53 9309 Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ);
ee6ba406 9310
ee6ba406 9311 pragma Assert (Present (Pdef));
9312
9dfe12ae 9313 -- Add private field components
ee6ba406 9314
9315 if Present (Private_Declarations (Pdef)) then
9316 Priv := First (Private_Declarations (Pdef));
ee6ba406 9317 while Present (Priv) loop
ee6ba406 9318 if Nkind (Priv) = N_Component_Declaration then
0b16c8b7 9319 if not Static_Component_Size (Defining_Identifier (Priv)) then
9320
9321 -- When compiling for a restricted profile, the private
9322 -- components must have a static size. If not, this is an
9323 -- error for a single protected declaration, and rates a
9324 -- warning on a protected type declaration.
9325
9326 if not Comes_From_Source (Prot_Typ) then
a9f3e0f0 9327
9328 -- It's ok to be checking this restriction at expansion
9329 -- time, because this is only for the restricted profile,
9330 -- which is not subject to strict RM conformance, so it
9331 -- is OK to miss this check in -gnatc mode.
9332
0b16c8b7 9333 Check_Restriction (No_Implicit_Heap_Allocations, Priv);
31bee906 9334 Check_Restriction
9335 (No_Implicit_Protected_Object_Allocations, Priv);
0b16c8b7 9336
9337 elsif Restriction_Active (No_Implicit_Heap_Allocations) then
f31be12c 9338 if not Discriminated_Size (Defining_Identifier (Priv))
9339 then
f31be12c 9340 -- Any object of the type will be non-static.
9341
9342 Error_Msg_N ("component has non-static size??", Priv);
9343 Error_Msg_NE
2f06c88a 9344 ("\creation of protected object of type& will "
9345 & "violate restriction "
f31be12c 9346 & "No_Implicit_Heap_Allocations??", Priv, Prot_Typ);
9347 else
9348
9349 -- Object will be non-static if discriminants are.
9350
9351 Error_Msg_NE
9352 ("creation of protected object of type& with "
9353 & "non-static discriminants will violate"
9354 & " restriction No_Implicit_Heap_Allocations??",
9355 Priv, Prot_Typ);
9356 end if;
31bee906 9357
9358 -- Likewise for No_Implicit_Protected_Object_Allocations
9359
9360 elsif Restriction_Active
9361 (No_Implicit_Protected_Object_Allocations)
9362 then
9363 if not Discriminated_Size (Defining_Identifier (Priv))
9364 then
31bee906 9365 -- Any object of the type will be non-static.
9366
9367 Error_Msg_N ("component has non-static size??", Priv);
9368 Error_Msg_NE
2f06c88a 9369 ("\creation of protected object of type& will "
9370 & "violate restriction "
31bee906 9371 & "No_Implicit_Protected_Object_Allocations??",
9372 Priv, Prot_Typ);
9373 else
31bee906 9374 -- Object will be non-static if discriminants are.
9375
9376 Error_Msg_NE
9377 ("creation of protected object of type& with "
2f06c88a 9378 & "non-static discriminants will violate "
9379 & "restriction "
9380 & "No_Implicit_Protected_Object_Allocations??",
31bee906 9381 Priv, Prot_Typ);
9382 end if;
0b16c8b7 9383 end if;
9384 end if;
ee6ba406 9385
357dd91a 9386 -- The component definition consists of a subtype indication,
9387 -- or (in Ada 2005) an access definition. Make a copy of the
9388 -- proper definition.
9389
9390 declare
9391 Old_Comp : constant Node_Id := Component_Definition (Priv);
36e5d81f 9392 Oent : constant Entity_Id := Defining_Identifier (Priv);
36e5d81f 9393 Nent : constant Entity_Id :=
9e434a36 9394 Make_Defining_Identifier (Sloc (Oent),
9395 Chars => Chars (Oent));
2f06c88a 9396 New_Comp : Node_Id;
357dd91a 9397
9398 begin
9399 if Present (Subtype_Indication (Old_Comp)) then
9400 New_Comp :=
36e5d81f 9401 Make_Component_Definition (Sloc (Oent),
357dd91a 9402 Aliased_Present => False,
9403 Subtype_Indication =>
2f06c88a 9404 New_Copy_Tree
9405 (Subtype_Indication (Old_Comp), Discr_Map));
357dd91a 9406 else
9407 New_Comp :=
36e5d81f 9408 Make_Component_Definition (Sloc (Oent),
357dd91a 9409 Aliased_Present => False,
9410 Access_Definition =>
2f06c88a 9411 New_Copy_Tree
9412 (Access_Definition (Old_Comp), Discr_Map));
357dd91a 9413 end if;
9414
9415 New_Priv :=
9416 Make_Component_Declaration (Loc,
9e434a36 9417 Defining_Identifier => Nent,
357dd91a 9418 Component_Definition => New_Comp,
9e434a36 9419 Expression => Expression (Priv));
357dd91a 9420
36e5d81f 9421 Set_Has_Per_Object_Constraint (Nent,
9422 Has_Per_Object_Constraint (Oent));
9423
357dd91a 9424 Append_To (Cdecls, New_Priv);
9425 end;
ee6ba406 9426
9427 elsif Nkind (Priv) = N_Subprogram_Declaration then
9428
9429 -- Make the unprotected version of the subprogram available
9430 -- for expansion of intra object calls. There is need for
9431 -- a protected version only if the subprogram is an interrupt
9432 -- handler, otherwise this operation can only be called from
9433 -- within the body.
9434
9435 Sub :=
9436 Make_Subprogram_Declaration (Loc,
9437 Specification =>
9438 Build_Protected_Sub_Specification
57993a53 9439 (Priv, Prot_Typ, Unprotected_Mode));
ee6ba406 9440
9441 Insert_After (Current_Node, Sub);
9442 Analyze (Sub);
9443
9444 Set_Protected_Body_Subprogram
9445 (Defining_Unit_Name (Specification (Priv)),
9446 Defining_Unit_Name (Specification (Sub)));
e4401d9b 9447 Check_Inlining (Defining_Unit_Name (Specification (Priv)));
ee6ba406 9448 Current_Node := Sub;
d62940bf 9449
cb5f80c1 9450 Sub :=
9451 Make_Subprogram_Declaration (Loc,
9452 Specification =>
9453 Build_Protected_Sub_Specification
57993a53 9454 (Priv, Prot_Typ, Protected_Mode));
cb5f80c1 9455
9456 Insert_After (Current_Node, Sub);
9457 Analyze (Sub);
9458 Current_Node := Sub;
9459
ee6ba406 9460 if Is_Interrupt_Handler
9461 (Defining_Unit_Name (Specification (Priv)))
9462 then
ee6ba406 9463 if not Restricted_Profile then
9464 Register_Handler;
9465 end if;
9466 end if;
9467 end if;
9468
9469 Next (Priv);
9470 end loop;
9471 end if;
9472
4740c6a2 9473 -- Except for the lock-free implementation, append the _Object field
7413d80d 9474 -- with the right type to the component list. We need to compute the
9475 -- number of entries, and in some cases the number of Attach_Handler
9476 -- pragmas.
9477
9478 if not Lock_Free_Active then
9479 declare
7413d80d 9480 Entry_Count_Expr : constant Node_Id :=
9481 Build_Entry_Count_Expression
9482 (Prot_Typ, Cdecls, Loc);
2f06c88a 9483 Num_Attach_Handler : Int := 0;
9484 Protection_Subtype : Node_Id;
9485 Ritem : Node_Id;
7413d80d 9486
9487 begin
7413d80d 9488 if Has_Attach_Handler (Prot_Typ) then
9489 Ritem := First_Rep_Item (Prot_Typ);
9490 while Present (Ritem) loop
9491 if Nkind (Ritem) = N_Pragma
9492 and then Pragma_Name (Ritem) = Name_Attach_Handler
9493 then
9494 Num_Attach_Handler := Num_Attach_Handler + 1;
9495 end if;
9496
9497 Next_Rep_Item (Ritem);
9498 end loop;
588e7f97 9499 end if;
7413d80d 9500
588e7f97 9501 -- Determine the proper protection type. There are two special
9502 -- cases: 1) when the protected type has dynamic interrupt
9503 -- handlers, and 2) when it has static handlers and we use a
9504 -- restricted profile.
a16536f8 9505
588e7f97 9506 if Has_Attach_Handler (Prot_Typ)
9507 and then not Restricted_Profile
7413d80d 9508 then
9509 Protection_Subtype :=
588e7f97 9510 Make_Subtype_Indication (Loc,
f4623c89 9511 Subtype_Mark =>
83c6c069 9512 New_Occurrence_Of
f4623c89 9513 (RTE (RE_Static_Interrupt_Protection), Loc),
9514 Constraint =>
9515 Make_Index_Or_Discriminant_Constraint (Loc,
9516 Constraints => New_List (
9517 Entry_Count_Expr,
9518 Make_Integer_Literal (Loc, Num_Attach_Handler))));
7413d80d 9519
588e7f97 9520 elsif Has_Interrupt_Handler (Prot_Typ)
9521 and then not Restriction_Active (No_Dynamic_Attachment)
7413d80d 9522 then
588e7f97 9523 Protection_Subtype :=
9524 Make_Subtype_Indication (Loc,
f4623c89 9525 Subtype_Mark =>
83c6c069 9526 New_Occurrence_Of
f4623c89 9527 (RTE (RE_Dynamic_Interrupt_Protection), Loc),
9528 Constraint =>
9529 Make_Index_Or_Discriminant_Constraint (Loc,
9530 Constraints => New_List (Entry_Count_Expr)));
588e7f97 9531
9532 else
7413d80d 9533 case Corresponding_Runtime_Package (Prot_Typ) is
9534 when System_Tasking_Protected_Objects_Entries =>
9535 Protection_Subtype :=
9536 Make_Subtype_Indication (Loc,
9537 Subtype_Mark =>
83c6c069 9538 New_Occurrence_Of
a16536f8 9539 (RTE (RE_Protection_Entries), Loc),
9540 Constraint =>
9541 Make_Index_Or_Discriminant_Constraint (Loc,
7413d80d 9542 Constraints => New_List (Entry_Count_Expr)));
9543
9544 when System_Tasking_Protected_Objects_Single_Entry =>
9545 Protection_Subtype :=
83c6c069 9546 New_Occurrence_Of (RTE (RE_Protection_Entry), Loc);
7413d80d 9547
588e7f97 9548 when System_Tasking_Protected_Objects =>
9549 Protection_Subtype :=
83c6c069 9550 New_Occurrence_Of (RTE (RE_Protection), Loc);
588e7f97 9551
7413d80d 9552 when others =>
9553 raise Program_Error;
9554 end case;
7413d80d 9555 end if;
9556
9557 Object_Comp :=
9558 Make_Component_Declaration (Loc,
a16536f8 9559 Defining_Identifier =>
7413d80d 9560 Make_Defining_Identifier (Loc, Name_uObject),
9561 Component_Definition =>
9562 Make_Component_Definition (Loc,
9563 Aliased_Present => True,
9564 Subtype_Indication => Protection_Subtype));
9565 end;
9566
9567 -- Put the _Object component after the private component so that it
9568 -- be finalized early as required by 9.4 (20)
ee6ba406 9569
7413d80d 9570 Append_To (Cdecls, Object_Comp);
9571 end if;
ee6ba406 9572
9573 Insert_After (Current_Node, Rec_Decl);
9574 Current_Node := Rec_Decl;
9575
9576 -- Analyze the record declaration immediately after construction,
9577 -- because the initialization procedure is needed for single object
9578 -- declarations before the next entity is analyzed (the freeze call
9579 -- that generates this initialization procedure is found below).
9580
9581 Analyze (Rec_Decl, Suppress => All_Checks);
9582
9f373bb8 9583 -- Ada 2005 (AI-345): Construct the primitive entry wrappers before
d2a42b76 9584 -- the corresponding record is frozen. If any wrappers are generated,
9585 -- Current_Node is updated accordingly.
9f373bb8 9586
de54c5ab 9587 if Ada_Version >= Ada_2005 then
d2a42b76 9588 Build_Wrapper_Specs (Loc, Prot_Typ, Current_Node);
9f373bb8 9589 end if;
9590
ee6ba406 9591 -- Collect pointers to entry bodies and their barriers, to be placed
9592 -- in the Entry_Bodies_Array for the type. For each entry/family we
9593 -- add an expression to the aggregate which is the initial value of
9594 -- this array. The array is declared after all protected subprograms.
9595
57993a53 9596 if Has_Entries (Prot_Typ) then
d2a42b76 9597 Entries_Aggr := Make_Aggregate (Loc, Expressions => New_List);
ee6ba406 9598 else
9599 Entries_Aggr := Empty;
9600 end if;
9601
76a1c25b 9602 -- Build two new procedure specifications for each protected subprogram;
9603 -- one to call from outside the object and one to call from inside.
9604 -- Build a barrier function and an entry body action procedure
9605 -- specification for each protected entry. Initialize the entry body
9606 -- array. If subprogram is flagged as eliminated, do not generate any
9607 -- internal operations.
ee6ba406 9608
9609 E_Count := 0;
ee6ba406 9610 Comp := First (Visible_Declarations (Pdef));
ee6ba406 9611 while Present (Comp) loop
d3f21ab5 9612 if Nkind (Comp) = N_Subprogram_Declaration then
ee6ba406 9613 Sub :=
9614 Make_Subprogram_Declaration (Loc,
9615 Specification =>
9616 Build_Protected_Sub_Specification
57993a53 9617 (Comp, Prot_Typ, Unprotected_Mode));
ee6ba406 9618
9619 Insert_After (Current_Node, Sub);
9620 Analyze (Sub);
9621
9622 Set_Protected_Body_Subprogram
9623 (Defining_Unit_Name (Specification (Comp)),
9624 Defining_Unit_Name (Specification (Sub)));
bb3b440a 9625 Check_Inlining (Defining_Unit_Name (Specification (Comp)));
ee6ba406 9626
76a1c25b 9627 -- Make the protected version of the subprogram available for
9628 -- expansion of external calls.
ee6ba406 9629
9630 Current_Node := Sub;
9631
9632 Sub :=
9633 Make_Subprogram_Declaration (Loc,
9634 Specification =>
9635 Build_Protected_Sub_Specification
57993a53 9636 (Comp, Prot_Typ, Protected_Mode));
ee6ba406 9637
9638 Insert_After (Current_Node, Sub);
9639 Analyze (Sub);
d62940bf 9640
ee6ba406 9641 Current_Node := Sub;
9642
d62940bf 9643 -- Generate an overriding primitive operation specification for
36b938a3 9644 -- this subprogram if the protected type implements an interface.
d62940bf 9645
de54c5ab 9646 if Ada_Version >= Ada_2005
d62940bf 9647 and then
a652dd51 9648 Present (Interfaces (Corresponding_Record_Type (Prot_Typ)))
d62940bf 9649 then
9650 Sub :=
9651 Make_Subprogram_Declaration (Loc,
9652 Specification =>
9653 Build_Protected_Sub_Specification
57993a53 9654 (Comp, Prot_Typ, Dispatching_Mode));
d62940bf 9655
9656 Insert_After (Current_Node, Sub);
9657 Analyze (Sub);
9658
9659 Current_Node := Sub;
9660 end if;
9661
76a1c25b 9662 -- If a pragma Interrupt_Handler applies, build and add a call to
9663 -- Register_Interrupt_Handler to the freezing actions of the
9664 -- protected version (Current_Node) of the subprogram:
9665
ee6ba406 9666 -- system.interrupts.register_interrupt_handler
9667 -- (prot_procP'address);
9668
9669 if not Restricted_Profile
9670 and then Is_Interrupt_Handler
d62940bf 9671 (Defining_Unit_Name (Specification (Comp)))
ee6ba406 9672 then
9673 Register_Handler;
9674 end if;
9675
9676 elsif Nkind (Comp) = N_Entry_Declaration then
4740c6a2 9677 Expand_Entry_Declaration (Comp);
ee6ba406 9678 end if;
9679
9680 Next (Comp);
9681 end loop;
9682
9683 -- If there are some private entry declarations, expand it as if they
9684 -- were visible entries.
9685
9686 if Present (Private_Declarations (Pdef)) then
9687 Comp := First (Private_Declarations (Pdef));
ee6ba406 9688 while Present (Comp) loop
9689 if Nkind (Comp) = N_Entry_Declaration then
4740c6a2 9690 Expand_Entry_Declaration (Comp);
ee6ba406 9691 end if;
9692
9693 Next (Comp);
9694 end loop;
9695 end if;
9696
9697 -- Emit declaration for Entry_Bodies_Array, now that the addresses of
9698 -- all protected subprograms have been collected.
9699
57993a53 9700 if Has_Entries (Prot_Typ) then
9701 Body_Id :=
9702 Make_Defining_Identifier (Sloc (Prot_Typ),
9703 Chars => New_External_Name (Chars (Prot_Typ), 'A'));
ee6ba406 9704
57993a53 9705 case Corresponding_Runtime_Package (Prot_Typ) is
70966f50 9706 when System_Tasking_Protected_Objects_Entries =>
2f06c88a 9707 Body_Arr :=
9708 Make_Object_Declaration (Loc,
9709 Defining_Identifier => Body_Id,
9710 Aliased_Present => True,
9711 Object_Definition =>
9712 Make_Subtype_Indication (Loc,
9713 Subtype_Mark =>
9714 New_Occurrence_Of
9715 (RTE (RE_Protected_Entry_Body_Array), Loc),
9716 Constraint =>
9717 Make_Index_Or_Discriminant_Constraint (Loc,
9718 Constraints => New_List (
9719 Make_Range (Loc,
9720 Make_Integer_Literal (Loc, 1),
9721 Make_Integer_Literal (Loc, E_Count))))),
9722 Expression => Entries_Aggr);
70966f50 9723
9724 when System_Tasking_Protected_Objects_Single_Entry =>
2f06c88a 9725 Body_Arr :=
9726 Make_Object_Declaration (Loc,
9727 Defining_Identifier => Body_Id,
9728 Aliased_Present => True,
9729 Object_Definition =>
9730 New_Occurrence_Of (RTE (RE_Entry_Body), Loc),
9731 Expression => Remove_Head (Expressions (Entries_Aggr)));
ee6ba406 9732
70966f50 9733 when others =>
9734 raise Program_Error;
9735 end case;
ee6ba406 9736
76a1c25b 9737 -- A pointer to this array will be placed in the corresponding record
9738 -- by its initialization procedure so this needs to be analyzed here.
ee6ba406 9739
9740 Insert_After (Current_Node, Body_Arr);
9741 Current_Node := Body_Arr;
9742 Analyze (Body_Arr);
9743
57993a53 9744 Set_Entry_Bodies_Array (Prot_Typ, Body_Id);
ee6ba406 9745
9746 -- Finally, build the function that maps an entry index into the
9747 -- corresponding body. A pointer to this function is placed in each
9748 -- object of the type. Except for a ravenscar-like profile (no abort,
9749 -- no entry queue, 1 entry)
9750
57993a53 9751 if Corresponding_Runtime_Package (Prot_Typ) =
9752 System_Tasking_Protected_Objects_Entries
ee6ba406 9753 then
9754 Sub :=
9755 Make_Subprogram_Declaration (Loc,
57993a53 9756 Specification => Build_Find_Body_Index_Spec (Prot_Typ));
ee6ba406 9757 Insert_After (Current_Node, Sub);
9758 Analyze (Sub);
9759 end if;
9760 end if;
9761 end Expand_N_Protected_Type_Declaration;
9762
9763 --------------------------------
9764 -- Expand_N_Requeue_Statement --
9765 --------------------------------
9766
5809835d 9767 -- A non-dispatching requeue statement is expanded into one of four GNARLI
9768 -- operations, depending on the source and destination (task or protected
9769 -- object). A dispatching requeue statement is expanded into a call to the
9770 -- predefined primitive _Disp_Requeue. In addition, code is generated to
9771 -- jump around the remainder of processing for the original entry and, if
9772 -- the destination is (different) protected object, to attempt to service
9773 -- it. The following illustrates the various cases:
ee6ba406 9774
9775 -- procedure entE
9776 -- (O : System.Address;
9777 -- P : System.Address;
9778 -- E : Protected_Entry_Index)
9779 -- is
9780 -- <discriminant renamings>
9781 -- <private object renamings>
9782 -- type poVP is access poV;
5809835d 9783 -- _object : ptVP := ptVP!(O);
9dfe12ae 9784
ee6ba406 9785 -- begin
9786 -- begin
9787 -- <start of statement sequence for entry>
9dfe12ae 9788
ee6ba406 9789 -- -- Requeue from one protected entry body to another protected
9790 -- -- entry.
9dfe12ae 9791
ee6ba406 9792 -- Requeue_Protected_Entry (
9793 -- _object._object'Access,
9794 -- new._object'Access,
9795 -- E,
9796 -- Abort_Present);
9797 -- return;
9dfe12ae 9798
ee6ba406 9799 -- <some more of the statement sequence for entry>
9dfe12ae 9800
2866d595 9801 -- -- Requeue from an entry body to a task entry
9dfe12ae 9802
ee6ba406 9803 -- Requeue_Protected_To_Task_Entry (
9804 -- New._task_id,
9805 -- E,
9806 -- Abort_Present);
9807 -- return;
9dfe12ae 9808
ee6ba406 9809 -- <rest of statement sequence for entry>
5809835d 9810 -- Complete_Entry_Body (_object._object);
9dfe12ae 9811
ee6ba406 9812 -- exception
9813 -- when all others =>
9814 -- Exceptional_Complete_Entry_Body (
5809835d 9815 -- _object._object, Get_GNAT_Exception);
ee6ba406 9816 -- end;
9817 -- end entE;
9818
2866d595 9819 -- Requeue of a task entry call to a task entry
9dfe12ae 9820
ee6ba406 9821 -- Accept_Call (E, Ann);
9822 -- <start of statement sequence for accept statement>
9823 -- Requeue_Task_Entry (New._task_id, E, Abort_Present);
9824 -- goto Lnn;
9825 -- <rest of statement sequence for accept statement>
9826 -- <<Lnn>>
9827 -- Complete_Rendezvous;
9dfe12ae 9828
ee6ba406 9829 -- exception
9830 -- when all others =>
9831 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9832
2866d595 9833 -- Requeue of a task entry call to a protected entry
9dfe12ae 9834
ee6ba406 9835 -- Accept_Call (E, Ann);
9836 -- <start of statement sequence for accept statement>
9837 -- Requeue_Task_To_Protected_Entry (
9838 -- new._object'Access,
9839 -- E,
9840 -- Abort_Present);
9841 -- newS (new, Pnn);
9842 -- goto Lnn;
9843 -- <rest of statement sequence for accept statement>
9844 -- <<Lnn>>
9845 -- Complete_Rendezvous;
9dfe12ae 9846
ee6ba406 9847 -- exception
9848 -- when all others =>
9849 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9850
9a479e51 9851 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9852 -- marked by pragma Implemented (XXX, By_Entry).
9853
9854 -- The requeue is inside a protected entry:
5809835d 9855
9856 -- procedure entE
9857 -- (O : System.Address;
9858 -- P : System.Address;
9859 -- E : Protected_Entry_Index)
9860 -- is
9861 -- <discriminant renamings>
9862 -- <private object renamings>
9863 -- type poVP is access poV;
9864 -- _object : ptVP := ptVP!(O);
9865
9866 -- begin
9867 -- begin
9868 -- <start of statement sequence for entry>
9869
9870 -- _Disp_Requeue
9871 -- (<interface class-wide object>,
9872 -- True,
9873 -- _object'Address,
9874 -- Ada.Tags.Get_Offset_Index
9875 -- (Tag (_object),
9876 -- <interface dispatch table index of target entry>),
9877 -- Abort_Present);
9878 -- return;
9879
9880 -- <rest of statement sequence for entry>
9881 -- Complete_Entry_Body (_object._object);
9882
9883 -- exception
9884 -- when all others =>
9885 -- Exceptional_Complete_Entry_Body (
9886 -- _object._object, Get_GNAT_Exception);
9887 -- end;
9888 -- end entE;
9889
9a479e51 9890 -- The requeue is inside a task entry:
5809835d 9891
9a479e51 9892 -- Accept_Call (E, Ann);
5809835d 9893 -- <start of statement sequence for accept statement>
9894 -- _Disp_Requeue
9895 -- (<interface class-wide object>,
9896 -- False,
9897 -- null,
9898 -- Ada.Tags.Get_Offset_Index
9899 -- (Tag (_object),
9900 -- <interface dispatch table index of target entrt>),
9901 -- Abort_Present);
9902 -- newS (new, Pnn);
9903 -- goto Lnn;
9904 -- <rest of statement sequence for accept statement>
9905 -- <<Lnn>>
9906 -- Complete_Rendezvous;
9907
9908 -- exception
9909 -- when all others =>
9910 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9911
9a479e51 9912 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9913 -- marked by pragma Implemented (XXX, By_Protected_Procedure). The requeue
9914 -- statement is replaced by a dispatching call with actual parameters taken
9915 -- from the inner-most accept statement or entry body.
9916
9917 -- Target.Primitive (Param1, ..., ParamN);
9918
9919 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
98108069 9920 -- marked by pragma Implemented (XXX, By_Any | Optional) or not marked
9921 -- at all.
9a479e51 9922
9923 -- declare
9924 -- S : constant Offset_Index :=
9925 -- Get_Offset_Index (Tag (Concval), DT_Position (Ename));
9926 -- C : constant Prim_Op_Kind := Get_Prim_Op_Kind (Tag (Concval), S);
9927
9928 -- begin
9929 -- if C = POK_Protected_Entry
9930 -- or else C = POK_Task_Entry
9931 -- then
9932 -- <statements for dispatching requeue>
9933
9934 -- elsif C = POK_Protected_Procedure then
9935 -- <dispatching call equivalent>
9936
9937 -- else
9938 -- raise Program_Error;
9939 -- end if;
9940 -- end;
ee6ba406 9941
9942 procedure Expand_N_Requeue_Statement (N : Node_Id) is
9a479e51 9943 Loc : constant Source_Ptr := Sloc (N);
9944 Conc_Typ : Entity_Id;
9945 Concval : Node_Id;
9946 Ename : Node_Id;
9947 Index : Node_Id;
9948 Old_Typ : Entity_Id;
9949
9950 function Build_Dispatching_Call_Equivalent return Node_Id;
9951 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9952 -- the form Concval.Ename. It is statically known that Ename is allowed
9953 -- to be implemented by a protected procedure. Create a dispatching call
9954 -- equivalent of Concval.Ename taking the actual parameters from the
9955 -- inner-most accept statement or entry body.
9956
9957 function Build_Dispatching_Requeue return Node_Id;
9958 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9959 -- the form Concval.Ename. It is statically known that Ename is allowed
9960 -- to be implemented by a protected or a task entry. Create a call to
9961 -- primitive _Disp_Requeue which handles the low-level actions.
9962
9963 function Build_Dispatching_Requeue_To_Any return Node_Id;
9964 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9965 -- the form Concval.Ename. Ename is either marked by pragma Implemented
98108069 9966 -- (XXX, By_Any | Optional) or not marked at all. Create a block which
9967 -- determines at runtime whether Ename denotes an entry or a procedure
9968 -- and perform the appropriate kind of dispatching select.
9a479e51 9969
9970 function Build_Normal_Requeue return Node_Id;
9971 -- N denotes a non-dispatching requeue statement to either a task or a
9972 -- protected entry. Build the appropriate runtime call to perform the
9973 -- action.
9974
9975 function Build_Skip_Statement (Search : Node_Id) return Node_Id;
9976 -- For a protected entry, create a return statement to skip the rest of
9977 -- the entry body. Otherwise, create a goto statement to skip the rest
9978 -- of a task accept statement. The lookup for the enclosing entry body
9979 -- or accept statement starts from Search.
ee6ba406 9980
9a479e51 9981 ---------------------------------------
9982 -- Build_Dispatching_Call_Equivalent --
9983 ---------------------------------------
ee6ba406 9984
9a479e51 9985 function Build_Dispatching_Call_Equivalent return Node_Id is
9986 Call_Ent : constant Entity_Id := Entity (Ename);
9987 Obj : constant Node_Id := Original_Node (Concval);
9988 Acc_Ent : Node_Id;
9989 Actuals : List_Id;
9990 Formal : Node_Id;
9991 Formals : List_Id;
ee6ba406 9992
9a479e51 9993 begin
9994 -- Climb the parent chain looking for the inner-most entry body or
9995 -- accept statement.
ee6ba406 9996
9a479e51 9997 Acc_Ent := N;
9998 while Present (Acc_Ent)
9999 and then not Nkind_In (Acc_Ent, N_Accept_Statement,
10000 N_Entry_Body)
10001 loop
10002 Acc_Ent := Parent (Acc_Ent);
10003 end loop;
ee6ba406 10004
9a479e51 10005 -- A requeue statement should be housed inside an entry body or an
10006 -- accept statement at some level. If this is not the case, then the
10007 -- tree is malformed.
ee6ba406 10008
9a479e51 10009 pragma Assert (Present (Acc_Ent));
ee6ba406 10010
9a479e51 10011 -- Recover the list of formal parameters
ee6ba406 10012
9a479e51 10013 if Nkind (Acc_Ent) = N_Entry_Body then
10014 Acc_Ent := Entry_Body_Formal_Part (Acc_Ent);
10015 end if;
ee6ba406 10016
9a479e51 10017 Formals := Parameter_Specifications (Acc_Ent);
10018
10019 -- Create the actual parameters for the dispatching call. These are
10020 -- simply copies of the entry body or accept statement formals in the
10021 -- same order as they appear.
10022
10023 Actuals := No_List;
10024
10025 if Present (Formals) then
10026 Actuals := New_List;
10027 Formal := First (Formals);
10028 while Present (Formal) loop
10029 Append_To (Actuals,
10030 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
10031 Next (Formal);
10032 end loop;
10033 end if;
5809835d 10034
10035 -- Generate:
9a479e51 10036 -- Obj.Call_Ent (Actuals);
10037
10038 return
10039 Make_Procedure_Call_Statement (Loc,
10040 Name =>
10041 Make_Selected_Component (Loc,
55868293 10042 Prefix => Make_Identifier (Loc, Chars (Obj)),
10043 Selector_Name => Make_Identifier (Loc, Chars (Call_Ent))),
9a479e51 10044
10045 Parameter_Associations => Actuals);
10046 end Build_Dispatching_Call_Equivalent;
10047
10048 -------------------------------
10049 -- Build_Dispatching_Requeue --
10050 -------------------------------
10051
10052 function Build_Dispatching_Requeue return Node_Id is
10053 Params : constant List_Id := New_List;
10054
10055 begin
10056 -- Process the "with abort" parameter
10057
10058 Prepend_To (Params,
83c6c069 10059 New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
9a479e51 10060
10061 -- Process the entry wrapper's position in the primary dispatch
10062 -- table parameter. Generate:
10063
caad910a 10064 -- Ada.Tags.Get_Entry_Index
30fe3fdc 10065 -- (T => To_Tag_Ptr (Obj'Address).all,
10066 -- Position =>
10067 -- Ada.Tags.Get_Offset_Index
10068 -- (Ada.Tags.Tag (Concval),
10069 -- <interface dispatch table position of Ename>));
caad910a 10070
10071 -- Note that Obj'Address is recursively expanded into a call to
30fe3fdc 10072 -- Base_Address (Obj).
5809835d 10073
6cb4b973 10074 if Tagged_Type_Expansion then
10075 Prepend_To (Params,
10076 Make_Function_Call (Loc,
83c6c069 10077 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
6cb4b973 10078 Parameter_Associations => New_List (
caad910a 10079
10080 Make_Explicit_Dereference (Loc,
10081 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
10082 Make_Attribute_Reference (Loc,
10083 Prefix => New_Copy_Tree (Concval),
10084 Attribute_Name => Name_Address))),
10085
10086 Make_Function_Call (Loc,
83c6c069 10087 Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
caad910a 10088 Parameter_Associations => New_List (
10089 Unchecked_Convert_To (RTE (RE_Tag), Concval),
10090 Make_Integer_Literal (Loc,
10091 DT_Position (Entity (Ename))))))));
6cb4b973 10092
10093 -- VM targets
10094
10095 else
10096 Prepend_To (Params,
caad910a 10097 Make_Function_Call (Loc,
83c6c069 10098 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
6cb4b973 10099 Parameter_Associations => New_List (
b860aaec 10100
6cb4b973 10101 Make_Attribute_Reference (Loc,
b860aaec 10102 Prefix => Concval,
6cb4b973 10103 Attribute_Name => Name_Tag),
10104
caad910a 10105 Make_Function_Call (Loc,
83c6c069 10106 Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
6cb4b973 10107
caad910a 10108 Parameter_Associations => New_List (
10109
10110 -- Obj_Tag
10111
10112 Make_Attribute_Reference (Loc,
10113 Prefix => Concval,
10114 Attribute_Name => Name_Tag),
10115
10116 -- Tag_Typ
10117
10118 Make_Attribute_Reference (Loc,
83c6c069 10119 Prefix => New_Occurrence_Of (Etype (Concval), Loc),
caad910a 10120 Attribute_Name => Name_Tag),
6cb4b973 10121
caad910a 10122 -- Position
6cb4b973 10123
caad910a 10124 Make_Integer_Literal (Loc,
10125 DT_Position (Entity (Ename))))))));
6cb4b973 10126 end if;
9a479e51 10127
10128 -- Specific actuals for protected to XXX requeue
5809835d 10129
10130 if Is_Protected_Type (Old_Typ) then
10131 Prepend_To (Params,
10132 Make_Attribute_Reference (Loc, -- _object'Address
10133 Prefix =>
10134 Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
9a479e51 10135 Attribute_Name => Name_Address));
10136
5809835d 10137 Prepend_To (Params, -- True
83c6c069 10138 New_Occurrence_Of (Standard_True, Loc));
5809835d 10139
9a479e51 10140 -- Specific actuals for task to XXX requeue
ee6ba406 10141
5809835d 10142 else
10143 pragma Assert (Is_Task_Type (Old_Typ));
10144
10145 Prepend_To (Params, -- null
83c6c069 10146 New_Occurrence_Of (RTE (RE_Null_Address), Loc));
9a479e51 10147
5809835d 10148 Prepend_To (Params, -- False
83c6c069 10149 New_Occurrence_Of (Standard_False, Loc));
5809835d 10150 end if;
10151
9a479e51 10152 -- Add the object parameter
5809835d 10153
10154 Prepend_To (Params, New_Copy_Tree (Concval));
10155
9a479e51 10156 -- Generate:
10157 -- _Disp_Requeue (<Params>);
5809835d 10158
6d852e2b 10159 -- Find entity for Disp_Requeue operation, which belongs to
10160 -- the type and may not be directly visible.
10161
10162 declare
10163 Elmt : Elmt_Id;
10164 Op : Entity_Id;
10165
10166 begin
10167 Elmt := First_Elmt (Primitive_Operations (Etype (Conc_Typ)));
10168 while Present (Elmt) loop
10169 Op := Node (Elmt);
10170 exit when Chars (Op) = Name_uDisp_Requeue;
10171 Next_Elmt (Elmt);
10172 end loop;
10173
10174 return
10175 Make_Procedure_Call_Statement (Loc,
10176 Name => New_Occurrence_Of (Op, Loc),
10177 Parameter_Associations => Params);
10178 end;
9a479e51 10179 end Build_Dispatching_Requeue;
10180
10181 --------------------------------------
10182 -- Build_Dispatching_Requeue_To_Any --
10183 --------------------------------------
10184
10185 function Build_Dispatching_Requeue_To_Any return Node_Id is
10186 Call_Ent : constant Entity_Id := Entity (Ename);
10187 Obj : constant Node_Id := Original_Node (Concval);
10188 Skip : constant Node_Id := Build_Skip_Statement (N);
10189 C : Entity_Id;
10190 Decls : List_Id;
10191 S : Entity_Id;
10192 Stmts : List_Id;
10193
10194 begin
10195 Decls := New_List;
10196 Stmts := New_List;
10197
10198 -- Dispatch table slot processing, generate:
10199 -- S : Integer;
10200
10201 S := Build_S (Loc, Decls);
10202
10203 -- Call kind processing, generate:
10204 -- C : Ada.Tags.Prim_Op_Kind;
10205
10206 C := Build_C (Loc, Decls);
5809835d 10207
9a479e51 10208 -- Generate:
10209 -- S := Ada.Tags.Get_Offset_Index
10210 -- (Ada.Tags.Tag (Obj), DT_Position (Call_Ent));
10211
10212 Append_To (Stmts, Build_S_Assignment (Loc, S, Obj, Call_Ent));
10213
10214 -- Generate:
10215 -- _Disp_Get_Prim_Op_Kind (Obj, S, C);
10216
10217 Append_To (Stmts,
10218 Make_Procedure_Call_Statement (Loc,
10219 Name =>
83c6c069 10220 New_Occurrence_Of (
9a479e51 10221 Find_Prim_Op (Etype (Etype (Obj)),
10222 Name_uDisp_Get_Prim_Op_Kind),
10223 Loc),
10224 Parameter_Associations => New_List (
10225 New_Copy_Tree (Obj),
83c6c069 10226 New_Occurrence_Of (S, Loc),
10227 New_Occurrence_Of (C, Loc))));
9a479e51 10228
10229 Append_To (Stmts,
10230
10231 -- if C = POK_Protected_Entry
10232 -- or else C = POK_Task_Entry
10233 -- then
10234
85377c9b 10235 Make_Implicit_If_Statement (N,
9a479e51 10236 Condition =>
10237 Make_Op_Or (Loc,
10238 Left_Opnd =>
10239 Make_Op_Eq (Loc,
10240 Left_Opnd =>
83c6c069 10241 New_Occurrence_Of (C, Loc),
9a479e51 10242 Right_Opnd =>
83c6c069 10243 New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
9a479e51 10244
10245 Right_Opnd =>
10246 Make_Op_Eq (Loc,
10247 Left_Opnd =>
83c6c069 10248 New_Occurrence_Of (C, Loc),
9a479e51 10249 Right_Opnd =>
83c6c069 10250 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
9a479e51 10251
10252 -- Dispatching requeue equivalent
10253
10254 Then_Statements => New_List (
10255 Build_Dispatching_Requeue,
10256 Skip),
10257
10258 -- elsif C = POK_Protected_Procedure then
10259
10260 Elsif_Parts => New_List (
10261 Make_Elsif_Part (Loc,
10262 Condition =>
10263 Make_Op_Eq (Loc,
10264 Left_Opnd =>
83c6c069 10265 New_Occurrence_Of (C, Loc),
9a479e51 10266 Right_Opnd =>
83c6c069 10267 New_Occurrence_Of (
9a479e51 10268 RTE (RE_POK_Protected_Procedure), Loc)),
10269
10270 -- Dispatching call equivalent
10271
10272 Then_Statements => New_List (
10273 Build_Dispatching_Call_Equivalent))),
10274
10275 -- else
10276 -- raise Program_Error;
10277 -- end if;
10278
10279 Else_Statements => New_List (
10280 Make_Raise_Program_Error (Loc,
10281 Reason => PE_Explicit_Raise))));
10282
10283 -- Wrap everything into a block
10284
10285 return
10286 Make_Block_Statement (Loc,
10287 Declarations => Decls,
10288 Handled_Statement_Sequence =>
10289 Make_Handled_Sequence_Of_Statements (Loc,
10290 Statements => Stmts));
10291 end Build_Dispatching_Requeue_To_Any;
10292
10293 --------------------------
10294 -- Build_Normal_Requeue --
10295 --------------------------
10296
10297 function Build_Normal_Requeue return Node_Id is
10298 Params : constant List_Id := New_List;
10299 Param : Node_Id;
10300 RT_Call : Node_Id;
10301
10302 begin
10303 -- Process the "with abort" parameter
5809835d 10304
10305 Prepend_To (Params,
83c6c069 10306 New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
5809835d 10307
9a479e51 10308 -- Add the index expression to the parameters. It is common among all
10309 -- four cases.
ee6ba406 10310
9a479e51 10311 Prepend_To (Params,
10312 Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
5809835d 10313
9a479e51 10314 if Is_Protected_Type (Old_Typ) then
10315 declare
10316 Self_Param : Node_Id;
ee6ba406 10317
9a479e51 10318 begin
10319 Self_Param :=
ee6ba406 10320 Make_Attribute_Reference (Loc,
5809835d 10321 Prefix =>
9a479e51 10322 Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
5809835d 10323 Attribute_Name =>
10324 Name_Unchecked_Access);
10325
9a479e51 10326 -- Protected to protected requeue
5809835d 10327
9a479e51 10328 if Is_Protected_Type (Conc_Typ) then
10329 RT_Call :=
83c6c069 10330 New_Occurrence_Of (
9a479e51 10331 RTE (RE_Requeue_Protected_Entry), Loc);
ee6ba406 10332
9a479e51 10333 Param :=
10334 Make_Attribute_Reference (Loc,
10335 Prefix =>
10336 Concurrent_Ref (Concval),
10337 Attribute_Name =>
10338 Name_Unchecked_Access);
ee6ba406 10339
9a479e51 10340 -- Protected to task requeue
10341
10342 else pragma Assert (Is_Task_Type (Conc_Typ));
10343 RT_Call :=
83c6c069 10344 New_Occurrence_Of (
9a479e51 10345 RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
10346
10347 Param := Concurrent_Ref (Concval);
10348 end if;
10349
10350 Prepend_To (Params, Param);
10351 Prepend_To (Params, Self_Param);
10352 end;
10353
10354 else pragma Assert (Is_Task_Type (Old_Typ));
5809835d 10355
10356 -- Task to protected requeue
10357
10358 if Is_Protected_Type (Conc_Typ) then
9a479e51 10359 RT_Call :=
83c6c069 10360 New_Occurrence_Of (
5809835d 10361 RTE (RE_Requeue_Task_To_Protected_Entry), Loc);
10362
9a479e51 10363 Param :=
5809835d 10364 Make_Attribute_Reference (Loc,
10365 Prefix =>
9a479e51 10366 Concurrent_Ref (Concval),
5809835d 10367 Attribute_Name =>
10368 Name_Unchecked_Access);
10369
10370 -- Task to task requeue
10371
9a479e51 10372 else pragma Assert (Is_Task_Type (Conc_Typ));
10373 RT_Call :=
83c6c069 10374 New_Occurrence_Of (RTE (RE_Requeue_Task_Entry), Loc);
9a479e51 10375
10376 Param := Concurrent_Ref (Concval);
5809835d 10377 end if;
10378
9a479e51 10379 Prepend_To (Params, Param);
ee6ba406 10380 end if;
ee6ba406 10381
9a479e51 10382 return
10383 Make_Procedure_Call_Statement (Loc,
10384 Name => RT_Call,
10385 Parameter_Associations => Params);
10386 end Build_Normal_Requeue;
ee6ba406 10387
9a479e51 10388 --------------------------
10389 -- Build_Skip_Statement --
10390 --------------------------
ee6ba406 10391
9a479e51 10392 function Build_Skip_Statement (Search : Node_Id) return Node_Id is
10393 Skip_Stmt : Node_Id;
ee6ba406 10394
9a479e51 10395 begin
10396 -- Build a return statement to skip the rest of the entire body
ee6ba406 10397
9a479e51 10398 if Is_Protected_Type (Old_Typ) then
10399 Skip_Stmt := Make_Simple_Return_Statement (Loc);
ee6ba406 10400
ee6ba406 10401 -- If the requeue is within a task, find the end label of the
9a479e51 10402 -- enclosing accept statement and create a goto statement to it.
ee6ba406 10403
9a479e51 10404 else
10405 declare
10406 Acc : Node_Id;
10407 Label : Node_Id;
ee6ba406 10408
9a479e51 10409 begin
10410 -- Climb the parent chain looking for the enclosing accept
10411 -- statement.
10412
10413 Acc := Parent (Search);
10414 while Present (Acc)
10415 and then Nkind (Acc) /= N_Accept_Statement
10416 loop
10417 Acc := Parent (Acc);
10418 end loop;
ee6ba406 10419
9a479e51 10420 -- The last statement is the second label used for completing
10421 -- the rendezvous the usual way. The label we are looking for
10422 -- is right before it.
ee6ba406 10423
9a479e51 10424 Label :=
10425 Prev (Last (Statements (Handled_Statement_Sequence (Acc))));
ee6ba406 10426
9a479e51 10427 pragma Assert (Nkind (Label) = N_Label);
ee6ba406 10428
9a479e51 10429 -- Generate a goto statement to skip the rest of the accept
10430
10431 Skip_Stmt :=
10432 Make_Goto_Statement (Loc,
10433 Name =>
10434 New_Occurrence_Of (Entity (Identifier (Label)), Loc));
10435 end;
10436 end if;
10437
10438 Set_Analyzed (Skip_Stmt);
10439
10440 return Skip_Stmt;
10441 end Build_Skip_Statement;
10442
10443 -- Start of processing for Expand_N_Requeue_Statement
10444
10445 begin
10446 -- Extract the components of the entry call
10447
10448 Extract_Entry (N, Concval, Ename, Index);
10449 Conc_Typ := Etype (Concval);
10450
6d852e2b 10451 -- If the prefix is an access to class-wide type, dereference to get
10452 -- object and entry type.
10453
10454 if Is_Access_Type (Conc_Typ) then
10455 Conc_Typ := Designated_Type (Conc_Typ);
10456 Rewrite (Concval,
10457 Make_Explicit_Dereference (Loc, Relocate_Node (Concval)));
10458 Analyze_And_Resolve (Concval, Conc_Typ);
10459 end if;
10460
9a479e51 10461 -- Examine the scope stack in order to find nearest enclosing protected
10462 -- or task type. This will constitute our invocation source.
10463
10464 Old_Typ := Current_Scope;
10465 while Present (Old_Typ)
10466 and then not Is_Protected_Type (Old_Typ)
10467 and then not Is_Task_Type (Old_Typ)
10468 loop
10469 Old_Typ := Scope (Old_Typ);
10470 end loop;
ee6ba406 10471
9a479e51 10472 -- Ada 2012 (AI05-0030): We have a dispatching requeue of the form
10473 -- Concval.Ename where the type of Concval is class-wide concurrent
10474 -- interface.
10475
10476 if Ada_Version >= Ada_2012
10477 and then Present (Concval)
10478 and then Is_Class_Wide_Type (Conc_Typ)
10479 and then Is_Concurrent_Interface (Conc_Typ)
10480 then
10481 declare
10482 Has_Impl : Boolean := False;
10483 Impl_Kind : Name_Id := No_Name;
10484
10485 begin
10486 -- Check whether the Ename is flagged by pragma Implemented
10487
10488 if Has_Rep_Pragma (Entity (Ename), Name_Implemented) then
10489 Has_Impl := True;
10490 Impl_Kind := Implementation_Kind (Entity (Ename));
10491 end if;
10492
10493 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10494 -- an entry. Create a call to predefined primitive _Disp_Requeue.
10495
c0688d2b 10496 if Has_Impl and then Impl_Kind = Name_By_Entry then
9a479e51 10497 Rewrite (N, Build_Dispatching_Requeue);
10498 Analyze (N);
10499 Insert_After (N, Build_Skip_Statement (N));
10500
10501 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10502 -- a protected procedure. In this case the requeue is transformed
10503 -- into a dispatching call.
10504
10505 elsif Has_Impl
10506 and then Impl_Kind = Name_By_Protected_Procedure
10507 then
10508 Rewrite (N, Build_Dispatching_Call_Equivalent);
10509 Analyze (N);
10510
10511 -- The procedure_or_entry_NAME's implementation kind is either
98108069 10512 -- By_Any, Optional, or pragma Implemented was not applied at all.
10513 -- In this case a runtime test determines whether Ename denotes an
10514 -- entry or a protected procedure and performs the appropriate
10515 -- call.
ee6ba406 10516
9a479e51 10517 else
10518 Rewrite (N, Build_Dispatching_Requeue_To_Any);
10519 Analyze (N);
10520 end if;
10521 end;
10522
10523 -- Processing for regular (non-dispatching) requeues
10524
10525 else
10526 Rewrite (N, Build_Normal_Requeue);
10527 Analyze (N);
10528 Insert_After (N, Build_Skip_Statement (N));
10529 end if;
ee6ba406 10530 end Expand_N_Requeue_Statement;
10531
10532 -------------------------------
10533 -- Expand_N_Selective_Accept --
10534 -------------------------------
10535
10536 procedure Expand_N_Selective_Accept (N : Node_Id) is
10537 Loc : constant Source_Ptr := Sloc (N);
10538 Alts : constant List_Id := Select_Alternatives (N);
10539
9dfe12ae 10540 -- Note: in the below declarations a lot of new lists are allocated
85377c9b 10541 -- unconditionally which may well not end up being used. That's not
10542 -- a good idea since it wastes space gratuitously ???
9dfe12ae 10543
ee6ba406 10544 Accept_Case : List_Id;
9dfe12ae 10545 Accept_List : constant List_Id := New_List;
ee6ba406 10546
10547 Alt : Node_Id;
9dfe12ae 10548 Alt_List : constant List_Id := New_List;
ee6ba406 10549 Alt_Stats : List_Id;
10550 Ann : Entity_Id := Empty;
10551
ee6ba406 10552 Check_Guard : Boolean := True;
ee6ba406 10553
9dfe12ae 10554 Decls : constant List_Id := New_List;
10555 Stats : constant List_Id := New_List;
10556 Body_List : constant List_Id := New_List;
10557 Trailing_List : constant List_Id := New_List;
ee6ba406 10558
10559 Choices : List_Id;
10560 Else_Present : Boolean := False;
10561 Terminate_Alt : Node_Id := Empty;
10562 Select_Mode : Node_Id;
10563
10564 Delay_Case : List_Id;
10565 Delay_Count : Integer := 0;
10566 Delay_Val : Entity_Id;
10567 Delay_Index : Entity_Id;
10568 Delay_Min : Entity_Id;
10569 Delay_Num : Int := 1;
10570 Delay_Alt_List : List_Id := New_List;
9dfe12ae 10571 Delay_List : constant List_Id := New_List;
ee6ba406 10572 D : Entity_Id;
10573 M : Entity_Id;
10574
10575 First_Delay : Boolean := True;
10576 Guard_Open : Entity_Id;
10577
10578 End_Lab : Node_Id;
10579 Index : Int := 1;
10580 Lab : Node_Id;
10581 Num_Alts : Int;
10582 Num_Accept : Nat := 0;
10583 Proc : Node_Id;
ee6ba406 10584 Time_Type : Entity_Id;
ee6ba406 10585 Select_Call : Node_Id;
10586
10587 Qnam : constant Entity_Id :=
10588 Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
10589
10590 Xnam : constant Entity_Id :=
10591 Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
10592
10593 -----------------------
10594 -- Local subprograms --
10595 -----------------------
10596
10597 function Accept_Or_Raise return List_Id;
10598 -- For the rare case where delay alternatives all have guards, and
10599 -- all of them are closed, it is still possible that there were open
10600 -- accept alternatives with no callers. We must reexamine the
10601 -- Accept_List, and execute a selective wait with no else if some
10602 -- accept is open. If none, we raise program_error.
10603
10604 procedure Add_Accept (Alt : Node_Id);
10605 -- Process a single accept statement in a select alternative. Build
10606 -- procedure for body of accept, and add entry to dispatch table with
10607 -- expression for guard, in preparation for call to run time select.
10608
10609 function Make_And_Declare_Label (Num : Int) return Node_Id;
10610 -- Manufacture a label using Num as a serial number and declare it.
10611 -- The declaration is appended to Decls. The label marks the trailing
10612 -- statements of an accept or delay alternative.
10613
10614 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
2866d595 10615 -- Build call to Selective_Wait runtime routine
ee6ba406 10616
10617 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
10618 -- Add code to compare value of delay with previous values, and
10619 -- generate case entry for trailing statements.
10620
10621 procedure Process_Accept_Alternative
10622 (Alt : Node_Id;
10623 Index : Int;
10624 Proc : Node_Id);
10625 -- Add code to call corresponding procedure, and branch to
10626 -- trailing statements, if any.
10627
10628 ---------------------
10629 -- Accept_Or_Raise --
10630 ---------------------
10631
10632 function Accept_Or_Raise return List_Id is
10633 Cond : Node_Id;
10634 Stats : List_Id;
ec97ce79 10635 J : constant Entity_Id := Make_Temporary (Loc, 'J');
ee6ba406 10636
10637 begin
10638 -- We generate the following:
10639
10640 -- for J in q'range loop
10641 -- if q(J).S /=null_task_entry then
10642 -- selective_wait (simple_mode,...);
10643 -- done := True;
10644 -- exit;
10645 -- end if;
10646 -- end loop;
10647 --
10648 -- if no rendez_vous then
10649 -- raise program_error;
10650 -- end if;
10651
10652 -- Note that the code needs to know that the selector name
10653 -- in an Accept_Alternative is named S.
10654
10655 Cond := Make_Op_Ne (Loc,
10656 Left_Opnd =>
10657 Make_Selected_Component (Loc,
55868293 10658 Prefix =>
10659 Make_Indexed_Component (Loc,
83c6c069 10660 Prefix => New_Occurrence_Of (Qnam, Loc),
10661 Expressions => New_List (New_Occurrence_Of (J, Loc))),
55868293 10662 Selector_Name => Make_Identifier (Loc, Name_S)),
ee6ba406 10663 Right_Opnd =>
83c6c069 10664 New_Occurrence_Of (RTE (RE_Null_Task_Entry), Loc));
ee6ba406 10665
10666 Stats := New_List (
10667 Make_Implicit_Loop_Statement (N,
ee6ba406 10668 Iteration_Scheme =>
10669 Make_Iteration_Scheme (Loc,
10670 Loop_Parameter_Specification =>
10671 Make_Loop_Parameter_Specification (Loc,
85377c9b 10672 Defining_Identifier => J,
ee6ba406 10673 Discrete_Subtype_Definition =>
10674 Make_Attribute_Reference (Loc,
83c6c069 10675 Prefix => New_Occurrence_Of (Qnam, Loc),
ee6ba406 10676 Attribute_Name => Name_Range,
85377c9b 10677 Expressions => New_List (
ee6ba406 10678 Make_Integer_Literal (Loc, 1))))),
10679
85377c9b 10680 Statements => New_List (
ee6ba406 10681 Make_Implicit_If_Statement (N,
85377c9b 10682 Condition => Cond,
ee6ba406 10683 Then_Statements => New_List (
10684 Make_Select_Call (
83c6c069 10685 New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)),
ee6ba406 10686 Make_Exit_Statement (Loc))))));
10687
10688 Append_To (Stats,
10689 Make_Raise_Program_Error (Loc,
10690 Condition => Make_Op_Eq (Loc,
83c6c069 10691 Left_Opnd => New_Occurrence_Of (Xnam, Loc),
ee6ba406 10692 Right_Opnd =>
83c6c069 10693 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
f15731c4 10694 Reason => PE_All_Guards_Closed));
ee6ba406 10695
10696 return Stats;
10697 end Accept_Or_Raise;
10698
10699 ----------------
10700 -- Add_Accept --
10701 ----------------
10702
10703 procedure Add_Accept (Alt : Node_Id) is
10704 Acc_Stm : constant Node_Id := Accept_Statement (Alt);
10705 Ename : constant Node_Id := Entry_Direct_Name (Acc_Stm);
7cab648c 10706 Eloc : constant Source_Ptr := Sloc (Ename);
ee6ba406 10707 Eent : constant Entity_Id := Entity (Ename);
10708 Index : constant Node_Id := Entry_Index (Acc_Stm);
10709 Null_Body : Node_Id;
10710 Proc_Body : Node_Id;
10711 PB_Ent : Entity_Id;
10712 Expr : Node_Id;
10713 Call : Node_Id;
10714
10715 begin
10716 if No (Ann) then
10717 Ann := Node (Last_Elmt (Accept_Address (Eent)));
10718 end if;
10719
10720 if Present (Condition (Alt)) then
10721 Expr :=
92f1631f 10722 Make_If_Expression (Eloc, New_List (
ee6ba406 10723 Condition (Alt),
7cab648c 10724 Entry_Index_Expression (Eloc, Eent, Index, Scope (Eent)),
83c6c069 10725 New_Occurrence_Of (RTE (RE_Null_Task_Entry), Eloc)));
ee6ba406 10726 else
10727 Expr :=
10728 Entry_Index_Expression
7cab648c 10729 (Eloc, Eent, Index, Scope (Eent));
ee6ba406 10730 end if;
10731
10732 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
83c6c069 10733 Null_Body := New_Occurrence_Of (Standard_False, Eloc);
ee6ba406 10734
4b16f8e3 10735 -- Always add call to Abort_Undefer when generating code, since
10736 -- this is what the runtime expects (abort deferred in
10737 -- Selective_Wait). In CodePeer mode this only confuses the
10738 -- analysis with unknown calls, so don't do it.
10739
10740 if not CodePeer_Mode then
10741 Call :=
10742 Make_Procedure_Call_Statement (Eloc,
83c6c069 10743 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Eloc));
4b16f8e3 10744 Insert_Before
10745 (First (Statements (Handled_Statement_Sequence
10746 (Accept_Statement (Alt)))),
10747 Call);
10748 Analyze (Call);
10749 end if;
ee6ba406 10750
10751 PB_Ent :=
7cab648c 10752 Make_Defining_Identifier (Eloc,
ee6ba406 10753 New_External_Name (Chars (Ename), 'A', Num_Accept));
10754
70966f50 10755 if Comes_From_Source (Alt) then
10756 Set_Debug_Info_Needed (PB_Ent);
10757 end if;
9dfe12ae 10758
ee6ba406 10759 Proc_Body :=
7cab648c 10760 Make_Subprogram_Body (Eloc,
85377c9b 10761 Specification =>
7cab648c 10762 Make_Procedure_Specification (Eloc,
ee6ba406 10763 Defining_Unit_Name => PB_Ent),
85377c9b 10764 Declarations => Declarations (Acc_Stm),
10765 Handled_Statement_Sequence =>
10766 Build_Accept_Body (Accept_Statement (Alt)));
ee6ba406 10767
10768 -- During the analysis of the body of the accept statement, any
10769 -- zero cost exception handler records were collected in the
76a1c25b 10770 -- Accept_Handler_Records field of the N_Accept_Alternative node.
10771 -- This is where we move them to where they belong, namely the
10772 -- newly created procedure.
ee6ba406 10773
10774 Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
10775 Append (Proc_Body, Body_List);
10776
10777 else
83c6c069 10778 Null_Body := New_Occurrence_Of (Standard_True, Eloc);
ee6ba406 10779
76a1c25b 10780 -- if accept statement has declarations, insert above, given that
10781 -- we are not creating a body for the accept.
ee6ba406 10782
10783 if Present (Declarations (Acc_Stm)) then
10784 Insert_Actions (N, Declarations (Acc_Stm));
10785 end if;
10786 end if;
10787
10788 Append_To (Accept_List,
7cab648c 10789 Make_Aggregate (Eloc, Expressions => New_List (Null_Body, Expr)));
ee6ba406 10790
10791 Num_Accept := Num_Accept + 1;
ee6ba406 10792 end Add_Accept;
10793
10794 ----------------------------
10795 -- Make_And_Declare_Label --
10796 ----------------------------
10797
10798 function Make_And_Declare_Label (Num : Int) return Node_Id is
10799 Lab_Id : Node_Id;
10800
10801 begin
10802 Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
10803 Lab :=
10804 Make_Label (Loc, Lab_Id);
10805
10806 Append_To (Decls,
10807 Make_Implicit_Label_Declaration (Loc,
10808 Defining_Identifier =>
10809 Make_Defining_Identifier (Loc, Chars (Lab_Id)),
85377c9b 10810 Label_Construct => Lab));
ee6ba406 10811
10812 return Lab;
10813 end Make_And_Declare_Label;
10814
10815 ----------------------
10816 -- Make_Select_Call --
10817 ----------------------
10818
10819 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
9dfe12ae 10820 Params : constant List_Id := New_List;
ee6ba406 10821
10822 begin
b23d813c 10823 Append_To (Params,
ee6ba406 10824 Make_Attribute_Reference (Loc,
83c6c069 10825 Prefix => New_Occurrence_Of (Qnam, Loc),
b23d813c 10826 Attribute_Name => Name_Unchecked_Access));
10827 Append_To (Params, Select_Mode);
10828 Append_To (Params, New_Occurrence_Of (Ann, Loc));
10829 Append_To (Params, New_Occurrence_Of (Xnam, Loc));
ee6ba406 10830
10831 return
10832 Make_Procedure_Call_Statement (Loc,
83c6c069 10833 Name => New_Occurrence_Of (RTE (RE_Selective_Wait), Loc),
ee6ba406 10834 Parameter_Associations => Params);
10835 end Make_Select_Call;
10836
10837 --------------------------------
10838 -- Process_Accept_Alternative --
10839 --------------------------------
10840
10841 procedure Process_Accept_Alternative
10842 (Alt : Node_Id;
10843 Index : Int;
10844 Proc : Node_Id)
10845 is
85377c9b 10846 Astmt : constant Node_Id := Accept_Statement (Alt);
ee6ba406 10847 Alt_Stats : List_Id;
10848
10849 begin
10850 Adjust_Condition (Condition (Alt));
ee6ba406 10851
e22bc81a 10852 -- Accept with body
ee6ba406 10853
e22bc81a 10854 if Present (Handled_Statement_Sequence (Astmt)) then
10855 Alt_Stats :=
10856 New_List (
10857 Make_Procedure_Call_Statement (Sloc (Proc),
10858 Name =>
83c6c069 10859 New_Occurrence_Of
e22bc81a 10860 (Defining_Unit_Name (Specification (Proc)),
10861 Sloc (Proc))));
ee6ba406 10862
e22bc81a 10863 -- Accept with no body (followed by trailing statements)
ee6ba406 10864
e22bc81a 10865 else
10866 Alt_Stats := Empty_List;
85377c9b 10867 end if;
ee6ba406 10868
e3cb8202 10869 Ensure_Statement_Present (Sloc (Astmt), Alt);
10870
85377c9b 10871 -- After the call, if any, branch to trailing statements, if any.
10872 -- We create a label for each, as well as the corresponding label
10873 -- declaration.
ee6ba406 10874
85377c9b 10875 if not Is_Empty_List (Statements (Alt)) then
ee6ba406 10876 Lab := Make_And_Declare_Label (Index);
ee6ba406 10877 Append (Lab, Trailing_List);
10878 Append_List (Statements (Alt), Trailing_List);
10879 Append_To (Trailing_List,
10880 Make_Goto_Statement (Loc,
10881 Name => New_Copy (Identifier (End_Lab))));
e22bc81a 10882
85377c9b 10883 else
10884 Lab := End_Lab;
ee6ba406 10885 end if;
10886
85377c9b 10887 Append_To (Alt_Stats,
10888 Make_Goto_Statement (Loc, Name => New_Copy (Identifier (Lab))));
ee6ba406 10889
85377c9b 10890 Append_To (Alt_List,
10891 Make_Case_Statement_Alternative (Loc,
8f531643 10892 Discrete_Choices => New_List (Make_Integer_Literal (Loc, Index)),
85377c9b 10893 Statements => Alt_Stats));
ee6ba406 10894 end Process_Accept_Alternative;
10895
10896 -------------------------------
10897 -- Process_Delay_Alternative --
10898 -------------------------------
10899
10900 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
e3cb8202 10901 Dloc : constant Source_Ptr := Sloc (Delay_Statement (Alt));
ee6ba406 10902 Cond : Node_Id;
10903 Delay_Alt : List_Id;
10904
10905 begin
10906 -- Deal with C/Fortran boolean as delay condition
10907
10908 Adjust_Condition (Condition (Alt));
10909
2866d595 10910 -- Determine the smallest specified delay
10911
ee6ba406 10912 -- for each delay alternative generate:
10913
10914 -- if guard-expression then
10915 -- Delay_Val := delay-expression;
10916 -- Guard_Open := True;
10917 -- if Delay_Val < Delay_Min then
10918 -- Delay_Min := Delay_Val;
10919 -- Delay_Index := Index;
10920 -- end if;
10921 -- end if;
10922
2866d595 10923 -- The enclosing if-statement is omitted if there is no guard
ee6ba406 10924
85377c9b 10925 if Delay_Count = 1 or else First_Delay then
ee6ba406 10926 First_Delay := False;
10927
10928 Delay_Alt := New_List (
10929 Make_Assignment_Statement (Loc,
83c6c069 10930 Name => New_Occurrence_Of (Delay_Min, Loc),
ee6ba406 10931 Expression => Expression (Delay_Statement (Alt))));
10932
10933 if Delay_Count > 1 then
10934 Append_To (Delay_Alt,
10935 Make_Assignment_Statement (Loc,
83c6c069 10936 Name => New_Occurrence_Of (Delay_Index, Loc),
ee6ba406 10937 Expression => Make_Integer_Literal (Loc, Index)));
10938 end if;
10939
10940 else
10941 Delay_Alt := New_List (
10942 Make_Assignment_Statement (Loc,
83c6c069 10943 Name => New_Occurrence_Of (Delay_Val, Loc),
ee6ba406 10944 Expression => Expression (Delay_Statement (Alt))));
10945
10946 if Time_Type = Standard_Duration then
10947 Cond :=
10948 Make_Op_Lt (Loc,
83c6c069 10949 Left_Opnd => New_Occurrence_Of (Delay_Val, Loc),
10950 Right_Opnd => New_Occurrence_Of (Delay_Min, Loc));
ee6ba406 10951
10952 else
10953 -- The scope of the time type must define a comparison
10954 -- operator. The scope itself may not be visible, so we
10955 -- construct a node with entity information to insure that
10956 -- semantic analysis can find the proper operator.
10957
10958 Cond :=
10959 Make_Function_Call (Loc,
10960 Name => Make_Selected_Component (Loc,
85377c9b 10961 Prefix =>
83c6c069 10962 New_Occurrence_Of (Scope (Time_Type), Loc),
ee6ba406 10963 Selector_Name =>
10964 Make_Operator_Symbol (Loc,
85377c9b 10965 Chars => Name_Op_Lt,
ee6ba406 10966 Strval => No_String)),
10967 Parameter_Associations =>
10968 New_List (
83c6c069 10969 New_Occurrence_Of (Delay_Val, Loc),
10970 New_Occurrence_Of (Delay_Min, Loc)));
ee6ba406 10971
10972 Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
10973 end if;
10974
10975 Append_To (Delay_Alt,
10976 Make_Implicit_If_Statement (N,
10977 Condition => Cond,
10978 Then_Statements => New_List (
10979 Make_Assignment_Statement (Loc,
83c6c069 10980 Name => New_Occurrence_Of (Delay_Min, Loc),
10981 Expression => New_Occurrence_Of (Delay_Val, Loc)),
ee6ba406 10982
10983 Make_Assignment_Statement (Loc,
83c6c069 10984 Name => New_Occurrence_Of (Delay_Index, Loc),
ee6ba406 10985 Expression => Make_Integer_Literal (Loc, Index)))));
10986 end if;
10987
10988 if Check_Guard then
10989 Append_To (Delay_Alt,
10990 Make_Assignment_Statement (Loc,
83c6c069 10991 Name => New_Occurrence_Of (Guard_Open, Loc),
10992 Expression => New_Occurrence_Of (Standard_True, Loc)));
ee6ba406 10993 end if;
10994
10995 if Present (Condition (Alt)) then
10996 Delay_Alt := New_List (
10997 Make_Implicit_If_Statement (N,
85377c9b 10998 Condition => Condition (Alt),
ee6ba406 10999 Then_Statements => Delay_Alt));
11000 end if;
11001
11002 Append_List (Delay_Alt, Delay_List);
11003
e3cb8202 11004 Ensure_Statement_Present (Dloc, Alt);
11005
76a1c25b 11006 -- If the delay alternative has a statement part, add choice to the
11007 -- case statements for delays.
ee6ba406 11008
85377c9b 11009 if not Is_Empty_List (Statements (Alt)) then
ee6ba406 11010
11011 if Delay_Count = 1 then
11012 Append_List (Statements (Alt), Delay_Alt_List);
11013
11014 else
ee6ba406 11015 Append_To (Delay_Alt_List,
11016 Make_Case_Statement_Alternative (Loc,
8f531643 11017 Discrete_Choices => New_List (
11018 Make_Integer_Literal (Loc, Index)),
85377c9b 11019 Statements => Statements (Alt)));
ee6ba406 11020 end if;
11021
11022 elsif Delay_Count = 1 then
11023
11024 -- If the single delay has no trailing statements, add a branch
11025 -- to the exit label to the selective wait.
11026
11027 Delay_Alt_List := New_List (
11028 Make_Goto_Statement (Loc,
11029 Name => New_Copy (Identifier (End_Lab))));
11030
11031 end if;
11032 end Process_Delay_Alternative;
11033
11034 -- Start of processing for Expand_N_Selective_Accept
11035
11036 begin
f239f5be 11037 Process_Statements_For_Controlled_Objects (N);
11038
ee6ba406 11039 -- First insert some declarations before the select. The first is:
11040
11041 -- Ann : Address
11042
11043 -- This variable holds the parameters passed to the accept body. This
11044 -- declaration has already been inserted by the time we get here by
11045 -- a call to Expand_Accept_Declarations made from the semantics when
11046 -- processing the first accept statement contained in the select. We
11047 -- can find this entity as Accept_Address (E), where E is any of the
11048 -- entries references by contained accept statements.
11049
11050 -- The first step is to scan the list of Selective_Accept_Statements
11051 -- to find this entity, and also count the number of accepts, and
11052 -- determine if terminated, delay or else is present:
11053
11054 Num_Alts := 0;
11055
11056 Alt := First (Alts);
11057 while Present (Alt) loop
f239f5be 11058 Process_Statements_For_Controlled_Objects (Alt);
ee6ba406 11059
11060 if Nkind (Alt) = N_Accept_Alternative then
11061 Add_Accept (Alt);
11062
11063 elsif Nkind (Alt) = N_Delay_Alternative then
0d85cfbf 11064 Delay_Count := Delay_Count + 1;
ee6ba406 11065
11066 -- If the delays are relative delays, the delay expressions have
11067 -- type Standard_Duration. Otherwise they must have some time type
11068 -- recognized by GNAT.
11069
11070 if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
11071 Time_Type := Standard_Duration;
11072 else
11073 Time_Type := Etype (Expression (Delay_Statement (Alt)));
11074
11075 if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
11076 or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
11077 then
11078 null;
11079 else
11080 Error_Msg_NE (
0d85cfbf 11081 "& is not a time type (RM 9.6(6))",
ee6ba406 11082 Expression (Delay_Statement (Alt)), Time_Type);
11083 Time_Type := Standard_Duration;
11084 Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
11085 end if;
11086 end if;
11087
11088 if No (Condition (Alt)) then
11089
2866d595 11090 -- This guard will always be open
ee6ba406 11091
11092 Check_Guard := False;
11093 end if;
11094
11095 elsif Nkind (Alt) = N_Terminate_Alternative then
11096 Adjust_Condition (Condition (Alt));
11097 Terminate_Alt := Alt;
11098 end if;
11099
11100 Num_Alts := Num_Alts + 1;
11101 Next (Alt);
11102 end loop;
11103
11104 Else_Present := Present (Else_Statements (N));
11105
11106 -- At the same time (see procedure Add_Accept) we build the accept list:
11107
11108 -- Qnn : Accept_List (1 .. num-select) := (
11109 -- (null-body, entry-index),
11110 -- (null-body, entry-index),
11111 -- ..
11112 -- (null_body, entry-index));
11113
11114 -- In the above declaration, null-body is True if the corresponding
11115 -- accept has no body, and false otherwise. The entry is either the
11116 -- entry index expression if there is no guard, or if a guard is
92f1631f 11117 -- present, then an if expression of the form:
ee6ba406 11118
11119 -- (if guard then entry-index else Null_Task_Entry)
11120
11121 -- If a guard is statically known to be false, the entry can simply
11122 -- be omitted from the accept list.
11123
85377c9b 11124 Append_To (Decls,
ee6ba406 11125 Make_Object_Declaration (Loc,
11126 Defining_Identifier => Qnam,
83c6c069 11127 Object_Definition => New_Occurrence_Of (RTE (RE_Accept_List), Loc),
85377c9b 11128 Aliased_Present => True,
11129 Expression =>
ee6ba406 11130 Make_Qualified_Expression (Loc,
11131 Subtype_Mark =>
83c6c069 11132 New_Occurrence_Of (RTE (RE_Accept_List), Loc),
85377c9b 11133 Expression =>
11134 Make_Aggregate (Loc, Expressions => Accept_List))));
ee6ba406 11135
11136 -- Then we declare the variable that holds the index for the accept
11137 -- that will be selected for service:
11138
11139 -- Xnn : Select_Index;
11140
85377c9b 11141 Append_To (Decls,
ee6ba406 11142 Make_Object_Declaration (Loc,
11143 Defining_Identifier => Xnam,
11144 Object_Definition =>
83c6c069 11145 New_Occurrence_Of (RTE (RE_Select_Index), Loc),
ee6ba406 11146 Expression =>
83c6c069 11147 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)));
ee6ba406 11148
2866d595 11149 -- After this follow procedure declarations for each accept body
ee6ba406 11150
11151 -- procedure Pnn is
11152 -- begin
11153 -- ...
11154 -- end;
11155
11156 -- where the ... are statements from the corresponding procedure body.
11157 -- No parameters are involved, since the parameters are passed via Ann
11158 -- and the parameter references have already been expanded to be direct
11159 -- references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
11160 -- any embedded tasking statements (which would normally be illegal in
cb5f80c1 11161 -- procedures), have been converted to calls to the tasking runtime so
ee6ba406 11162 -- there is no problem in putting them into procedures.
11163
11164 -- The original accept statement has been expanded into a block in
11165 -- the same fashion as for simple accepts (see Build_Accept_Body).
11166
11167 -- Note: we don't really need to build these procedures for the case
11168 -- where no delay statement is present, but it is just as easy to
11169 -- build them unconditionally, and not significantly inefficient,
11170 -- since if they are short they will be inlined anyway.
11171
2866d595 11172 -- The procedure declarations have been assembled in Body_List
ee6ba406 11173
11174 -- If delays are present, we must compute the required delay.
11175 -- We first generate the declarations:
11176
11177 -- Delay_Index : Boolean := 0;
11178 -- Delay_Min : Some_Time_Type.Time;
11179 -- Delay_Val : Some_Time_Type.Time;
11180
11181 -- Delay_Index will be set to the index of the minimum delay, i.e. the
2866d595 11182 -- active delay that is actually chosen as the basis for the possible
11183 -- delay if an immediate rendez-vous is not possible.
11184
11185 -- In the most common case there is a single delay statement, and this
11186 -- is handled specially.
ee6ba406 11187
11188 if Delay_Count > 0 then
11189
11190 -- Generate the required declarations
11191
11192 Delay_Val :=
11193 Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
11194 Delay_Index :=
11195 Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
11196 Delay_Min :=
11197 Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
11198
11199 Append_To (Decls,
11200 Make_Object_Declaration (Loc,
11201 Defining_Identifier => Delay_Val,
83c6c069 11202 Object_Definition => New_Occurrence_Of (Time_Type, Loc)));
ee6ba406 11203
11204 Append_To (Decls,
11205 Make_Object_Declaration (Loc,
11206 Defining_Identifier => Delay_Index,
83c6c069 11207 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
ee6ba406 11208 Expression => Make_Integer_Literal (Loc, 0)));
11209
11210 Append_To (Decls,
11211 Make_Object_Declaration (Loc,
11212 Defining_Identifier => Delay_Min,
83c6c069 11213 Object_Definition => New_Occurrence_Of (Time_Type, Loc),
ee6ba406 11214 Expression =>
11215 Unchecked_Convert_To (Time_Type,
11216 Make_Attribute_Reference (Loc,
11217 Prefix =>
11218 New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
11219 Attribute_Name => Name_Last))));
11220
11221 -- Create Duration and Delay_Mode objects used for passing a delay
11222 -- value to RTS
11223
ec97ce79 11224 D := Make_Temporary (Loc, 'D');
11225 M := Make_Temporary (Loc, 'M');
ee6ba406 11226
11227 declare
11228 Discr : Entity_Id;
11229
11230 begin
11231 -- Note that these values are defined in s-osprim.ads and must
11232 -- be kept in sync:
11233 --
11234 -- Relative : constant := 0;
11235 -- Absolute_Calendar : constant := 1;
11236 -- Absolute_RT : constant := 2;
11237
11238 if Time_Type = Standard_Duration then
11239 Discr := Make_Integer_Literal (Loc, 0);
11240
11241 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11242 Discr := Make_Integer_Literal (Loc, 1);
11243
11244 else
11245 pragma Assert
11246 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11247 Discr := Make_Integer_Literal (Loc, 2);
11248 end if;
11249
11250 Append_To (Decls,
11251 Make_Object_Declaration (Loc,
11252 Defining_Identifier => D,
85377c9b 11253 Object_Definition =>
83c6c069 11254 New_Occurrence_Of (Standard_Duration, Loc)));
ee6ba406 11255
11256 Append_To (Decls,
11257 Make_Object_Declaration (Loc,
11258 Defining_Identifier => M,
11259 Object_Definition =>
83c6c069 11260 New_Occurrence_Of (Standard_Integer, Loc),
ee6ba406 11261 Expression => Discr));
11262 end;
11263
11264 if Check_Guard then
11265 Guard_Open :=
11266 Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
11267
11268 Append_To (Decls,
11269 Make_Object_Declaration (Loc,
11270 Defining_Identifier => Guard_Open,
83c6c069 11271 Object_Definition =>
11272 New_Occurrence_Of (Standard_Boolean, Loc),
11273 Expression =>
11274 New_Occurrence_Of (Standard_False, Loc)));
ee6ba406 11275 end if;
11276
11277 -- Delay_Count is zero, don't need M and D set (suppress warning)
11278
11279 else
11280 M := Empty;
11281 D := Empty;
11282 end if;
11283
11284 if Present (Terminate_Alt) then
11285
11286 -- If the terminate alternative guard is False, use
11287 -- Simple_Mode; otherwise use Terminate_Mode.
11288
11289 if Present (Condition (Terminate_Alt)) then
92f1631f 11290 Select_Mode := Make_If_Expression (Loc,
ee6ba406 11291 New_List (Condition (Terminate_Alt),
83c6c069 11292 New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc),
11293 New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)));
ee6ba406 11294 else
83c6c069 11295 Select_Mode := New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc);
ee6ba406 11296 end if;
11297
11298 elsif Else_Present or Delay_Count > 0 then
83c6c069 11299 Select_Mode := New_Occurrence_Of (RTE (RE_Else_Mode), Loc);
ee6ba406 11300
11301 else
83c6c069 11302 Select_Mode := New_Occurrence_Of (RTE (RE_Simple_Mode), Loc);
ee6ba406 11303 end if;
11304
11305 Select_Call := Make_Select_Call (Select_Mode);
11306 Append (Select_Call, Stats);
11307
11308 -- Now generate code to act on the result. There is an entry
11309 -- in this case for each accept statement with a non-null body,
11310 -- followed by a branch to the statements that follow the Accept.
11311 -- In the absence of delay alternatives, we generate:
11312
11313 -- case X is
11314 -- when No_Rendezvous => -- omitted if simple mode
11315 -- goto Lab0;
11316
11317 -- when 1 =>
11318 -- P1n;
11319 -- goto Lab1;
11320
11321 -- when 2 =>
11322 -- P2n;
11323 -- goto Lab2;
11324
11325 -- when others =>
11326 -- goto Exit;
11327 -- end case;
11328 --
11329 -- Lab0: Else_Statements;
11330 -- goto exit;
11331
11332 -- Lab1: Trailing_Statements1;
11333 -- goto Exit;
11334 --
11335 -- Lab2: Trailing_Statements2;
11336 -- goto Exit;
11337 -- ...
11338 -- Exit:
11339
2866d595 11340 -- Generate label for common exit
ee6ba406 11341
11342 End_Lab := Make_And_Declare_Label (Num_Alts + 1);
11343
2866d595 11344 -- First entry is the default case, when no rendezvous is possible
ee6ba406 11345
83c6c069 11346 Choices := New_List (New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc));
ee6ba406 11347
11348 if Else_Present then
11349
2866d595 11350 -- If no rendezvous is possible, the else part is executed
ee6ba406 11351
11352 Lab := Make_And_Declare_Label (0);
11353 Alt_Stats := New_List (
11354 Make_Goto_Statement (Loc,
11355 Name => New_Copy (Identifier (Lab))));
11356
11357 Append (Lab, Trailing_List);
11358 Append_List (Else_Statements (N), Trailing_List);
11359 Append_To (Trailing_List,
11360 Make_Goto_Statement (Loc,
11361 Name => New_Copy (Identifier (End_Lab))));
11362 else
11363 Alt_Stats := New_List (
11364 Make_Goto_Statement (Loc,
11365 Name => New_Copy (Identifier (End_Lab))));
11366 end if;
11367
11368 Append_To (Alt_List,
11369 Make_Case_Statement_Alternative (Loc,
11370 Discrete_Choices => Choices,
85377c9b 11371 Statements => Alt_Stats));
ee6ba406 11372
76a1c25b 11373 -- We make use of the fact that Accept_Index is an integer type, and
11374 -- generate successive literals for entries for each accept. Only those
11375 -- for which there is a body or trailing statements get a case entry.
ee6ba406 11376
11377 Alt := First (Select_Alternatives (N));
11378 Proc := First (Body_List);
ee6ba406 11379 while Present (Alt) loop
11380
11381 if Nkind (Alt) = N_Accept_Alternative then
11382 Process_Accept_Alternative (Alt, Index, Proc);
11383 Index := Index + 1;
11384
11385 if Present
11386 (Handled_Statement_Sequence (Accept_Statement (Alt)))
11387 then
11388 Next (Proc);
11389 end if;
11390
11391 elsif Nkind (Alt) = N_Delay_Alternative then
11392 Process_Delay_Alternative (Alt, Delay_Num);
11393 Delay_Num := Delay_Num + 1;
11394 end if;
11395
11396 Next (Alt);
11397 end loop;
11398
11399 -- An others choice is always added to the main case, as well
11400 -- as the delay case (to satisfy the compiler).
11401
11402 Append_To (Alt_List,
11403 Make_Case_Statement_Alternative (Loc,
11404 Discrete_Choices =>
11405 New_List (Make_Others_Choice (Loc)),
11406 Statements =>
11407 New_List (Make_Goto_Statement (Loc,
11408 Name => New_Copy (Identifier (End_Lab))))));
11409
11410 Accept_Case := New_List (
11411 Make_Case_Statement (Loc,
83c6c069 11412 Expression => New_Occurrence_Of (Xnam, Loc),
ee6ba406 11413 Alternatives => Alt_List));
11414
11415 Append_List (Trailing_List, Accept_Case);
ee6ba406 11416 Append_List (Body_List, Decls);
11417
11418 -- Construct case statement for trailing statements of delay
11419 -- alternatives, if there are several of them.
11420
11421 if Delay_Count > 1 then
11422 Append_To (Delay_Alt_List,
11423 Make_Case_Statement_Alternative (Loc,
11424 Discrete_Choices =>
11425 New_List (Make_Others_Choice (Loc)),
11426 Statements =>
11427 New_List (Make_Null_Statement (Loc))));
11428
11429 Delay_Case := New_List (
11430 Make_Case_Statement (Loc,
83c6c069 11431 Expression => New_Occurrence_Of (Delay_Index, Loc),
ee6ba406 11432 Alternatives => Delay_Alt_List));
11433 else
11434 Delay_Case := Delay_Alt_List;
11435 end if;
11436
11437 -- If there are no delay alternatives, we append the case statement
11438 -- to the statement list.
11439
11440 if Delay_Count = 0 then
11441 Append_List (Accept_Case, Stats);
11442
11443 -- Delay alternatives present
11444
11445 else
11446 -- If delay alternatives are present we generate:
11447
11448 -- find minimum delay.
11449 -- DX := minimum delay;
11450 -- M := <delay mode>;
11451 -- Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
11452 -- DX, MX, X);
11453 --
11454 -- if X = No_Rendezvous then
11455 -- case statement for delay statements.
11456 -- else
11457 -- case statement for accept alternatives.
11458 -- end if;
11459
11460 declare
11461 Cases : Node_Id;
11462 Stmt : Node_Id;
11463 Parms : List_Id;
11464 Parm : Node_Id;
11465 Conv : Node_Id;
11466
11467 begin
11468 -- The type of the delay expression is known to be legal
11469
11470 if Time_Type = Standard_Duration then
83c6c069 11471 Conv := New_Occurrence_Of (Delay_Min, Loc);
ee6ba406 11472
11473 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11474 Conv := Make_Function_Call (Loc,
83c6c069 11475 New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
11476 New_List (New_Occurrence_Of (Delay_Min, Loc)));
ee6ba406 11477
11478 else
11479 pragma Assert
11480 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11481
11482 Conv := Make_Function_Call (Loc,
83c6c069 11483 New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
11484 New_List (New_Occurrence_Of (Delay_Min, Loc)));
ee6ba406 11485 end if;
11486
11487 Stmt := Make_Assignment_Statement (Loc,
83c6c069 11488 Name => New_Occurrence_Of (D, Loc),
ee6ba406 11489 Expression => Conv);
11490
11491 -- Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
11492
11493 Parms := Parameter_Associations (Select_Call);
ee6ba406 11494
c0688d2b 11495 Parm := First (Parms);
85377c9b 11496 while Present (Parm) and then Parm /= Select_Mode loop
ee6ba406 11497 Next (Parm);
11498 end loop;
11499
11500 pragma Assert (Present (Parm));
83c6c069 11501 Rewrite (Parm, New_Occurrence_Of (RTE (RE_Delay_Mode), Loc));
ee6ba406 11502 Analyze (Parm);
11503
11504 -- Prepare two new parameters of Duration and Delay_Mode type
11505 -- which represent the value and the mode of the minimum delay.
11506
11507 Next (Parm);
83c6c069 11508 Insert_After (Parm, New_Occurrence_Of (M, Loc));
11509 Insert_After (Parm, New_Occurrence_Of (D, Loc));
ee6ba406 11510
2866d595 11511 -- Create a call to RTS
ee6ba406 11512
11513 Rewrite (Select_Call,
11514 Make_Procedure_Call_Statement (Loc,
83c6c069 11515 Name => New_Occurrence_Of (RTE (RE_Timed_Selective_Wait), Loc),
ee6ba406 11516 Parameter_Associations => Parms));
11517
76a1c25b 11518 -- This new call should follow the calculation of the minimum
11519 -- delay.
ee6ba406 11520
11521 Insert_List_Before (Select_Call, Delay_List);
11522
11523 if Check_Guard then
11524 Stmt :=
11525 Make_Implicit_If_Statement (N,
83c6c069 11526 Condition => New_Occurrence_Of (Guard_Open, Loc),
85377c9b 11527 Then_Statements => New_List (
11528 New_Copy_Tree (Stmt),
11529 New_Copy_Tree (Select_Call)),
ee6ba406 11530 Else_Statements => Accept_Or_Raise);
11531 Rewrite (Select_Call, Stmt);
11532 else
11533 Insert_Before (Select_Call, Stmt);
11534 end if;
11535
11536 Cases :=
11537 Make_Implicit_If_Statement (N,
11538 Condition => Make_Op_Eq (Loc,
83c6c069 11539 Left_Opnd => New_Occurrence_Of (Xnam, Loc),
ee6ba406 11540 Right_Opnd =>
83c6c069 11541 New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
ee6ba406 11542
11543 Then_Statements => Delay_Case,
11544 Else_Statements => Accept_Case);
11545
11546 Append (Cases, Stats);
11547 end;
11548 end if;
b23d813c 11549
85377c9b 11550 Append (End_Lab, Stats);
ee6ba406 11551
11552 -- Replace accept statement with appropriate block
11553
85377c9b 11554 Rewrite (N,
ee6ba406 11555 Make_Block_Statement (Loc,
85377c9b 11556 Declarations => Decls,
ee6ba406 11557 Handled_Statement_Sequence =>
85377c9b 11558 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stats)));
ee6ba406 11559 Analyze (N);
11560
11561 -- Note: have to worry more about abort deferral in above code ???
11562
11563 -- Final step is to unstack the Accept_Address entries for all accept
11564 -- statements appearing in accept alternatives in the select statement
11565
11566 Alt := First (Alts);
11567 while Present (Alt) loop
11568 if Nkind (Alt) = N_Accept_Alternative then
11569 Remove_Last_Elmt (Accept_Address
11570 (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
11571 end if;
11572
11573 Next (Alt);
11574 end loop;
ee6ba406 11575 end Expand_N_Selective_Accept;
11576
a21c7222 11577 -------------------------------------------
11578 -- Expand_N_Single_Protected_Declaration --
11579 -------------------------------------------
11580
11581 -- A single protected declaration should never be present after semantic
11582 -- analysis because it is transformed into a protected type declaration
11583 -- and an accompanying anonymous object. This routine ensures that the
11584 -- transformation takes place.
11585
11586 procedure Expand_N_Single_Protected_Declaration (N : Node_Id) is
11587 begin
11588 raise Program_Error;
11589 end Expand_N_Single_Protected_Declaration;
11590
ee6ba406 11591 --------------------------------------
11592 -- Expand_N_Single_Task_Declaration --
11593 --------------------------------------
11594
a21c7222 11595 -- A single task declaration should never be present after semantic
11596 -- analysis because it is transformed into a task type declaration and
11597 -- an accompanying anonymous object. This routine ensures that the
11598 -- transformation takes place.
ee6ba406 11599
11600 procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
11601 begin
11602 raise Program_Error;
11603 end Expand_N_Single_Task_Declaration;
11604
11605 ------------------------
11606 -- Expand_N_Task_Body --
11607 ------------------------
11608
11609 -- Given a task body
11610
11611 -- task body tname is
11612 -- <declarations>
11613 -- begin
11614 -- <statements>
11615 -- end x;
11616
11617 -- This expansion routine converts it into a procedure and sets the
11618 -- elaboration flag for the procedure to true, to represent the fact
11619 -- that the task body is now elaborated:
11620
11621 -- procedure tnameB (_Task : access tnameV) is
11622 -- discriminal : dtype renames _Task.discriminant;
9dfe12ae 11623
ee6ba406 11624 -- procedure _clean is
11625 -- begin
11626 -- Abort_Defer.all;
11627 -- Complete_Task;
11628 -- Abort_Undefer.all;
11629 -- return;
11630 -- end _clean;
9dfe12ae 11631
ee6ba406 11632 -- begin
11633 -- Abort_Undefer.all;
11634 -- <declarations>
11635 -- System.Task_Stages.Complete_Activation;
11636 -- <statements>
11637 -- at end
11638 -- _clean;
11639 -- end tnameB;
11640
11641 -- tnameE := True;
11642
76a1c25b 11643 -- In addition, if the task body is an activator, then a call to activate
11644 -- tasks is added at the start of the statements, before the call to
11645 -- Complete_Activation, and if in addition the task is a master then it
11646 -- must be established as a master. These calls are inserted and analyzed
11647 -- in Expand_Cleanup_Actions, when the Handled_Sequence_Of_Statements is
11648 -- expanded.
ee6ba406 11649
11650 -- There is one discriminal declaration line generated for each
76a1c25b 11651 -- discriminant that is present to provide an easy reference point for
11652 -- discriminant references inside the body (see Exp_Ch2.Expand_Name).
ee6ba406 11653
11654 -- Note on relationship to GNARLI definition. In the GNARLI definition,
11655 -- task body procedures have a profile (Arg : System.Address). That is
11656 -- needed because GNARLI has to use the same access-to-subprogram type
11657 -- for all task types. We depend here on knowing that in GNAT, passing
11658 -- an address argument by value is identical to passing a record value
11659 -- by access (in either case a single pointer is passed), so even though
11660 -- this procedure has the wrong profile. In fact it's all OK, since the
11661 -- callings sequence is identical.
11662
11663 procedure Expand_N_Task_Body (N : Node_Id) is
11664 Loc : constant Source_Ptr := Sloc (N);
11665 Ttyp : constant Entity_Id := Corresponding_Spec (N);
11666 Call : Node_Id;
11667 New_N : Node_Id;
11668
d2a42b76 11669 Insert_Nod : Node_Id;
11670 -- Used to determine the proper location of wrapper body insertions
11671
ee6ba406 11672 begin
30ab103b 11673 -- if no task body procedure, means we had an error in configurable
11674 -- run-time mode, and there is no point in proceeding further.
11675
11676 if No (Task_Body_Procedure (Ttyp)) then
11677 return;
11678 end if;
11679
57993a53 11680 -- Add renaming declarations for discriminals and a declaration for the
11681 -- entry family index (if applicable).
f15731c4 11682
57993a53 11683 Install_Private_Data_Declarations
11684 (Loc, Task_Body_Procedure (Ttyp), Ttyp, N, Declarations (N));
ee6ba406 11685
11686 -- Add a call to Abort_Undefer at the very beginning of the task
11687 -- body since this body is called with abort still deferred.
11688
11689 if Abort_Allowed then
11690 Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
11691 Insert_Before
11692 (First (Statements (Handled_Statement_Sequence (N))), Call);
11693 Analyze (Call);
11694 end if;
11695
11696 -- The statement part has already been protected with an at_end and
11697 -- cleanup actions. The call to Complete_Activation must be placed
11698 -- at the head of the sequence of statements of that block. The
11699 -- declarations have been merged in this sequence of statements but
11700 -- the first real statement is accessible from the First_Real_Statement
11701 -- field (which was set for exactly this purpose).
11702
11703 if Restricted_Profile then
11704 Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
11705 else
11706 Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
11707 end if;
11708
11709 Insert_Before
11710 (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
11711 Analyze (Call);
11712
11713 New_N :=
11714 Make_Subprogram_Body (Loc,
57993a53 11715 Specification => Build_Task_Proc_Specification (Ttyp),
11716 Declarations => Declarations (N),
ee6ba406 11717 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
2f06c88a 11718 Set_Is_Task_Body_Procedure (New_N);
ee6ba406 11719
57993a53 11720 -- If the task contains generic instantiations, cleanup actions are
11721 -- delayed until after instantiation. Transfer the activation chain to
11722 -- the subprogram, to insure that the activation call is properly
11723 -- generated. It the task body contains inner tasks, indicate that the
11724 -- subprogram is a task master.
ee6ba406 11725
11726 if Delay_Cleanups (Ttyp) then
11727 Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
11728 Set_Is_Task_Master (New_N, Is_Task_Master (N));
11729 end if;
11730
11731 Rewrite (N, New_N);
11732 Analyze (N);
11733
76a1c25b 11734 -- Set elaboration flag immediately after task body. If the body is a
11735 -- subunit, the flag is set in the declarative part containing the stub.
ee6ba406 11736
11737 if Nkind (Parent (N)) /= N_Subunit then
11738 Insert_After (N,
11739 Make_Assignment_Statement (Loc,
11740 Name =>
11741 Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
83c6c069 11742 Expression => New_Occurrence_Of (Standard_True, Loc)));
ee6ba406 11743 end if;
9f373bb8 11744
76a1c25b 11745 -- Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
d2a42b76 11746 -- the task body. At this point all wrapper specs have been created,
76a1c25b 11747 -- frozen and included in the dispatch table for the task type.
9f373bb8 11748
de54c5ab 11749 if Ada_Version >= Ada_2005 then
d2a42b76 11750 if Nkind (Parent (N)) = N_Subunit then
11751 Insert_Nod := Corresponding_Stub (Parent (N));
11752 else
11753 Insert_Nod := N;
11754 end if;
9f373bb8 11755
d2a42b76 11756 Build_Wrapper_Bodies (Loc, Ttyp, Insert_Nod);
9f373bb8 11757 end if;
ee6ba406 11758 end Expand_N_Task_Body;
11759
11760 ------------------------------------
11761 -- Expand_N_Task_Type_Declaration --
11762 ------------------------------------
11763
11764 -- We have several things to do. First we must create a Boolean flag used
11765 -- to mark if the body is elaborated yet. This variable gets set to True
11766 -- when the body of the task is elaborated (we can't rely on the normal
11767 -- ABE mechanism for the task body, since we need to pass an access to
11768 -- this elaboration boolean to the runtime routines).
11769
11770 -- taskE : aliased Boolean := False;
11771
76a1c25b 11772 -- Next a variable is declared to hold the task stack size (either the
11773 -- default : Unspecified_Size, or a value that is set by a pragma
ee6ba406 11774 -- Storage_Size). If the value of the pragma Storage_Size is static, then
11775 -- the variable is initialized with this value:
11776
11777 -- taskZ : Size_Type := Unspecified_Size;
11778 -- or
11779 -- taskZ : Size_Type := Size_Type (size_expression);
11780
57993a53 11781 -- Note: No variable is needed to hold the task relative deadline since
11782 -- its value would never be static because the parameter is of a private
11783 -- type (Ada.Real_Time.Time_Span).
11784
ee6ba406 11785 -- Next we create a corresponding record type declaration used to represent
11786 -- values of this task. The general form of this type declaration is
11787
11788 -- type taskV (discriminants) is record
a7a4a7c2 11789 -- _Task_Id : Task_Id;
11790 -- entry_family : array (bounds) of Void;
11791 -- _Priority : Integer := priority_expression;
11792 -- _Size : Size_Type := size_expression;
11793 -- _Task_Info : Task_Info_Type := task_info_expression;
11794 -- _CPU : Integer := cpu_range_expression;
11795 -- _Relative_Deadline : Time_Span := time_span_expression;
11796 -- _Domain : Dispatching_Domain := dd_expression;
ee6ba406 11797 -- end record;
11798
11799 -- The discriminants are present only if the corresponding task type has
11800 -- discriminants, and they exactly mirror the task type discriminants.
11801
76a1c25b 11802 -- The Id field is always present. It contains the Task_Id value, as set by
11803 -- the call to Create_Task. Note that although the task is limited, the
11804 -- task value record type is not limited, so there is no problem in passing
11805 -- this field as an out parameter to Create_Task.
ee6ba406 11806
76a1c25b 11807 -- One entry_family component is present for each entry family in the task
11808 -- definition. The bounds correspond to the bounds of the entry family
11809 -- (which may depend on discriminants). The element type is void, since we
11810 -- only need the bounds information for determining the entry index. Note
11811 -- that the use of an anonymous array would normally be illegal in this
11812 -- context, but this is a parser check, and the semantics is quite prepared
11813 -- to handle such a case.
11814
11815 -- The _Size field is present only if a Storage_Size pragma appears in the
11816 -- task definition. The expression captures the argument that was present
11817 -- in the pragma, and is used to override the task stack size otherwise
11818 -- associated with the task type.
ee6ba406 11819
06ef5f86 11820 -- The _Priority field is present only if the task entity has a Priority or
11821 -- Interrupt_Priority rep item (pragma, aspect specification or attribute
11822 -- definition clause). It will be filled at the freeze point, when the
11823 -- record init proc is built, to capture the expression of the rep item
11824 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11825 -- here since aspect evaluations are delayed till the freeze point.
ee6ba406 11826
11827 -- The _Task_Info field is present only if a Task_Info pragma appears in
11828 -- the task definition. The expression captures the argument that was
11829 -- present in the pragma, and is used to provide the Task_Image parameter
11830 -- to the call to Create_Task.
11831
06ef5f86 11832 -- The _CPU field is present only if the task entity has a CPU rep item
11833 -- (pragma, aspect specification or attribute definition clause). It will
11834 -- be filled at the freeze point, when the record init proc is built, to
11835 -- capture the expression of the rep item (see Build_Record_Init_Proc in
11836 -- Exp_Ch3). Note that it cannot be filled here since aspect evaluations
11837 -- are delayed till the freeze point.
d9c927cc 11838
57993a53 11839 -- The _Relative_Deadline field is present only if a Relative_Deadline
11840 -- pragma appears in the task definition. The expression captures the
11841 -- argument that was present in the pragma, and is used to provide the
11842 -- Relative_Deadline parameter to the call to Create_Task.
11843
06ef5f86 11844 -- The _Domain field is present only if the task entity has a
11845 -- Dispatching_Domain rep item (pragma, aspect specification or attribute
11846 -- definition clause). It will be filled at the freeze point, when the
11847 -- record init proc is built, to capture the expression of the rep item
11848 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11849 -- here since aspect evaluations are delayed till the freeze point.
a7a4a7c2 11850
ee6ba406 11851 -- When a task is declared, an instance of the task value record is
76a1c25b 11852 -- created. The elaboration of this declaration creates the correct bounds
11853 -- for the entry families, and also evaluates the size, priority, and
11854 -- task_Info expressions if needed. The initialization routine for the task
11855 -- type itself then calls Create_Task with appropriate parameters to
11856 -- initialize the value of the Task_Id field.
ee6ba406 11857
11858 -- Note: the address of this record is passed as the "Discriminants"
76a1c25b 11859 -- parameter for Create_Task. Since Create_Task merely passes this onto the
11860 -- body procedure, it does not matter that it does not quite match the
11861 -- GNARLI model of what is being passed (the record contains more than just
11862 -- the discriminants, but the discriminants can be found from the record
11863 -- value).
ee6ba406 11864
11865 -- The Entity_Id for this created record type is placed in the
11866 -- Corresponding_Record_Type field of the associated task type entity.
11867
11868 -- Next we create a procedure specification for the task body procedure:
11869
11870 -- procedure taskB (_Task : access taskV);
11871
11872 -- Note that this must come after the record type declaration, since
11873 -- the spec refers to this type. It turns out that the initialization
11874 -- procedure for the value type references the task body spec, but that's
11875 -- fine, since it won't be generated till the freeze point for the type,
11876 -- which is certainly after the task body spec declaration.
11877
11878 -- Finally, we set the task index value field of the entry attribute in
11879 -- the case of a simple entry.
11880
11881 procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
57993a53 11882 Loc : constant Source_Ptr := Sloc (N);
89f1e35c 11883 TaskId : constant Entity_Id := Defining_Identifier (N);
57993a53 11884 Tasktyp : constant Entity_Id := Etype (Defining_Identifier (N));
11885 Tasknm : constant Name_Id := Chars (Tasktyp);
11886 Taskdef : constant Node_Id := Task_Definition (N);
ee6ba406 11887
89f1e35c 11888 Body_Decl : Node_Id;
11889 Cdecls : List_Id;
11890 Decl_Stack : Node_Id;
11891 Elab_Decl : Node_Id;
11892 Ent_Stack : Entity_Id;
fb4b3501 11893 Proc_Spec : Node_Id;
11894 Rec_Decl : Node_Id;
11895 Rec_Ent : Entity_Id;
89f1e35c 11896 Size_Decl : Entity_Id;
fb4b3501 11897 Task_Size : Node_Id;
89f1e35c 11898
11899 function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id;
11900 -- Searches the task definition T for the first occurrence of the pragma
11901 -- Relative Deadline. The caller has ensured that the pragma is present
11902 -- in the task definition. Note that this routine cannot be implemented
11903 -- with the Rep Item chain mechanism since Relative_Deadline pragmas are
11904 -- not chained because their expansion into a procedure call statement
11905 -- would cause a break in the chain.
11906
11907 ----------------------------------
11908 -- Get_Relative_Deadline_Pragma --
11909 ----------------------------------
11910
11911 function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id is
11912 N : Node_Id;
11913
11914 begin
11915 N := First (Visible_Declarations (T));
11916 while Present (N) loop
11917 if Nkind (N) = N_Pragma
11918 and then Pragma_Name (N) = Name_Relative_Deadline
11919 then
11920 return N;
11921 end if;
11922
11923 Next (N);
11924 end loop;
11925
11926 N := First (Private_Declarations (T));
11927 while Present (N) loop
11928 if Nkind (N) = N_Pragma
11929 and then Pragma_Name (N) = Name_Relative_Deadline
11930 then
11931 return N;
11932 end if;
11933
11934 Next (N);
11935 end loop;
11936
11937 raise Program_Error;
11938 end Get_Relative_Deadline_Pragma;
11939
11940 -- Start of processing for Expand_N_Task_Type_Declaration
ee6ba406 11941
11942 begin
f15731c4 11943 -- If already expanded, nothing to do
11944
9dfe12ae 11945 if Present (Corresponding_Record_Type (Tasktyp)) then
f15731c4 11946 return;
ee6ba406 11947 end if;
11948
f15731c4 11949 -- Here we will do the expansion
11950
11951 Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
9f373bb8 11952
f15731c4 11953 Rec_Ent := Defining_Identifier (Rec_Decl);
11954 Cdecls := Component_Items (Component_List
11955 (Type_Definition (Rec_Decl)));
11956
ee6ba406 11957 Qualify_Entity_Names (N);
11958
11959 -- First create the elaboration variable
11960
11961 Elab_Decl :=
11962 Make_Object_Declaration (Loc,
11963 Defining_Identifier =>
11964 Make_Defining_Identifier (Sloc (Tasktyp),
11965 Chars => New_External_Name (Tasknm, 'E')),
11966 Aliased_Present => True,
83c6c069 11967 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
11968 Expression => New_Occurrence_Of (Standard_False, Loc));
89f1e35c 11969
ee6ba406 11970 Insert_After (N, Elab_Decl);
11971
11972 -- Next create the declaration of the size variable (tasknmZ)
11973
11974 Set_Storage_Size_Variable (Tasktyp,
11975 Make_Defining_Identifier (Sloc (Tasktyp),
11976 Chars => New_External_Name (Tasknm, 'Z')));
11977
d8e08976 11978 if Present (Taskdef)
11979 and then Has_Storage_Size_Pragma (Taskdef)
11980 and then
cda40848 11981 Is_OK_Static_Expression
f52e508d 11982 (Expression
11983 (First (Pragma_Argument_Associations
89f1e35c 11984 (Get_Rep_Pragma (TaskId, Name_Storage_Size)))))
ee6ba406 11985 then
11986 Size_Decl :=
11987 Make_Object_Declaration (Loc,
11988 Defining_Identifier => Storage_Size_Variable (Tasktyp),
83c6c069 11989 Object_Definition =>
11990 New_Occurrence_Of (RTE (RE_Size_Type), Loc),
f52e508d 11991 Expression =>
ee6ba406 11992 Convert_To (RTE (RE_Size_Type),
f52e508d 11993 Relocate_Node
11994 (Expression (First (Pragma_Argument_Associations
89f1e35c 11995 (Get_Rep_Pragma
11996 (TaskId, Name_Storage_Size)))))));
ee6ba406 11997
11998 else
11999 Size_Decl :=
12000 Make_Object_Declaration (Loc,
12001 Defining_Identifier => Storage_Size_Variable (Tasktyp),
f52e508d 12002 Object_Definition =>
83c6c069 12003 New_Occurrence_Of (RTE (RE_Size_Type), Loc),
f52e508d 12004 Expression =>
83c6c069 12005 New_Occurrence_Of (RTE (RE_Unspecified_Size), Loc));
ee6ba406 12006 end if;
12007
12008 Insert_After (Elab_Decl, Size_Decl);
12009
76a1c25b 12010 -- Next build the rest of the corresponding record declaration. This is
12011 -- done last, since the corresponding record initialization procedure
12012 -- will reference the previously created entities.
ee6ba406 12013
2866d595 12014 -- Fill in the component declarations -- first the _Task_Id field
ee6ba406 12015
12016 Append_To (Cdecls,
12017 Make_Component_Declaration (Loc,
f52e508d 12018 Defining_Identifier =>
ee6ba406 12019 Make_Defining_Identifier (Loc, Name_uTask_Id),
b5ff3ed8 12020 Component_Definition =>
12021 Make_Component_Definition (Loc,
12022 Aliased_Present => False,
83c6c069 12023 Subtype_Indication => New_Occurrence_Of (RTE (RO_ST_Task_Id),
b5ff3ed8 12024 Loc))));
ee6ba406 12025
76a1c25b 12026 -- Declare static ATCB (that is, created by the expander) if we are
12027 -- using the Restricted run time.
8f71d067 12028
12029 if Restricted_Profile then
12030 Append_To (Cdecls,
12031 Make_Component_Declaration (Loc,
12032 Defining_Identifier =>
12033 Make_Defining_Identifier (Loc, Name_uATCB),
12034
12035 Component_Definition =>
12036 Make_Component_Definition (Loc,
12037 Aliased_Present => True,
12038 Subtype_Indication => Make_Subtype_Indication (Loc,
f52e508d 12039 Subtype_Mark =>
12040 New_Occurrence_Of (RTE (RE_Ada_Task_Control_Block), Loc),
8f71d067 12041
12042 Constraint =>
12043 Make_Index_Or_Discriminant_Constraint (Loc,
12044 Constraints =>
12045 New_List (Make_Integer_Literal (Loc, 0)))))));
12046
12047 end if;
12048
76a1c25b 12049 -- Declare static stack (that is, created by the expander) if we are
12050 -- using the Restricted run time on a bare board configuration.
fb4b3501 12051
c0688d2b 12052 if Restricted_Profile and then Preallocated_Stacks_On_Target then
12053
fb4b3501 12054 -- First we need to extract the appropriate stack size
12055
12056 Ent_Stack := Make_Defining_Identifier (Loc, Name_uStack);
12057
12058 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
cb5f80c1 12059 declare
12060 Expr_N : constant Node_Id :=
12061 Expression (First (
12062 Pragma_Argument_Associations (
89f1e35c 12063 Get_Rep_Pragma (TaskId, Name_Storage_Size))));
cb5f80c1 12064 Etyp : constant Entity_Id := Etype (Expr_N);
12065 P : constant Node_Id := Parent (Expr_N);
12066
12067 begin
12068 -- The stack is defined inside the corresponding record.
12069 -- Therefore if the size of the stack is set by means of
12070 -- a discriminant, we must reference the discriminant of the
12071 -- corresponding record type.
12072
12073 if Nkind (Expr_N) in N_Has_Entity
12074 and then Present (Discriminal_Link (Entity (Expr_N)))
12075 then
12076 Task_Size :=
83c6c069 12077 New_Occurrence_Of
cb5f80c1 12078 (CR_Discriminant (Discriminal_Link (Entity (Expr_N))),
12079 Loc);
12080 Set_Parent (Task_Size, P);
12081 Set_Etype (Task_Size, Etyp);
12082 Set_Analyzed (Task_Size);
12083
12084 else
12085 Task_Size := Relocate_Node (Expr_N);
12086 end if;
12087 end;
12088
fb4b3501 12089 else
12090 Task_Size :=
83c6c069 12091 New_Occurrence_Of (RTE (RE_Default_Stack_Size), Loc);
fb4b3501 12092 end if;
12093
12094 Decl_Stack := Make_Component_Declaration (Loc,
12095 Defining_Identifier => Ent_Stack,
12096
12097 Component_Definition =>
12098 Make_Component_Definition (Loc,
12099 Aliased_Present => True,
12100 Subtype_Indication => Make_Subtype_Indication (Loc,
12101 Subtype_Mark =>
12102 New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
12103
12104 Constraint =>
12105 Make_Index_Or_Discriminant_Constraint (Loc,
12106 Constraints => New_List (Make_Range (Loc,
12107 Low_Bound => Make_Integer_Literal (Loc, 1),
12108 High_Bound => Convert_To (RTE (RE_Storage_Offset),
12109 Task_Size)))))));
12110
12111 Append_To (Cdecls, Decl_Stack);
12112
76a1c25b 12113 -- The appropriate alignment for the stack is ensured by the run-time
12114 -- code in charge of task creation.
fb4b3501 12115
12116 end if;
12117
ee6ba406 12118 -- Add components for entry families
12119
12120 Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
12121
06ef5f86 12122 -- Add the _Priority component if a Interrupt_Priority or Priority rep
12123 -- item is present.
ee6ba406 12124
06ef5f86 12125 if Has_Rep_Item (TaskId, Name_Priority, Check_Parents => False) then
12126 Append_To (Cdecls,
12127 Make_Component_Declaration (Loc,
12128 Defining_Identifier =>
12129 Make_Defining_Identifier (Loc, Name_uPriority),
12130 Component_Definition =>
12131 Make_Component_Definition (Loc,
12132 Aliased_Present => False,
12133 Subtype_Indication =>
83c6c069 12134 New_Occurrence_Of (Standard_Integer, Loc))));
06ef5f86 12135 end if;
ee6ba406 12136
89f1e35c 12137 -- Add the _Size component if a Storage_Size pragma is present
ee6ba406 12138
c0688d2b 12139 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
ee6ba406 12140 Append_To (Cdecls,
12141 Make_Component_Declaration (Loc,
12142 Defining_Identifier =>
12143 Make_Defining_Identifier (Loc, Name_uSize),
12144
b5ff3ed8 12145 Component_Definition =>
12146 Make_Component_Definition (Loc,
12147 Aliased_Present => False,
89f1e35c 12148 Subtype_Indication =>
83c6c069 12149 New_Occurrence_Of (RTE (RE_Size_Type), Loc)),
ee6ba406 12150
12151 Expression =>
12152 Convert_To (RTE (RE_Size_Type),
12153 Relocate_Node (
12154 Expression (First (
12155 Pragma_Argument_Associations (
89f1e35c 12156 Get_Rep_Pragma (TaskId, Name_Storage_Size))))))));
ee6ba406 12157 end if;
12158
12159 -- Add the _Task_Info component if a Task_Info pragma is present
12160
89b3b365 12161 if Has_Rep_Pragma (TaskId, Name_Task_Info, Check_Parents => False) then
ee6ba406 12162 Append_To (Cdecls,
12163 Make_Component_Declaration (Loc,
12164 Defining_Identifier =>
12165 Make_Defining_Identifier (Loc, Name_uTask_Info),
0914a918 12166
b5ff3ed8 12167 Component_Definition =>
12168 Make_Component_Definition (Loc,
12169 Aliased_Present => False,
12170 Subtype_Indication =>
83c6c069 12171 New_Occurrence_Of (RTE (RE_Task_Info_Type), Loc)),
0914a918 12172
ee6ba406 12173 Expression => New_Copy (
12174 Expression (First (
12175 Pragma_Argument_Associations (
89b3b365 12176 Get_Rep_Pragma
12177 (TaskId, Name_Task_Info, Check_Parents => False)))))));
ee6ba406 12178 end if;
12179
06ef5f86 12180 -- Add the _CPU component if a CPU rep item is present
d9c927cc 12181
06ef5f86 12182 if Has_Rep_Item (TaskId, Name_CPU, Check_Parents => False) then
12183 Append_To (Cdecls,
12184 Make_Component_Declaration (Loc,
12185 Defining_Identifier =>
12186 Make_Defining_Identifier (Loc, Name_uCPU),
d9c927cc 12187
06ef5f86 12188 Component_Definition =>
12189 Make_Component_Definition (Loc,
12190 Aliased_Present => False,
12191 Subtype_Indication =>
83c6c069 12192 New_Occurrence_Of (RTE (RE_CPU_Range), Loc))));
06ef5f86 12193 end if;
d9c927cc 12194
57993a53 12195 -- Add the _Relative_Deadline component if a Relative_Deadline pragma is
12196 -- present. If we are using a restricted run time this component will
12197 -- not be added (deadlines are not allowed by the Ravenscar profile).
12198
12199 if not Restricted_Profile
12200 and then Present (Taskdef)
12201 and then Has_Relative_Deadline_Pragma (Taskdef)
12202 then
12203 Append_To (Cdecls,
12204 Make_Component_Declaration (Loc,
12205 Defining_Identifier =>
12206 Make_Defining_Identifier (Loc, Name_uRelative_Deadline),
12207
12208 Component_Definition =>
12209 Make_Component_Definition (Loc,
12210 Aliased_Present => False,
12211 Subtype_Indication =>
83c6c069 12212 New_Occurrence_Of (RTE (RE_Time_Span), Loc)),
57993a53 12213
12214 Expression =>
12215 Convert_To (RTE (RE_Time_Span),
12216 Relocate_Node (
12217 Expression (First (
12218 Pragma_Argument_Associations (
89f1e35c 12219 Get_Relative_Deadline_Pragma (Taskdef))))))));
57993a53 12220 end if;
12221
06ef5f86 12222 -- Add the _Dispatching_Domain component if a Dispatching_Domain rep
12223 -- item is present. If we are using a restricted run time this component
12224 -- will not be added (dispatching domains are not allowed by the
12225 -- Ravenscar profile).
a7a4a7c2 12226
06ef5f86 12227 if not Restricted_Profile
12228 and then
12229 Has_Rep_Item
12230 (TaskId, Name_Dispatching_Domain, Check_Parents => False)
12231 then
a7a4a7c2 12232 Append_To (Cdecls,
12233 Make_Component_Declaration (Loc,
e7b8f0ea 12234 Defining_Identifier =>
a7a4a7c2 12235 Make_Defining_Identifier (Loc, Name_uDispatching_Domain),
12236
12237 Component_Definition =>
12238 Make_Component_Definition (Loc,
12239 Aliased_Present => False,
12240 Subtype_Indication =>
83c6c069 12241 New_Occurrence_Of
89f1e35c 12242 (RTE (RE_Dispatching_Domain_Access), Loc))));
a7a4a7c2 12243 end if;
12244
ee6ba406 12245 Insert_After (Size_Decl, Rec_Decl);
12246
12247 -- Analyze the record declaration immediately after construction,
12248 -- because the initialization procedure is needed for single task
12249 -- declarations before the next entity is analyzed.
12250
12251 Analyze (Rec_Decl);
12252
12253 -- Create the declaration of the task body procedure
12254
12255 Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
12256 Body_Decl :=
12257 Make_Subprogram_Declaration (Loc,
12258 Specification => Proc_Spec);
2f06c88a 12259 Set_Is_Task_Body_Procedure (Body_Decl);
ee6ba406 12260
12261 Insert_After (Rec_Decl, Body_Decl);
12262
76a1c25b 12263 -- The subprogram does not comes from source, so we have to indicate the
12264 -- need for debugging information explicitly.
9dfe12ae 12265
70966f50 12266 if Comes_From_Source (Original_Node (N)) then
12267 Set_Debug_Info_Needed (Defining_Entity (Proc_Spec));
12268 end if;
9dfe12ae 12269
76a1c25b 12270 -- Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
12271 -- the corresponding record has been frozen.
ee6ba406 12272
de54c5ab 12273 if Ada_Version >= Ada_2005 then
d2a42b76 12274 Build_Wrapper_Specs (Loc, Tasktyp, Rec_Decl);
9f373bb8 12275 end if;
12276
12277 -- Ada 2005 (AI-345): We must defer freezing to allow further
12278 -- declaration of primitive subprograms covering task interfaces
12279
12280 if Ada_Version <= Ada_95 then
12281
12282 -- Now we can freeze the corresponding record. This needs manually
12283 -- freezing, since it is really part of the task type, and the task
12284 -- type is frozen at this stage. We of course need the initialization
12285 -- procedure for this corresponding record type and we won't get it
12286 -- in time if we don't freeze now.
12287
12288 declare
d74fc39a 12289 L : constant List_Id := Freeze_Entity (Rec_Ent, N);
9f373bb8 12290 begin
12291 if Is_Non_Empty_List (L) then
12292 Insert_List_After (Body_Decl, L);
12293 end if;
12294 end;
12295 end if;
ee6ba406 12296
76a1c25b 12297 -- Complete the expansion of access types to the current task type, if
12298 -- any were declared.
ee6ba406 12299
f15731c4 12300 Expand_Previous_Access_Type (Tasktyp);
f9e6d9d0 12301
3ff5e35d 12302 -- Create wrappers for entries that have contract cases, preconditions
12303 -- and postconditions.
f9e6d9d0 12304
12305 declare
12306 Ent : Entity_Id;
12307
12308 begin
12309 Ent := First_Entity (Tasktyp);
12310 while Present (Ent) loop
3ff5e35d 12311 if Ekind_In (Ent, E_Entry, E_Entry_Family) then
12312 Build_Contract_Wrapper (Ent, N);
f9e6d9d0 12313 end if;
12314
12315 Next_Entity (Ent);
12316 end loop;
12317 end;
ee6ba406 12318 end Expand_N_Task_Type_Declaration;
12319
12320 -------------------------------
12321 -- Expand_N_Timed_Entry_Call --
12322 -------------------------------
12323
76a1c25b 12324 -- A timed entry call in normal case is not implemented using ATC mechanism
12325 -- anymore for efficiency reason.
ee6ba406 12326
12327 -- select
12328 -- T.E;
12329 -- S1;
12330 -- or
85377c9b 12331 -- delay D;
ee6ba406 12332 -- S2;
12333 -- end select;
12334
85377c9b 12335 -- is expanded as follows:
ee6ba406 12336
12337 -- 1) When T.E is a task entry_call;
12338
12339 -- declare
d62940bf 12340 -- B : Boolean;
12341 -- X : Task_Entry_Index := <entry index>;
ee6ba406 12342 -- DX : Duration := To_Duration (D);
d62940bf 12343 -- M : Delay_Mode := <discriminant>;
12344 -- P : parms := (parm, parm, parm);
ee6ba406 12345
12346 -- begin
5809835d 12347 -- Timed_Protected_Entry_Call
12348 -- (<acceptor-task>, X, P'Address, DX, M, B);
ee6ba406 12349 -- if B then
12350 -- S1;
12351 -- else
12352 -- S2;
12353 -- end if;
12354 -- end;
12355
12356 -- 2) When T.E is a protected entry_call;
12357
12358 -- declare
12359 -- B : Boolean;
12360 -- X : Protected_Entry_Index := <entry index>;
12361 -- DX : Duration := To_Duration (D);
d62940bf 12362 -- M : Delay_Mode := <discriminant>;
ee6ba406 12363 -- P : parms := (parm, parm, parm);
12364
12365 -- begin
5809835d 12366 -- Timed_Protected_Entry_Call
12367 -- (<object>'unchecked_access, X, P'Address, DX, M, B);
ee6ba406 12368 -- if B then
12369 -- S1;
12370 -- else
12371 -- S2;
12372 -- end if;
12373 -- end;
12374
0fc711fa 12375 -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call, there
12376 -- is no delay and the triggering statements are executed. We first
c96806b2 12377 -- determine the kind of the triggering call and then execute a
0fc711fa 12378 -- synchronized operation or a direct call.
d62940bf 12379
12380 -- declare
12381 -- B : Boolean := False;
12382 -- C : Ada.Tags.Prim_Op_Kind;
12383 -- DX : Duration := To_Duration (D)
5809835d 12384 -- K : Ada.Tags.Tagged_Kind :=
12385 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
d62940bf 12386 -- M : Integer :=...;
12387 -- P : Parameters := (Param1 .. ParamN);
6cb4b973 12388 -- S : Integer;
d62940bf 12389
12390 -- begin
37c6e44c 12391 -- if K = Ada.Tags.TK_Limited_Tagged
12392 -- or else K = Ada.Tags.TK_Tagged
12393 -- then
952af0b9 12394 -- <dispatching-call>;
0fc711fa 12395 -- B := True;
d62940bf 12396
952af0b9 12397 -- else
5809835d 12398 -- S :=
12399 -- Ada.Tags.Get_Offset_Index
12400 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
d62940bf 12401
952af0b9 12402 -- _Disp_Timed_Select (<object>, S, P'Address, DX, M, C, B);
12403
12404 -- if C = POK_Protected_Entry
12405 -- or else C = POK_Task_Entry
d62940bf 12406 -- then
952af0b9 12407 -- Param1 := P.Param1;
12408 -- ...
12409 -- ParamN := P.ParamN;
12410 -- end if;
12411
12412 -- if B then
12413 -- if C = POK_Procedure
12414 -- or else C = POK_Protected_Procedure
12415 -- or else C = POK_Task_Procedure
12416 -- then
12417 -- <dispatching-call>;
12418 -- end if;
0fc711fa 12419 -- end if;
d62940bf 12420 -- end if;
0fc711fa 12421
12422 -- if B then
12423 -- <triggering-statements>
12424 -- else
12425 -- <timed-statements>
12426 -- end if;
d62940bf 12427 -- end;
5a4d11b2 12428
12429 -- The triggering statement and the sequence of timed statements have not
da94c58f 12430 -- been analyzed yet (see Analyzed_Timed_Entry_Call), but they may contain
0fc711fa 12431 -- global references if within an instantiation.
d62940bf 12432
ee6ba406 12433 procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
12434 Loc : constant Source_Ptr := Sloc (N);
12435
952af0b9 12436 Actuals : List_Id;
12437 Blk_Typ : Entity_Id;
12438 Call : Node_Id;
12439 Call_Ent : Entity_Id;
12440 Conc_Typ_Stmts : List_Id;
12441 Concval : Node_Id;
85377c9b 12442 D_Alt : constant Node_Id := Delay_Alternative (N);
952af0b9 12443 D_Conv : Node_Id;
12444 D_Disc : Node_Id;
e5e512c5 12445 D_Stat : Node_Id := Delay_Statement (D_Alt);
0703c8dc 12446 D_Stats : List_Id;
952af0b9 12447 D_Type : Entity_Id;
12448 Decls : List_Id;
12449 Dummy : Node_Id;
85377c9b 12450 E_Alt : constant Node_Id := Entry_Call_Alternative (N);
e5e512c5 12451 E_Call : Node_Id := Entry_Call_Statement (E_Alt);
0703c8dc 12452 E_Stats : List_Id;
952af0b9 12453 Ename : Node_Id;
12454 Formals : List_Id;
12455 Index : Node_Id;
5809835d 12456 Is_Disp_Select : Boolean;
952af0b9 12457 Lim_Typ_Stmts : List_Id;
12458 N_Stats : List_Id;
12459 Obj : Entity_Id;
12460 Param : Node_Id;
12461 Params : List_Id;
12462 Stmt : Node_Id;
12463 Stmts : List_Id;
12464 Unpack : List_Id;
d62940bf 12465
12466 B : Entity_Id; -- Call status flag
12467 C : Entity_Id; -- Call kind
12468 D : Entity_Id; -- Delay
952af0b9 12469 K : Entity_Id; -- Tagged kind
d62940bf 12470 M : Entity_Id; -- Delay mode
76a1c25b 12471 P : Entity_Id; -- Parameter block
d62940bf 12472 S : Entity_Id; -- Primitive operation slot
ee6ba406 12473
e5e512c5 12474 -- Start of processing for Expand_N_Timed_Entry_Call
12475
ee6ba406 12476 begin
67e60322 12477 -- Under the Ravenscar profile, timed entry calls are excluded. An error
12478 -- was already reported on spec, so do not attempt to expand the call.
12479
12480 if Restriction_Active (No_Select_Statements) then
12481 return;
12482 end if;
12483
85377c9b 12484 Process_Statements_For_Controlled_Objects (E_Alt);
12485 Process_Statements_For_Controlled_Objects (D_Alt);
f239f5be 12486
e3cb8202 12487 Ensure_Statement_Present (Sloc (D_Stat), D_Alt);
12488
0703c8dc 12489 -- Retrieve E_Stats and D_Stats now because the finalization machinery
12490 -- may wrap them in blocks.
6121886e 12491
85377c9b 12492 E_Stats := Statements (E_Alt);
12493 D_Stats := Statements (D_Alt);
6121886e 12494
ee6ba406 12495 -- The arguments in the call may require dynamic allocation, and the
12496 -- call statement may have been transformed into a block. The block
12497 -- may contain additional declarations for internal entities, and the
12498 -- original call is found by sequential search.
12499
12500 if Nkind (E_Call) = N_Block_Statement then
12501 E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
5809835d 12502 while not Nkind_In (E_Call, N_Procedure_Call_Statement,
12503 N_Entry_Call_Statement)
ee6ba406 12504 loop
12505 Next (E_Call);
12506 end loop;
12507 end if;
12508
5809835d 12509 Is_Disp_Select :=
de54c5ab 12510 Ada_Version >= Ada_2005
5809835d 12511 and then Nkind (E_Call) = N_Procedure_Call_Statement;
12512
12513 if Is_Disp_Select then
d62940bf 12514 Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
d62940bf 12515 Decls := New_List;
da94c58f 12516
d62940bf 12517 Stmts := New_List;
ee6ba406 12518
5809835d 12519 -- Generate:
12520 -- B : Boolean := False;
12521
12522 B := Build_B (Loc, Decls);
12523
12524 -- Generate:
12525 -- C : Ada.Tags.Prim_Op_Kind;
12526
12527 C := Build_C (Loc, Decls);
12528
12529 -- Because the analysis of all statements was disabled, manually
12530 -- analyze the delay statement.
12531
12532 Analyze (D_Stat);
12533 D_Stat := Original_Node (D_Stat);
12534
d62940bf 12535 else
12536 -- Build an entry call using Simple_Entry_Call
ee6ba406 12537
d62940bf 12538 Extract_Entry (E_Call, Concval, Ename, Index);
12539 Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
ee6ba406 12540
d62940bf 12541 Decls := Declarations (E_Call);
12542 Stmts := Statements (Handled_Statement_Sequence (E_Call));
12543
12544 if No (Decls) then
12545 Decls := New_List;
12546 end if;
d62940bf 12547
d62940bf 12548 -- Generate:
12549 -- B : Boolean;
12550
12551 B := Make_Defining_Identifier (Loc, Name_uB);
12552
12553 Prepend_To (Decls,
12554 Make_Object_Declaration (Loc,
4d6daf23 12555 Defining_Identifier => B,
83c6c069 12556 Object_Definition =>
12557 New_Occurrence_Of (Standard_Boolean, Loc)));
d62940bf 12558 end if;
12559
d62940bf 12560 -- Duration and mode processing
12561
12562 D_Type := Base_Type (Etype (Expression (D_Stat)));
ee6ba406 12563
5809835d 12564 -- Use the type of the delay expression (Calendar or Real_Time) to
12565 -- generate the appropriate conversion.
ee6ba406 12566
12567 if Nkind (D_Stat) = N_Delay_Relative_Statement then
d62940bf 12568 D_Disc := Make_Integer_Literal (Loc, 0);
12569 D_Conv := Relocate_Node (Expression (D_Stat));
ee6ba406 12570
d62940bf 12571 elsif Is_RTE (D_Type, RO_CA_Time) then
12572 D_Disc := Make_Integer_Literal (Loc, 1);
4d6daf23 12573 D_Conv :=
12574 Make_Function_Call (Loc,
83c6c069 12575 Name => New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
4d6daf23 12576 Parameter_Associations =>
12577 New_List (New_Copy (Expression (D_Stat))));
ee6ba406 12578
d62940bf 12579 else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
12580 D_Disc := Make_Integer_Literal (Loc, 2);
4d6daf23 12581 D_Conv :=
12582 Make_Function_Call (Loc,
83c6c069 12583 Name => New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
4d6daf23 12584 Parameter_Associations =>
12585 New_List (New_Copy (Expression (D_Stat))));
ee6ba406 12586 end if;
12587
ec97ce79 12588 D := Make_Temporary (Loc, 'D');
ee6ba406 12589
d62940bf 12590 -- Generate:
12591 -- D : Duration;
ee6ba406 12592
12593 Append_To (Decls,
12594 Make_Object_Declaration (Loc,
4d6daf23 12595 Defining_Identifier => D,
83c6c069 12596 Object_Definition => New_Occurrence_Of (Standard_Duration, Loc)));
ee6ba406 12597
ec97ce79 12598 M := Make_Temporary (Loc, 'M');
ee6ba406 12599
d62940bf 12600 -- Generate:
12601 -- M : Integer := (0 | 1 | 2);
ee6ba406 12602
d62940bf 12603 Append_To (Decls,
ee6ba406 12604 Make_Object_Declaration (Loc,
4d6daf23 12605 Defining_Identifier => M,
83c6c069 12606 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
4d6daf23 12607 Expression => D_Disc));
ee6ba406 12608
36b938a3 12609 -- Do the assignment at this stage only because the evaluation of the
ee6ba406 12610 -- expression must not occur before (see ACVC C97302A).
12611
d62940bf 12612 Append_To (Stmts,
ee6ba406 12613 Make_Assignment_Statement (Loc,
83c6c069 12614 Name => New_Occurrence_Of (D, Loc),
4d6daf23 12615 Expression => D_Conv));
ee6ba406 12616
d62940bf 12617 -- Parameter block processing
ee6ba406 12618
d62940bf 12619 -- Manually create the parameter block for dispatching calls. In the
12620 -- case of entries, the block has already been created during the call
12621 -- to Build_Simple_Entry_Call.
ee6ba406 12622
5809835d 12623 if Is_Disp_Select then
12624
952af0b9 12625 -- Tagged kind processing, generate:
12626 -- K : Ada.Tags.Tagged_Kind :=
12627 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag <object>));
12628
12629 K := Build_K (Loc, Decls, Obj);
12630
d62940bf 12631 Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
4d6daf23 12632 P :=
12633 Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
ee6ba406 12634
d62940bf 12635 -- Dispatch table slot processing, generate:
952af0b9 12636 -- S : Integer;
ee6ba406 12637
952af0b9 12638 S := Build_S (Loc, Decls);
ee6ba406 12639
d62940bf 12640 -- Generate:
5809835d 12641 -- S := Ada.Tags.Get_Offset_Index
12642 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
952af0b9 12643
5809835d 12644 Conc_Typ_Stmts :=
12645 New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
952af0b9 12646
12647 -- Generate:
5809835d 12648 -- _Disp_Timed_Select (<object>, S, P'Address, D, M, C, B);
ee6ba406 12649
d62940bf 12650 -- where Obj is the controlling formal parameter, S is the dispatch
12651 -- table slot number of the dispatching operation, P is the wrapped
12652 -- parameter block, D is the duration, M is the duration mode, C is
12653 -- the call kind and B is the call status.
ee6ba406 12654
d62940bf 12655 Params := New_List;
ee6ba406 12656
5809835d 12657 Append_To (Params, New_Copy_Tree (Obj));
83c6c069 12658 Append_To (Params, New_Occurrence_Of (S, Loc));
4d6daf23 12659 Append_To (Params,
12660 Make_Attribute_Reference (Loc,
83c6c069 12661 Prefix => New_Occurrence_Of (P, Loc),
4d6daf23 12662 Attribute_Name => Name_Address));
83c6c069 12663 Append_To (Params, New_Occurrence_Of (D, Loc));
12664 Append_To (Params, New_Occurrence_Of (M, Loc));
12665 Append_To (Params, New_Occurrence_Of (C, Loc));
12666 Append_To (Params, New_Occurrence_Of (B, Loc));
ee6ba406 12667
952af0b9 12668 Append_To (Conc_Typ_Stmts,
d62940bf 12669 Make_Procedure_Call_Statement (Loc,
12670 Name =>
83c6c069 12671 New_Occurrence_Of
4d6daf23 12672 (Find_Prim_Op
12673 (Etype (Etype (Obj)), Name_uDisp_Timed_Select), Loc),
12674 Parameter_Associations => Params));
d62940bf 12675
12676 -- Generate:
12677 -- if C = POK_Protected_Entry
12678 -- or else C = POK_Task_Entry
12679 -- then
12680 -- Param1 := P.Param1;
12681 -- ...
12682 -- ParamN := P.ParamN;
12683 -- end if;
ee6ba406 12684
76a1c25b 12685 Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
d62940bf 12686
76a1c25b 12687 -- Generate the if statement only when the packed parameters need
12688 -- explicit assignments to their corresponding actuals.
ee6ba406 12689
76a1c25b 12690 if Present (Unpack) then
952af0b9 12691 Append_To (Conc_Typ_Stmts,
85377c9b 12692 Make_Implicit_If_Statement (N,
76a1c25b 12693
4d6daf23 12694 Condition =>
76a1c25b 12695 Make_Or_Else (Loc,
4d6daf23 12696 Left_Opnd =>
76a1c25b 12697 Make_Op_Eq (Loc,
83c6c069 12698 Left_Opnd => New_Occurrence_Of (C, Loc),
76a1c25b 12699 Right_Opnd =>
83c6c069 12700 New_Occurrence_Of
4d6daf23 12701 (RTE (RE_POK_Protected_Entry), Loc)),
12702
76a1c25b 12703 Right_Opnd =>
12704 Make_Op_Eq (Loc,
83c6c069 12705 Left_Opnd => New_Occurrence_Of (C, Loc),
76a1c25b 12706 Right_Opnd =>
83c6c069 12707 New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
76a1c25b 12708
4d6daf23 12709 Then_Statements => Unpack));
76a1c25b 12710 end if;
d62940bf 12711
12712 -- Generate:
76a1c25b 12713
d62940bf 12714 -- if B then
12715 -- if C = POK_Procedure
12716 -- or else C = POK_Protected_Procedure
12717 -- or else C = POK_Task_Procedure
12718 -- then
952af0b9 12719 -- <dispatching-call>
d62940bf 12720 -- end if;
d62940bf 12721 -- end if;
ee6ba406 12722
0fc711fa 12723 N_Stats := New_List (
85377c9b 12724 Make_Implicit_If_Statement (N,
d62940bf 12725 Condition =>
12726 Make_Or_Else (Loc,
12727 Left_Opnd =>
12728 Make_Op_Eq (Loc,
83c6c069 12729 Left_Opnd => New_Occurrence_Of (C, Loc),
d62940bf 12730 Right_Opnd =>
83c6c069 12731 New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
4d6daf23 12732
d62940bf 12733 Right_Opnd =>
12734 Make_Or_Else (Loc,
12735 Left_Opnd =>
12736 Make_Op_Eq (Loc,
83c6c069 12737 Left_Opnd => New_Occurrence_Of (C, Loc),
d62940bf 12738 Right_Opnd =>
83c6c069 12739 New_Occurrence_Of (RTE (
d62940bf 12740 RE_POK_Protected_Procedure), Loc)),
12741 Right_Opnd =>
12742 Make_Op_Eq (Loc,
83c6c069 12743 Left_Opnd => New_Occurrence_Of (C, Loc),
d62940bf 12744 Right_Opnd =>
83c6c069 12745 New_Occurrence_Of
4d6daf23 12746 (RTE (RE_POK_Task_Procedure), Loc)))),
ee6ba406 12747
4d6daf23 12748 Then_Statements => New_List (E_Call)));
ee6ba406 12749
952af0b9 12750 Append_To (Conc_Typ_Stmts,
85377c9b 12751 Make_Implicit_If_Statement (N,
83c6c069 12752 Condition => New_Occurrence_Of (B, Loc),
0fc711fa 12753 Then_Statements => N_Stats));
952af0b9 12754
12755 -- Generate:
12756 -- <dispatching-call>;
0fc711fa 12757 -- B := True;
952af0b9 12758
0fc711fa 12759 Lim_Typ_Stmts :=
12760 New_List (New_Copy_Tree (E_Call),
12761 Make_Assignment_Statement (Loc,
12762 Name => New_Occurrence_Of (B, Loc),
12763 Expression => New_Occurrence_Of (Standard_True, Loc)));
952af0b9 12764
12765 -- Generate:
37c6e44c 12766 -- if K = Ada.Tags.TK_Limited_Tagged
12767 -- or else K = Ada.Tags.TK_Tagged
12768 -- then
952af0b9 12769 -- Lim_Typ_Stmts
12770 -- else
12771 -- Conc_Typ_Stmts
12772 -- end if;
12773
12774 Append_To (Stmts,
85377c9b 12775 Make_Implicit_If_Statement (N,
37c6e44c 12776 Condition => Build_Dispatching_Tag_Check (K, N),
4d6daf23 12777 Then_Statements => Lim_Typ_Stmts,
12778 Else_Statements => Conc_Typ_Stmts));
952af0b9 12779
0fc711fa 12780 -- Generate:
12781
12782 -- if B then
12783 -- <triggering-statements>
12784 -- else
12785 -- <timed-statements>
12786 -- end if;
12787
12788 Append_To (Stmts,
12789 Make_Implicit_If_Statement (N,
12790 Condition => New_Occurrence_Of (B, Loc),
12791 Then_Statements => E_Stats,
12792 Else_Statements => D_Stats));
12793
d62940bf 12794 else
0fc711fa 12795 -- Simple case of a non-dispatching trigger. Skip assignments to
12796 -- temporaries created for in-out parameters.
12797
d62940bf 12798 -- This makes unwarranted assumptions about the shape of the expanded
12799 -- tree for the call, and should be cleaned up ???
ee6ba406 12800
d62940bf 12801 Stmt := First (Stmts);
12802 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
12803 Next (Stmt);
12804 end loop;
ee6ba406 12805
36b938a3 12806 -- Do the assignment at this stage only because the evaluation
d62940bf 12807 -- of the expression must not occur before (see ACVC C97302A).
ee6ba406 12808
d62940bf 12809 Insert_Before (Stmt,
12810 Make_Assignment_Statement (Loc,
83c6c069 12811 Name => New_Occurrence_Of (D, Loc),
d62940bf 12812 Expression => D_Conv));
12813
12814 Call := Stmt;
12815 Params := Parameter_Associations (Call);
12816
12817 -- For a protected type, we build a Timed_Protected_Entry_Call
12818
12819 if Is_Protected_Type (Etype (Concval)) then
12820
12821 -- Create a new call statement
12822
12823 Param := First (Params);
12824 while Present (Param)
12825 and then not Is_RTE (Etype (Param), RE_Call_Modes)
ee6ba406 12826 loop
d62940bf 12827 Next (Param);
ee6ba406 12828 end loop;
12829
d62940bf 12830 Dummy := Remove_Next (Next (Param));
ee6ba406 12831
d62940bf 12832 -- Remove garbage is following the Cancel_Param if present
ee6ba406 12833
d62940bf 12834 Dummy := Next (Param);
ee6ba406 12835
d62940bf 12836 -- Remove the mode of the Protected_Entry_Call call, then remove
12837 -- the Communication_Block of the Protected_Entry_Call call, and
12838 -- finally add Duration and a Delay_Mode parameter
ee6ba406 12839
d62940bf 12840 pragma Assert (Present (Param));
83c6c069 12841 Rewrite (Param, New_Occurrence_Of (D, Loc));
ee6ba406 12842
83c6c069 12843 Rewrite (Dummy, New_Occurrence_Of (M, Loc));
ee6ba406 12844
d62940bf 12845 -- Add a Boolean flag for successful entry call
ee6ba406 12846
83c6c069 12847 Append_To (Params, New_Occurrence_Of (B, Loc));
d62940bf 12848
70966f50 12849 case Corresponding_Runtime_Package (Etype (Concval)) is
12850 when System_Tasking_Protected_Objects_Entries =>
12851 Rewrite (Call,
12852 Make_Procedure_Call_Statement (Loc,
12853 Name =>
83c6c069 12854 New_Occurrence_Of
70966f50 12855 (RTE (RE_Timed_Protected_Entry_Call), Loc),
12856 Parameter_Associations => Params));
12857
70966f50 12858 when others =>
12859 raise Program_Error;
12860 end case;
d62940bf 12861
12862 -- For the task case, build a Timed_Task_Entry_Call
12863
12864 else
12865 -- Create a new call statement
12866
83c6c069 12867 Append_To (Params, New_Occurrence_Of (D, Loc));
12868 Append_To (Params, New_Occurrence_Of (M, Loc));
12869 Append_To (Params, New_Occurrence_Of (B, Loc));
d62940bf 12870
12871 Rewrite (Call,
12872 Make_Procedure_Call_Statement (Loc,
12873 Name =>
83c6c069 12874 New_Occurrence_Of (RTE (RE_Timed_Task_Entry_Call), Loc),
d62940bf 12875 Parameter_Associations => Params));
12876 end if;
12877
12878 Append_To (Stmts,
12879 Make_Implicit_If_Statement (N,
83c6c069 12880 Condition => New_Occurrence_Of (B, Loc),
d62940bf 12881 Then_Statements => E_Stats,
12882 Else_Statements => D_Stats));
12883 end if;
ee6ba406 12884
12885 Rewrite (N,
12886 Make_Block_Statement (Loc,
4d6daf23 12887 Declarations => Decls,
ee6ba406 12888 Handled_Statement_Sequence =>
12889 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
12890
12891 Analyze (N);
ee6ba406 12892 end Expand_N_Timed_Entry_Call;
12893
12894 ----------------------------------------
12895 -- Expand_Protected_Body_Declarations --
12896 ----------------------------------------
12897
ee6ba406 12898 procedure Expand_Protected_Body_Declarations
9dfe12ae 12899 (N : Node_Id;
ee6ba406 12900 Spec_Id : Entity_Id)
12901 is
ee6ba406 12902 begin
9dfe12ae 12903 if No_Run_Time_Mode then
12904 Error_Msg_CRT ("protected body", N);
12905 return;
12906
a33565dd 12907 elsif Expander_Active then
680a0a68 12908
57993a53 12909 -- Associate discriminals with the first subprogram or entry body to
12910 -- be expanded.
ee6ba406 12911
57993a53 12912 if Present (First_Protected_Operation (Declarations (N))) then
f15731c4 12913 Set_Discriminals (Parent (Spec_Id));
ee6ba406 12914 end if;
12915 end if;
12916 end Expand_Protected_Body_Declarations;
12917
12918 -------------------------
12919 -- External_Subprogram --
12920 -------------------------
12921
12922 function External_Subprogram (E : Entity_Id) return Entity_Id is
12923 Subp : constant Entity_Id := Protected_Body_Subprogram (E);
ee6ba406 12924
12925 begin
4961db87 12926 -- The internal and external subprograms follow each other on the entity
12927 -- chain. Note that previously private operations had no separate
12928 -- external subprogram. We now create one in all cases, because a
12929 -- private operation may actually appear in an external call, through
12930 -- a 'Access reference used for a callback.
12931
12932 -- If the operation is a function that returns an anonymous access type,
12933 -- the corresponding itype appears before the operation, and must be
12934 -- skipped.
12935
12936 -- This mechanism is fragile, there should be a real link between the
12937 -- two versions of the operation, but there is no place to put it ???
cb5f80c1 12938
4961db87 12939 if Is_Access_Type (Next_Entity (Subp)) then
12940 return Next_Entity (Next_Entity (Subp));
12941 else
12942 return Next_Entity (Subp);
12943 end if;
ee6ba406 12944 end External_Subprogram;
12945
d62940bf 12946 ------------------------------
12947 -- Extract_Dispatching_Call --
12948 ------------------------------
12949
12950 procedure Extract_Dispatching_Call
12951 (N : Node_Id;
12952 Call_Ent : out Entity_Id;
12953 Object : out Entity_Id;
12954 Actuals : out List_Id;
12955 Formals : out List_Id)
12956 is
12957 Call_Nam : Node_Id;
12958
12959 begin
12960 pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
12961
12962 if Present (Original_Node (N)) then
12963 Call_Nam := Name (Original_Node (N));
12964 else
12965 Call_Nam := Name (N);
12966 end if;
12967
12968 -- Retrieve the name of the dispatching procedure. It contains the
12969 -- dispatch table slot number.
12970
12971 loop
12972 case Nkind (Call_Nam) is
12973 when N_Identifier =>
12974 exit;
12975
12976 when N_Selected_Component =>
12977 Call_Nam := Selector_Name (Call_Nam);
12978
12979 when others =>
12980 raise Program_Error;
12981
12982 end case;
12983 end loop;
12984
12985 Actuals := Parameter_Associations (N);
12986 Call_Ent := Entity (Call_Nam);
12987 Formals := Parameter_Specifications (Parent (Call_Ent));
12988 Object := First (Actuals);
12989
12990 if Present (Original_Node (Object)) then
12991 Object := Original_Node (Object);
12992 end if;
9b94c9e7 12993
12994 -- If the type of the dispatching object is an access type then return
4ecb1318 12995 -- an explicit dereference.
9b94c9e7 12996
12997 if Is_Access_Type (Etype (Object)) then
12998 Object := Make_Explicit_Dereference (Sloc (N), Object);
12999 Analyze (Object);
13000 end if;
d62940bf 13001 end Extract_Dispatching_Call;
13002
ee6ba406 13003 -------------------
13004 -- Extract_Entry --
13005 -------------------
13006
13007 procedure Extract_Entry
13008 (N : Node_Id;
13009 Concval : out Node_Id;
13010 Ename : out Node_Id;
13011 Index : out Node_Id)
13012 is
13013 Nam : constant Node_Id := Name (N);
13014
13015 begin
13016 -- For a simple entry, the name is a selected component, with the
13017 -- prefix being the task value, and the selector being the entry.
13018
13019 if Nkind (Nam) = N_Selected_Component then
13020 Concval := Prefix (Nam);
13021 Ename := Selector_Name (Nam);
13022 Index := Empty;
13023
d62940bf 13024 -- For a member of an entry family, the name is an indexed component
13025 -- where the prefix is a selected component, whose prefix in turn is
13026 -- the task value, and whose selector is the entry family. The single
13027 -- expression in the expressions list of the indexed component is the
13028 -- subscript for the family.
ee6ba406 13029
d62940bf 13030 else pragma Assert (Nkind (Nam) = N_Indexed_Component);
ee6ba406 13031 Concval := Prefix (Prefix (Nam));
13032 Ename := Selector_Name (Prefix (Nam));
13033 Index := First (Expressions (Nam));
13034 end if;
ad0254f2 13035
13036 -- Through indirection, the type may actually be a limited view of a
13037 -- concurrent type. When compiling a call, the non-limited view of the
13038 -- type is visible.
13039
13040 if From_Limited_With (Etype (Concval)) then
13041 Set_Etype (Concval, Non_Limited_View (Etype (Concval)));
13042 end if;
ee6ba406 13043 end Extract_Entry;
13044
13045 -------------------
13046 -- Family_Offset --
13047 -------------------
13048
13049 function Family_Offset
13050 (Loc : Source_Ptr;
13051 Hi : Node_Id;
13052 Lo : Node_Id;
cb5f80c1 13053 Ttyp : Entity_Id;
13054 Cap : Boolean) return Node_Id
ee6ba406 13055 is
cb5f80c1 13056 Ityp : Entity_Id;
13057 Real_Hi : Node_Id;
13058 Real_Lo : Node_Id;
13059
ee6ba406 13060 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
76a1c25b 13061 -- If one of the bounds is a reference to a discriminant, replace with
13062 -- corresponding discriminal of type. Within the body of a task retrieve
13063 -- the renamed discriminant by simple visibility, using its generated
cb5f80c1 13064 -- name. Within a protected object, find the original discriminant and
13065 -- replace it with the discriminal of the current protected operation.
ee6ba406 13066
13067 ------------------------------
13068 -- Convert_Discriminant_Ref --
13069 ------------------------------
13070
13071 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
13072 Loc : constant Source_Ptr := Sloc (Bound);
13073 B : Node_Id;
13074 D : Entity_Id;
13075
13076 begin
13077 if Is_Entity_Name (Bound)
13078 and then Ekind (Entity (Bound)) = E_Discriminant
13079 then
c0688d2b 13080 if Is_Task_Type (Ttyp) and then Has_Completion (Ttyp) then
ee6ba406 13081 B := Make_Identifier (Loc, Chars (Entity (Bound)));
13082 Find_Direct_Name (B);
13083
13084 elsif Is_Protected_Type (Ttyp) then
13085 D := First_Discriminant (Ttyp);
ee6ba406 13086 while Chars (D) /= Chars (Entity (Bound)) loop
13087 Next_Discriminant (D);
13088 end loop;
13089
83c6c069 13090 B := New_Occurrence_Of (Discriminal (D), Loc);
ee6ba406 13091
13092 else
83c6c069 13093 B := New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
ee6ba406 13094 end if;
13095
13096 elsif Nkind (Bound) = N_Attribute_Reference then
13097 return Bound;
13098
13099 else
13100 B := New_Copy_Tree (Bound);
13101 end if;
13102
13103 return
13104 Make_Attribute_Reference (Loc,
13105 Attribute_Name => Name_Pos,
13106 Prefix => New_Occurrence_Of (Etype (Bound), Loc),
13107 Expressions => New_List (B));
13108 end Convert_Discriminant_Ref;
13109
13110 -- Start of processing for Family_Offset
13111
13112 begin
cb5f80c1 13113 Real_Hi := Convert_Discriminant_Ref (Hi);
13114 Real_Lo := Convert_Discriminant_Ref (Lo);
13115
13116 if Cap then
13117 if Is_Task_Type (Ttyp) then
13118 Ityp := RTE (RE_Task_Entry_Index);
13119 else
13120 Ityp := RTE (RE_Protected_Entry_Index);
13121 end if;
13122
13123 Real_Hi :=
13124 Make_Attribute_Reference (Loc,
83c6c069 13125 Prefix => New_Occurrence_Of (Ityp, Loc),
cb5f80c1 13126 Attribute_Name => Name_Min,
13127 Expressions => New_List (
13128 Real_Hi,
13129 Make_Integer_Literal (Loc, Entry_Family_Bound - 1)));
13130
13131 Real_Lo :=
13132 Make_Attribute_Reference (Loc,
83c6c069 13133 Prefix => New_Occurrence_Of (Ityp, Loc),
cb5f80c1 13134 Attribute_Name => Name_Max,
13135 Expressions => New_List (
13136 Real_Lo,
13137 Make_Integer_Literal (Loc, -Entry_Family_Bound)));
13138 end if;
13139
13140 return Make_Op_Subtract (Loc, Real_Hi, Real_Lo);
ee6ba406 13141 end Family_Offset;
13142
13143 -----------------
13144 -- Family_Size --
13145 -----------------
13146
13147 function Family_Size
13148 (Loc : Source_Ptr;
13149 Hi : Node_Id;
13150 Lo : Node_Id;
cb5f80c1 13151 Ttyp : Entity_Id;
13152 Cap : Boolean) return Node_Id
ee6ba406 13153 is
13154 Ityp : Entity_Id;
13155
13156 begin
13157 if Is_Task_Type (Ttyp) then
13158 Ityp := RTE (RE_Task_Entry_Index);
13159 else
13160 Ityp := RTE (RE_Protected_Entry_Index);
13161 end if;
13162
13163 return
13164 Make_Attribute_Reference (Loc,
83c6c069 13165 Prefix => New_Occurrence_Of (Ityp, Loc),
ee6ba406 13166 Attribute_Name => Name_Max,
13167 Expressions => New_List (
13168 Make_Op_Add (Loc,
c0688d2b 13169 Left_Opnd => Family_Offset (Loc, Hi, Lo, Ttyp, Cap),
13170 Right_Opnd => Make_Integer_Literal (Loc, 1)),
ee6ba406 13171 Make_Integer_Literal (Loc, 0)));
13172 end Family_Size;
13173
43602818 13174 ----------------------------
13175 -- Find_Enclosing_Context --
13176 ----------------------------
13177
13178 procedure Find_Enclosing_Context
13179 (N : Node_Id;
13180 Context : out Node_Id;
13181 Context_Id : out Entity_Id;
13182 Context_Decls : out List_Id)
13183 is
13184 begin
13185 -- Traverse the parent chain looking for an enclosing body, block,
13186 -- package or return statement.
13187
13188 Context := Parent (N);
13189 while not Nkind_In (Context, N_Block_Statement,
13190 N_Entry_Body,
13191 N_Extended_Return_Statement,
13192 N_Package_Body,
13193 N_Package_Declaration,
13194 N_Subprogram_Body,
13195 N_Task_Body)
13196 loop
13197 Context := Parent (Context);
13198 end loop;
13199
13200 -- Extract the constituents of the context
13201
13202 if Nkind (Context) = N_Extended_Return_Statement then
13203 Context_Decls := Return_Object_Declarations (Context);
13204 Context_Id := Return_Statement_Entity (Context);
13205
13206 -- Package declarations and bodies use a common library-level activation
13207 -- chain or task master, therefore return the package declaration as the
13208 -- proper carrier for the appropriate flag.
13209
13210 elsif Nkind (Context) = N_Package_Body then
13211 Context_Decls := Declarations (Context);
13212 Context_Id := Corresponding_Spec (Context);
13213 Context := Parent (Context_Id);
13214
13215 if Nkind (Context) = N_Defining_Program_Unit_Name then
13216 Context := Parent (Parent (Context));
13217 else
13218 Context := Parent (Context);
13219 end if;
13220
13221 elsif Nkind (Context) = N_Package_Declaration then
13222 Context_Decls := Visible_Declarations (Specification (Context));
13223 Context_Id := Defining_Unit_Name (Specification (Context));
13224
13225 if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13226 Context_Id := Defining_Identifier (Context_Id);
13227 end if;
13228
13229 else
13230 Context_Decls := Declarations (Context);
13231
13232 if Nkind (Context) = N_Block_Statement then
13233 Context_Id := Entity (Identifier (Context));
13234
13235 elsif Nkind (Context) = N_Entry_Body then
13236 Context_Id := Defining_Identifier (Context);
13237
13238 elsif Nkind (Context) = N_Subprogram_Body then
13239 if Present (Corresponding_Spec (Context)) then
13240 Context_Id := Corresponding_Spec (Context);
13241 else
13242 Context_Id := Defining_Unit_Name (Specification (Context));
13243
13244 if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13245 Context_Id := Defining_Identifier (Context_Id);
13246 end if;
13247 end if;
13248
13249 elsif Nkind (Context) = N_Task_Body then
13250 Context_Id := Corresponding_Spec (Context);
13251
13252 else
13253 raise Program_Error;
13254 end if;
13255 end if;
13256
13257 pragma Assert (Present (Context));
13258 pragma Assert (Present (Context_Id));
13259 pragma Assert (Present (Context_Decls));
13260 end Find_Enclosing_Context;
13261
eb704cc6 13262 -----------------------
13263 -- Find_Master_Scope --
13264 -----------------------
13265
13266 function Find_Master_Scope (E : Entity_Id) return Entity_Id is
13267 S : Entity_Id;
13268
13269 begin
b2df433c 13270 -- In Ada 2005, the master is the innermost enclosing scope that is not
eb704cc6 13271 -- transient. If the enclosing block is the rewriting of a call or the
13272 -- scope is an extended return statement this is valid master. The
13273 -- master in an extended return is only used within the return, and is
13274 -- subsequently overwritten in Move_Activation_Chain, but it must exist
13275 -- now before that overwriting occurs.
13276
13277 S := Scope (E);
13278
de54c5ab 13279 if Ada_Version >= Ada_2005 then
eb704cc6 13280 while Is_Internal (S) loop
13281 if Nkind (Parent (S)) = N_Block_Statement
13282 and then
13283 Nkind (Original_Node (Parent (S))) = N_Procedure_Call_Statement
13284 then
13285 exit;
13286
13287 elsif Ekind (S) = E_Return_Statement then
13288 exit;
13289
13290 else
13291 S := Scope (S);
13292 end if;
13293 end loop;
13294 end if;
13295
13296 return S;
13297 end Find_Master_Scope;
13298
ee6ba406 13299 -------------------------------
13300 -- First_Protected_Operation --
13301 -------------------------------
13302
13303 function First_Protected_Operation (D : List_Id) return Node_Id is
13304 First_Op : Node_Id;
13305
13306 begin
13307 First_Op := First (D);
13308 while Present (First_Op)
5809835d 13309 and then not Nkind_In (First_Op, N_Subprogram_Body, N_Entry_Body)
ee6ba406 13310 loop
13311 Next (First_Op);
13312 end loop;
13313
13314 return First_Op;
13315 end First_Protected_Operation;
13316
57993a53 13317 ---------------------------------------
13318 -- Install_Private_Data_Declarations --
13319 ---------------------------------------
ee6ba406 13320
57993a53 13321 procedure Install_Private_Data_Declarations
13322 (Loc : Source_Ptr;
13323 Spec_Id : Entity_Id;
13324 Conc_Typ : Entity_Id;
13325 Body_Nod : Node_Id;
13326 Decls : List_Id;
13327 Barrier : Boolean := False;
13328 Family : Boolean := False)
ee6ba406 13329 is
57993a53 13330 Is_Protected : constant Boolean := Is_Protected_Type (Conc_Typ);
13331 Decl : Node_Id;
13332 Def : Node_Id;
13333 Insert_Node : Node_Id := Empty;
13334 Obj_Ent : Entity_Id;
13335
13336 procedure Add (Decl : Node_Id);
13337 -- Add a single declaration after Insert_Node. If this is the first
13338 -- addition, Decl is added to the front of Decls and it becomes the
13339 -- insertion node.
13340
13341 function Replace_Bound (Bound : Node_Id) return Node_Id;
13342 -- The bounds of an entry index may depend on discriminants, create a
13343 -- reference to the corresponding prival. Otherwise return a duplicate
13344 -- of the original bound.
13345
13346 ---------
13347 -- Add --
13348 ---------
13349
13350 procedure Add (Decl : Node_Id) is
13351 begin
13352 if No (Insert_Node) then
13353 Prepend_To (Decls, Decl);
13354 else
13355 Insert_After (Insert_Node, Decl);
13356 end if;
ee6ba406 13357
57993a53 13358 Insert_Node := Decl;
13359 end Add;
ee6ba406 13360
13361 --------------------------
13362 -- Replace_Discriminant --
13363 --------------------------
13364
57993a53 13365 function Replace_Bound (Bound : Node_Id) return Node_Id is
ee6ba406 13366 begin
13367 if Nkind (Bound) = N_Identifier
57993a53 13368 and then Is_Discriminal (Entity (Bound))
ee6ba406 13369 then
13370 return Make_Identifier (Loc, Chars (Entity (Bound)));
13371 else
13372 return Duplicate_Subexpr (Bound);
13373 end if;
57993a53 13374 end Replace_Bound;
ee6ba406 13375
57993a53 13376 -- Start of processing for Install_Private_Data_Declarations
ee6ba406 13377
13378 begin
57993a53 13379 -- Step 1: Retrieve the concurrent object entity. Obj_Ent can denote
13380 -- formal parameter _O, _object or _task depending on the context.
ee6ba406 13381
57993a53 13382 Obj_Ent := Concurrent_Object (Spec_Id, Conc_Typ);
13383
13384 -- Special processing of _O for barrier functions, protected entries
13385 -- and families.
13386
13387 if Barrier
13388 or else
13389 (Is_Protected
13390 and then
13391 (Ekind (Spec_Id) = E_Entry
13392 or else Ekind (Spec_Id) = E_Entry_Family))
ee6ba406 13393 then
57993a53 13394 declare
13395 Conc_Rec : constant Entity_Id :=
13396 Corresponding_Record_Type (Conc_Typ);
13397 Typ_Id : constant Entity_Id :=
13398 Make_Defining_Identifier (Loc,
13399 New_External_Name (Chars (Conc_Rec), 'P'));
13400 begin
13401 -- Generate:
13402 -- type prot_typVP is access prot_typV;
ee6ba406 13403
57993a53 13404 Decl :=
13405 Make_Full_Type_Declaration (Loc,
13406 Defining_Identifier => Typ_Id,
13407 Type_Definition =>
13408 Make_Access_To_Object_Definition (Loc,
13409 Subtype_Indication =>
83c6c069 13410 New_Occurrence_Of (Conc_Rec, Loc)));
57993a53 13411 Add (Decl);
ee6ba406 13412
57993a53 13413 -- Generate:
13414 -- _object : prot_typVP := prot_typV (_O);
ee6ba406 13415
57993a53 13416 Decl :=
13417 Make_Object_Declaration (Loc,
13418 Defining_Identifier =>
13419 Make_Defining_Identifier (Loc, Name_uObject),
83c6c069 13420 Object_Definition => New_Occurrence_Of (Typ_Id, Loc),
57993a53 13421 Expression =>
13422 Unchecked_Convert_To (Typ_Id,
83c6c069 13423 New_Occurrence_Of (Obj_Ent, Loc)));
57993a53 13424 Add (Decl);
ee6ba406 13425
57993a53 13426 -- Set the reference to the concurrent object
ee6ba406 13427
57993a53 13428 Obj_Ent := Defining_Identifier (Decl);
13429 end;
ee6ba406 13430 end if;
13431
57993a53 13432 -- Step 2: Create the Protection object and build its declaration for
7413d80d 13433 -- any protected entry (family) of subprogram. Note for the lock-free
13434 -- implementation, the Protection object is not needed anymore.
ee6ba406 13435
a16536f8 13436 if Is_Protected and then not Uses_Lock_Free (Conc_Typ) then
57993a53 13437 declare
ec97ce79 13438 Prot_Ent : constant Entity_Id := Make_Temporary (Loc, 'R');
57993a53 13439 Prot_Typ : RE_Id;
ee6ba406 13440
57993a53 13441 begin
13442 Set_Protection_Object (Spec_Id, Prot_Ent);
ee6ba406 13443
57993a53 13444 -- Determine the proper protection type
ee6ba406 13445
57993a53 13446 if Has_Attach_Handler (Conc_Typ)
13447 and then not Restricted_Profile
13448 then
13449 Prot_Typ := RE_Static_Interrupt_Protection;
ee6ba406 13450
134520e8 13451 elsif Has_Interrupt_Handler (Conc_Typ)
13452 and then not Restriction_Active (No_Dynamic_Attachment)
13453 then
57993a53 13454 Prot_Typ := RE_Dynamic_Interrupt_Protection;
13455
588e7f97 13456 else
57993a53 13457 case Corresponding_Runtime_Package (Conc_Typ) is
13458 when System_Tasking_Protected_Objects_Entries =>
13459 Prot_Typ := RE_Protection_Entries;
13460
13461 when System_Tasking_Protected_Objects_Single_Entry =>
13462 Prot_Typ := RE_Protection_Entry;
13463
588e7f97 13464 when System_Tasking_Protected_Objects =>
13465 Prot_Typ := RE_Protection;
13466
57993a53 13467 when others =>
13468 raise Program_Error;
13469 end case;
57993a53 13470 end if;
13471
13472 -- Generate:
13473 -- conc_typR : protection_typ renames _object._object;
13474
13475 Decl :=
13476 Make_Object_Renaming_Declaration (Loc,
13477 Defining_Identifier => Prot_Ent,
13478 Subtype_Mark =>
83c6c069 13479 New_Occurrence_Of (RTE (Prot_Typ), Loc),
57993a53 13480 Name =>
13481 Make_Selected_Component (Loc,
83c6c069 13482 Prefix => New_Occurrence_Of (Obj_Ent, Loc),
55868293 13483 Selector_Name => Make_Identifier (Loc, Name_uObject)));
57993a53 13484 Add (Decl);
13485 end;
13486 end if;
13487
13488 -- Step 3: Add discriminant renamings (if any)
13489
13490 if Has_Discriminants (Conc_Typ) then
13491 declare
13492 D : Entity_Id;
13493
13494 begin
13495 D := First_Discriminant (Conc_Typ);
13496 while Present (D) loop
13497
13498 -- Adjust the source location
13499
13500 Set_Sloc (Discriminal (D), Loc);
13501
13502 -- Generate:
13503 -- discr_name : discr_typ renames _object.discr_name;
13504 -- or
13505 -- discr_name : discr_typ renames _task.discr_name;
13506
13507 Decl :=
13508 Make_Object_Renaming_Declaration (Loc,
13509 Defining_Identifier => Discriminal (D),
83c6c069 13510 Subtype_Mark => New_Occurrence_Of (Etype (D), Loc),
57993a53 13511 Name =>
13512 Make_Selected_Component (Loc,
83c6c069 13513 Prefix => New_Occurrence_Of (Obj_Ent, Loc),
57993a53 13514 Selector_Name => Make_Identifier (Loc, Chars (D))));
13515 Add (Decl);
13516
13517 Next_Discriminant (D);
13518 end loop;
13519 end;
13520 end if;
13521
13522 -- Step 4: Add private component renamings (if any)
13523
13524 if Is_Protected then
13525 Def := Protected_Definition (Parent (Conc_Typ));
13526
13527 if Present (Private_Declarations (Def)) then
13528 declare
13529 Comp : Node_Id;
13530 Comp_Id : Entity_Id;
13531 Decl_Id : Entity_Id;
13532
13533 begin
13534 Comp := First (Private_Declarations (Def));
13535 while Present (Comp) loop
13536 if Nkind (Comp) = N_Component_Declaration then
13537 Comp_Id := Defining_Identifier (Comp);
13538 Decl_Id :=
13539 Make_Defining_Identifier (Loc, Chars (Comp_Id));
13540
13541 -- Minimal decoration
13542
13543 if Ekind (Spec_Id) = E_Function then
13544 Set_Ekind (Decl_Id, E_Constant);
13545 else
13546 Set_Ekind (Decl_Id, E_Variable);
13547 end if;
13548
13549 Set_Prival (Comp_Id, Decl_Id);
13550 Set_Prival_Link (Decl_Id, Comp_Id);
13551 Set_Is_Aliased (Decl_Id, Is_Aliased (Comp_Id));
13552
13553 -- Generate:
13554 -- comp_name : comp_typ renames _object.comp_name;
13555
13556 Decl :=
13557 Make_Object_Renaming_Declaration (Loc,
13558 Defining_Identifier => Decl_Id,
13559 Subtype_Mark =>
83c6c069 13560 New_Occurrence_Of (Etype (Comp_Id), Loc),
57993a53 13561 Name =>
13562 Make_Selected_Component (Loc,
13563 Prefix =>
83c6c069 13564 New_Occurrence_Of (Obj_Ent, Loc),
57993a53 13565 Selector_Name =>
13566 Make_Identifier (Loc, Chars (Comp_Id))));
13567 Add (Decl);
13568 end if;
13569
13570 Next (Comp);
13571 end loop;
13572 end;
13573 end if;
13574 end if;
13575
13576 -- Step 5: Add the declaration of the entry index and the associated
13577 -- type for barrier functions and entry families.
13578
c0688d2b 13579 if (Barrier and Family) or else Ekind (Spec_Id) = E_Entry_Family then
57993a53 13580 declare
13581 E : constant Entity_Id := Index_Object (Spec_Id);
13582 Index : constant Entity_Id :=
c0688d2b 13583 Defining_Identifier
13584 (Entry_Index_Specification
13585 (Entry_Body_Formal_Part (Body_Nod)));
57993a53 13586 Index_Con : constant Entity_Id :=
13587 Make_Defining_Identifier (Loc, Chars (Index));
13588 High : Node_Id;
13589 Index_Typ : Entity_Id;
13590 Low : Node_Id;
13591
13592 begin
13593 -- Minimal decoration
13594
13595 Set_Ekind (Index_Con, E_Constant);
13596 Set_Entry_Index_Constant (Index, Index_Con);
13597 Set_Discriminal_Link (Index_Con, Index);
13598
13599 -- Retrieve the bounds of the entry family
13600
13601 High := Type_High_Bound (Etype (Index));
13602 Low := Type_Low_Bound (Etype (Index));
13603
13604 -- In the simple case the entry family is given by a subtype
13605 -- mark and the index constant has the same type.
13606
13607 if Is_Entity_Name (Original_Node (
13608 Discrete_Subtype_Definition (Parent (Index))))
13609 then
13610 Index_Typ := Etype (Index);
13611
13612 -- Otherwise a new subtype declaration is required
13613
13614 else
13615 High := Replace_Bound (High);
13616 Low := Replace_Bound (Low);
13617
ec97ce79 13618 Index_Typ := Make_Temporary (Loc, 'J');
57993a53 13619
13620 -- Generate:
13621 -- subtype Jnn is <Etype of Index> range Low .. High;
13622
13623 Decl :=
13624 Make_Subtype_Declaration (Loc,
13625 Defining_Identifier => Index_Typ,
13626 Subtype_Indication =>
13627 Make_Subtype_Indication (Loc,
13628 Subtype_Mark =>
83c6c069 13629 New_Occurrence_Of (Base_Type (Etype (Index)), Loc),
57993a53 13630 Constraint =>
13631 Make_Range_Constraint (Loc,
13632 Range_Expression =>
13633 Make_Range (Loc, Low, High))));
13634 Add (Decl);
13635 end if;
13636
13637 Set_Etype (Index_Con, Index_Typ);
13638
13639 -- Create the object which designates the index:
13640 -- J : constant Jnn :=
13641 -- Jnn'Val (_E - <index expr> + Jnn'Pos (Jnn'First));
13642 --
13643 -- where Jnn is the subtype created above or the original type of
13644 -- the index, _E is a formal of the protected body subprogram and
13645 -- <index expr> is the index of the first family member.
13646
13647 Decl :=
13648 Make_Object_Declaration (Loc,
13649 Defining_Identifier => Index_Con,
13650 Constant_Present => True,
13651 Object_Definition =>
83c6c069 13652 New_Occurrence_Of (Index_Typ, Loc),
57993a53 13653
13654 Expression =>
13655 Make_Attribute_Reference (Loc,
13656 Prefix =>
83c6c069 13657 New_Occurrence_Of (Index_Typ, Loc),
57993a53 13658 Attribute_Name => Name_Val,
13659
13660 Expressions => New_List (
13661
13662 Make_Op_Add (Loc,
13663 Left_Opnd =>
13664 Make_Op_Subtract (Loc,
c0688d2b 13665 Left_Opnd => New_Occurrence_Of (E, Loc),
57993a53 13666 Right_Opnd =>
13667 Entry_Index_Expression (Loc,
13668 Defining_Identifier (Body_Nod),
13669 Empty, Conc_Typ)),
13670
13671 Right_Opnd =>
13672 Make_Attribute_Reference (Loc,
c0688d2b 13673 Prefix =>
83c6c069 13674 New_Occurrence_Of (Index_Typ, Loc),
57993a53 13675 Attribute_Name => Name_Pos,
c0688d2b 13676 Expressions => New_List (
57993a53 13677 Make_Attribute_Reference (Loc,
c0688d2b 13678 Prefix =>
83c6c069 13679 New_Occurrence_Of (Index_Typ, Loc),
57993a53 13680 Attribute_Name => Name_First)))))));
13681 Add (Decl);
13682 end;
13683 end if;
13684 end Install_Private_Data_Declarations;
13685
7a19298b 13686 -----------------------
13687 -- Is_Exception_Safe --
13688 -----------------------
13689
13690 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
13691
13692 function Has_Side_Effect (N : Node_Id) return Boolean;
13693 -- Return True whenever encountering a subprogram call or raise
13694 -- statement of any kind in the sequence of statements
13695
13696 ---------------------
13697 -- Has_Side_Effect --
13698 ---------------------
13699
13700 -- What is this doing buried two levels down in exp_ch9. It seems like a
13701 -- generally useful function, and indeed there may be code duplication
13702 -- going on here ???
13703
13704 function Has_Side_Effect (N : Node_Id) return Boolean is
13705 Stmt : Node_Id;
13706 Expr : Node_Id;
13707
13708 function Is_Call_Or_Raise (N : Node_Id) return Boolean;
13709 -- Indicate whether N is a subprogram call or a raise statement
13710
13711 ----------------------
13712 -- Is_Call_Or_Raise --
13713 ----------------------
13714
13715 function Is_Call_Or_Raise (N : Node_Id) return Boolean is
13716 begin
13717 return Nkind_In (N, N_Procedure_Call_Statement,
13718 N_Function_Call,
13719 N_Raise_Statement,
13720 N_Raise_Constraint_Error,
13721 N_Raise_Program_Error,
13722 N_Raise_Storage_Error);
13723 end Is_Call_Or_Raise;
13724
13725 -- Start of processing for Has_Side_Effect
13726
13727 begin
13728 Stmt := N;
13729 while Present (Stmt) loop
13730 if Is_Call_Or_Raise (Stmt) then
13731 return True;
13732 end if;
13733
13734 -- An object declaration can also contain a function call or a
13735 -- raise statement.
13736
13737 if Nkind (Stmt) = N_Object_Declaration then
13738 Expr := Expression (Stmt);
13739
13740 if Present (Expr) and then Is_Call_Or_Raise (Expr) then
13741 return True;
13742 end if;
13743 end if;
13744
13745 Next (Stmt);
13746 end loop;
13747
13748 return False;
13749 end Has_Side_Effect;
13750
13751 -- Start of processing for Is_Exception_Safe
13752
13753 begin
b69074f3 13754 -- When exceptions can't be propagated, the subprogram returns normally
8325ff3b 13755
13756 if No_Exception_Handlers_Set then
13757 return True;
13758 end if;
13759
7a19298b 13760 -- If the checks handled by the back end are not disabled, we cannot
13761 -- ensure that no exception will be raised.
13762
13763 if not Access_Checks_Suppressed (Empty)
13764 or else not Discriminant_Checks_Suppressed (Empty)
13765 or else not Range_Checks_Suppressed (Empty)
13766 or else not Index_Checks_Suppressed (Empty)
13767 or else Opt.Stack_Checking_Enabled
13768 then
13769 return False;
13770 end if;
13771
13772 if Has_Side_Effect (First (Declarations (Subprogram)))
13773 or else
13774 Has_Side_Effect
13775 (First (Statements (Handled_Statement_Sequence (Subprogram))))
13776 then
13777 return False;
13778 else
13779 return True;
13780 end if;
13781 end Is_Exception_Safe;
13782
57993a53 13783 ---------------------------------
13784 -- Is_Potentially_Large_Family --
13785 ---------------------------------
13786
13787 function Is_Potentially_Large_Family
13788 (Base_Index : Entity_Id;
13789 Conctyp : Entity_Id;
13790 Lo : Node_Id;
13791 Hi : Node_Id) return Boolean
13792 is
13793 begin
13794 return Scope (Base_Index) = Standard_Standard
13795 and then Base_Index = Base_Type (Standard_Integer)
13796 and then Has_Discriminants (Conctyp)
7a19298b 13797 and then
13798 Present (Discriminant_Default_Value (First_Discriminant (Conctyp)))
57993a53 13799 and then
13800 (Denotes_Discriminant (Lo, True)
7a19298b 13801 or else
13802 Denotes_Discriminant (Hi, True));
57993a53 13803 end Is_Potentially_Large_Family;
13804
d2a42b76 13805 -------------------------------------
13806 -- Is_Private_Primitive_Subprogram --
13807 -------------------------------------
13808
13809 function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean is
13810 begin
13811 return
13812 (Ekind (Id) = E_Function or else Ekind (Id) = E_Procedure)
3ade4496 13813 and then Is_Private_Primitive (Id);
d2a42b76 13814 end Is_Private_Primitive_Subprogram;
13815
57993a53 13816 ------------------
13817 -- Index_Object --
13818 ------------------
13819
13820 function Index_Object (Spec_Id : Entity_Id) return Entity_Id is
13821 Bod_Subp : constant Entity_Id := Protected_Body_Subprogram (Spec_Id);
13822 Formal : Entity_Id;
13823
13824 begin
13825 Formal := First_Formal (Bod_Subp);
13826 while Present (Formal) loop
13827
13828 -- Look for formal parameter _E
13829
13830 if Chars (Formal) = Name_uE then
13831 return Formal;
13832 end if;
13833
13834 Next_Formal (Formal);
13835 end loop;
13836
13837 -- A protected body subprogram should always have the parameter in
13838 -- question.
13839
13840 raise Program_Error;
13841 end Index_Object;
ee6ba406 13842
13843 --------------------------------
13844 -- Make_Initialize_Protection --
13845 --------------------------------
13846
13847 function Make_Initialize_Protection
bdd64cbe 13848 (Protect_Rec : Entity_Id) return List_Id
ee6ba406 13849 is
9dfe12ae 13850 Loc : constant Source_Ptr := Sloc (Protect_Rec);
13851 P_Arr : Entity_Id;
9dfe12ae 13852 Pdec : Node_Id;
c0688d2b 13853 Ptyp : constant Node_Id :=
9dfe12ae 13854 Corresponding_Concurrent_Type (Protect_Rec);
13855 Args : List_Id;
c0688d2b 13856 L : constant List_Id := New_List;
13857 Has_Entry : constant Boolean := Has_Entries (Ptyp);
f4cf0c72 13858 Prio_Type : Entity_Id;
c0688d2b 13859 Prio_Var : Entity_Id := Empty;
13860 Restricted : constant Boolean := Restricted_Profile;
ee6ba406 13861
13862 begin
76a1c25b 13863 -- We may need two calls to properly initialize the object, one to
13864 -- Initialize_Protection, and possibly one to Install_Handlers if we
13865 -- have a pragma Attach_Handler.
ee6ba406 13866
ee6ba406 13867 -- Get protected declaration. In the case of a task type declaration,
76a1c25b 13868 -- this is simply the parent of the protected type entity. In the single
13869 -- protected object declaration, this parent will be the implicit type,
13870 -- and we can find the corresponding single protected object declaration
13871 -- by searching forward in the declaration list in the tree.
ee6ba406 13872
76a1c25b 13873 -- Is the test for N_Single_Protected_Declaration needed here??? Nodes
13874 -- of this type should have been removed during semantic analysis.
ee6ba406 13875
76a1c25b 13876 Pdec := Parent (Ptyp);
5809835d 13877 while not Nkind_In (Pdec, N_Protected_Type_Declaration,
13878 N_Single_Protected_Declaration)
ee6ba406 13879 loop
13880 Next (Pdec);
13881 end loop;
13882
ee6ba406 13883 -- Build the parameter list for the call. Note that _Init is the name
13884 -- of the formal for the object to be initialized, which is the task
13885 -- value record itself.
13886
13887 Args := New_List;
13888
7413d80d 13889 -- For lock-free implementation, skip initializations of the Protection
13890 -- object.
9f76f439 13891
7413d80d 13892 if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
c0688d2b 13893
7413d80d 13894 -- Object parameter. This is a pointer to the object of type
13895 -- Protection used by the GNARL to control the protected object.
ee6ba406 13896
ee6ba406 13897 Append_To (Args,
7413d80d 13898 Make_Attribute_Reference (Loc,
13899 Prefix =>
13900 Make_Selected_Component (Loc,
13901 Prefix => Make_Identifier (Loc, Name_uInit),
13902 Selector_Name => Make_Identifier (Loc, Name_uObject)),
13903 Attribute_Name => Name_Unchecked_Access));
13904
13905 -- Priority parameter. Set to Unspecified_Priority unless there is a
89b3b365 13906 -- Priority rep item, in which case we take the value from the pragma
13907 -- or attribute definition clause, or there is an Interrupt_Priority
13908 -- rep item and no Priority rep item, and we set the ceiling to
13909 -- Interrupt_Priority'Last, an implementation-defined value, see
caf125ce 13910 -- (RM D.3(10)).
7413d80d 13911
06ef5f86 13912 if Has_Rep_Item (Ptyp, Name_Priority, Check_Parents => False) then
7413d80d 13913 declare
89f1e35c 13914 Prio_Clause : constant Node_Id :=
06ef5f86 13915 Get_Rep_Item
13916 (Ptyp, Name_Priority, Check_Parents => False);
89f1e35c 13917
13918 Prio : Node_Id;
ee6ba406 13919
7413d80d 13920 begin
89f1e35c 13921 -- Pragma Priority
13922
13923 if Nkind (Prio_Clause) = N_Pragma then
13924 Prio :=
13925 Expression
13926 (First (Pragma_Argument_Associations (Prio_Clause)));
13927
f4cf0c72 13928 -- Get_Rep_Item returns either priority pragma.
13929
13930 if Pragma_Name (Prio_Clause) = Name_Priority then
13931 Prio_Type := RTE (RE_Any_Priority);
13932 else
13933 Prio_Type := RTE (RE_Interrupt_Priority);
13934 end if;
13935
89f1e35c 13936 -- Attribute definition clause Priority
13937
13938 else
f4cf0c72 13939 if Chars (Prio_Clause) = Name_Priority then
13940 Prio_Type := RTE (RE_Any_Priority);
13941 else
13942 Prio_Type := RTE (RE_Interrupt_Priority);
13943 end if;
13944
89f1e35c 13945 Prio := Expression (Prio_Clause);
13946 end if;
13947
feea0ab5 13948 -- Always create a locale variable to capture the priority.
13949 -- The priority is also passed to Install_Restriced_Handlers.
13950 -- Note that it is really necessary to create this variable
13951 -- explicitly. It might be thought that removing side effects
13952 -- would the appropriate approach, but that could generate
13953 -- declarations improperly placed in the enclosing scope.
9f76f439 13954
feea0ab5 13955 Prio_Var := Make_Temporary (Loc, 'R', Prio);
13956 Append_To (L,
13957 Make_Object_Declaration (Loc,
13958 Defining_Identifier => Prio_Var,
13959 Object_Definition => New_Occurrence_Of (Prio_Type, Loc),
13960 Expression => Relocate_Node (Prio)));
9f76f439 13961
feea0ab5 13962 Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
7413d80d 13963 end;
fe0961a8 13964
7413d80d 13965 -- When no priority is specified but an xx_Handler pragma is, we
13966 -- default to System.Interrupts.Default_Interrupt_Priority, see
13967 -- D.3(10).
ee6ba406 13968
7413d80d 13969 elsif Has_Attach_Handler (Ptyp)
13970 or else Has_Interrupt_Handler (Ptyp)
13971 then
13972 Append_To (Args,
83c6c069 13973 New_Occurrence_Of (RTE (RE_Default_Interrupt_Priority), Loc));
ee6ba406 13974
7413d80d 13975 -- Normal case, no priority or xx_Handler specified, default priority
ee6ba406 13976
7413d80d 13977 else
13978 Append_To (Args,
83c6c069 13979 New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
7413d80d 13980 end if;
ee6ba406 13981
7413d80d 13982 -- Test for Compiler_Info parameter. This parameter allows entry body
13983 -- procedures and barrier functions to be called from the runtime. It
13984 -- is a pointer to the record generated by the compiler to represent
13985 -- the protected object.
13986
13987 -- A protected type without entries that covers an interface and
13988 -- overrides the abstract routines with protected procedures is
13989 -- considered equivalent to a protected type with entries in the
13990 -- context of dispatching select statements.
13991
588e7f97 13992 -- Protected types with interrupt handlers (when not using a
13993 -- restricted profile) are also considered equivalent to protected
f4623c89 13994 -- types with entries.
13995
13996 -- The types which are used (Static_Interrupt_Protection and
13997 -- Dynamic_Interrupt_Protection) are derived from Protection_Entries.
ee6ba406 13998
588e7f97 13999 declare
14000 Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
f4623c89 14001
588e7f97 14002 Called_Subp : RE_Id;
ee6ba406 14003
588e7f97 14004 begin
14005 case Pkg_Id is
14006 when System_Tasking_Protected_Objects_Entries =>
14007 Called_Subp := RE_Initialize_Protection_Entries;
ee6ba406 14008
588e7f97 14009 -- Argument Compiler_Info
70966f50 14010
7413d80d 14011 Append_To (Args,
14012 Make_Attribute_Reference (Loc,
14013 Prefix => Make_Identifier (Loc, Name_uInit),
14014 Attribute_Name => Name_Address));
70966f50 14015
588e7f97 14016 when System_Tasking_Protected_Objects_Single_Entry =>
14017 Called_Subp := RE_Initialize_Protection_Entry;
70966f50 14018
588e7f97 14019 -- Argument Compiler_Info
70966f50 14020
14021 Append_To (Args,
14022 Make_Attribute_Reference (Loc,
588e7f97 14023 Prefix => Make_Identifier (Loc, Name_uInit),
14024 Attribute_Name => Name_Address));
f89cc618 14025
588e7f97 14026 when System_Tasking_Protected_Objects =>
14027 Called_Subp := RE_Initialize_Protection;
f89cc618 14028
588e7f97 14029 when others =>
14030 raise Program_Error;
14031 end case;
7413d80d 14032
588e7f97 14033 -- Entry_Bodies parameter. This is a pointer to an array of
14034 -- pointers to the entry body procedures and barrier functions of
14035 -- the object. If the protected type has no entries this object
14036 -- will not exist, in this case, pass a null (it can happen when
14037 -- there are protected interrupt handlers or interfaces).
7413d80d 14038
588e7f97 14039 if Has_Entry then
14040 P_Arr := Entry_Bodies_Array (Ptyp);
70966f50 14041
588e7f97 14042 -- Argument Entry_Body (for single entry) or Entry_Bodies (for
14043 -- multiple entries).
14044
14045 Append_To (Args,
14046 Make_Attribute_Reference (Loc,
83c6c069 14047 Prefix => New_Occurrence_Of (P_Arr, Loc),
f4623c89 14048 Attribute_Name => Name_Unrestricted_Access));
588e7f97 14049
14050 if Pkg_Id = System_Tasking_Protected_Objects_Entries then
14051
14052 -- Find index mapping function (clumsy but ok for now)
14053
14054 while Ekind (P_Arr) /= E_Function loop
14055 Next_Entity (P_Arr);
14056 end loop;
70966f50 14057
588e7f97 14058 Append_To (Args,
14059 Make_Attribute_Reference (Loc,
83c6c069 14060 Prefix => New_Occurrence_Of (P_Arr, Loc),
588e7f97 14061 Attribute_Name => Name_Unrestricted_Access));
7413d80d 14062 end if;
9dfe12ae 14063
588e7f97 14064 elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
f4623c89 14065
588e7f97 14066 -- This is the case where we have a protected object with
14067 -- interfaces and no entries, and the single entry restriction
14068 -- is in effect. We pass a null pointer for the entry
14069 -- parameter because there is no actual entry.
14070
14071 Append_To (Args, Make_Null (Loc));
14072
14073 elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
f4623c89 14074
588e7f97 14075 -- This is the case where we have a protected object with no
14076 -- entries and:
14077 -- - either interrupt handlers with non restricted profile,
14078 -- - or interfaces
14079 -- Note that the types which are used for interrupt handlers
14080 -- (Static/Dynamic_Interrupt_Protection) are derived from
14081 -- Protection_Entries. We pass two null pointers because there
14082 -- is no actual entry, and the initialization procedure needs
14083 -- both Entry_Bodies and Find_Body_Index.
14084
14085 Append_To (Args, Make_Null (Loc));
14086 Append_To (Args, Make_Null (Loc));
14087 end if;
14088
ee6ba406 14089 Append_To (L,
14090 Make_Procedure_Call_Statement (Loc,
7ee08bca 14091 Name =>
14092 New_Occurrence_Of (RTE (Called_Subp), Loc),
ee6ba406 14093 Parameter_Associations => Args));
588e7f97 14094 end;
ee6ba406 14095 end if;
14096
14097 if Has_Attach_Handler (Ptyp) then
14098
76a1c25b 14099 -- We have a list of N Attach_Handler (ProcI, ExprI), and we have to
14100 -- make the following call:
14101
ee6ba406 14102 -- Install_Handlers (_object,
14103 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
76a1c25b 14104
9dfe12ae 14105 -- or, in the case of Ravenscar:
76a1c25b 14106
57993a53 14107 -- Install_Restricted_Handlers
feea0ab5 14108 -- (Prio, (Expr1, Proc1'access), ...., (ExprN, ProcN'access));
ee6ba406 14109
14110 declare
9dfe12ae 14111 Args : constant List_Id := New_List;
14112 Table : constant List_Id := New_List;
70966f50 14113 Ritem : Node_Id := First_Rep_Item (Ptyp);
ee6ba406 14114
14115 begin
feea0ab5 14116 -- Build the Priority parameter (only for ravenscar)
14117
14118 if Restricted then
14119
14120 -- Priority comes from a pragma
14121
14122 if Present (Prio_Var) then
14123 Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
14124
14125 -- Priority is the default one
14126
14127 else
14128 Append_To (Args,
83c6c069 14129 New_Occurrence_Of
feea0ab5 14130 (RTE (RE_Default_Interrupt_Priority), Loc));
14131 end if;
14132 end if;
14133
ee6ba406 14134 -- Build the Attach_Handler table argument
14135
14136 while Present (Ritem) loop
14137 if Nkind (Ritem) = N_Pragma
70966f50 14138 and then Pragma_Name (Ritem) = Name_Attach_Handler
ee6ba406 14139 then
14140 declare
5c61a0ff 14141 Handler : constant Node_Id :=
14142 First (Pragma_Argument_Associations (Ritem));
ee6ba406 14143
70966f50 14144 Interrupt : constant Node_Id := Next (Handler);
14145 Expr : constant Node_Id := Expression (Interrupt);
9dfe12ae 14146
5c61a0ff 14147 begin
ee6ba406 14148 Append_To (Table,
14149 Make_Aggregate (Loc, Expressions => New_List (
9dfe12ae 14150 Unchecked_Convert_To
14151 (RTE (RE_System_Interrupt_Id), Expr),
ee6ba406 14152 Make_Attribute_Reference (Loc,
7ee08bca 14153 Prefix =>
14154 Make_Selected_Component (Loc,
14155 Prefix =>
14156 Make_Identifier (Loc, Name_uInit),
14157 Selector_Name =>
14158 Duplicate_Subexpr_No_Checks
14159 (Expression (Handler))),
ee6ba406 14160 Attribute_Name => Name_Access))));
14161 end;
14162 end if;
14163
14164 Next_Rep_Item (Ritem);
14165 end loop;
14166
2866d595 14167 -- Append the table argument we just built
14168
ee6ba406 14169 Append_To (Args, Make_Aggregate (Loc, Table));
14170
57993a53 14171 -- Append the Install_Handlers (or Install_Restricted_Handlers)
14172 -- call to the statements.
2866d595 14173
57993a53 14174 if Restricted then
14175 -- Call a simplified version of Install_Handlers to be used
14176 -- when the Ravenscar restrictions are in effect
14177 -- (Install_Restricted_Handlers).
14178
14179 Append_To (L,
14180 Make_Procedure_Call_Statement (Loc,
14181 Name =>
83c6c069 14182 New_Occurrence_Of
7ee08bca 14183 (RTE (RE_Install_Restricted_Handlers), Loc),
57993a53 14184 Parameter_Associations => Args));
14185
14186 else
7413d80d 14187 if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
7ee08bca 14188
7413d80d 14189 -- First, prepends the _object argument
57993a53 14190
7413d80d 14191 Prepend_To (Args,
14192 Make_Attribute_Reference (Loc,
7ee08bca 14193 Prefix =>
7413d80d 14194 Make_Selected_Component (Loc,
14195 Prefix => Make_Identifier (Loc, Name_uInit),
14196 Selector_Name =>
14197 Make_Identifier (Loc, Name_uObject)),
14198 Attribute_Name => Name_Unchecked_Access));
14199 end if;
57993a53 14200
14201 -- Then, insert call to Install_Handlers
14202
14203 Append_To (L,
14204 Make_Procedure_Call_Statement (Loc,
7ee08bca 14205 Name =>
14206 New_Occurrence_Of (RTE (RE_Install_Handlers), Loc),
57993a53 14207 Parameter_Associations => Args));
14208 end if;
ee6ba406 14209 end;
14210 end if;
14211
14212 return L;
14213 end Make_Initialize_Protection;
14214
14215 ---------------------------
14216 -- Make_Task_Create_Call --
14217 ---------------------------
14218
14219 function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
14220 Loc : constant Source_Ptr := Sloc (Task_Rec);
f89cc618 14221 Args : List_Id;
14222 Ecount : Node_Id;
ee6ba406 14223 Name : Node_Id;
ee6ba406 14224 Tdec : Node_Id;
f89cc618 14225 Tdef : Node_Id;
ee6ba406 14226 Tnam : Name_Id;
f89cc618 14227 Ttyp : Node_Id;
ee6ba406 14228
14229 begin
14230 Ttyp := Corresponding_Concurrent_Type (Task_Rec);
14231 Tnam := Chars (Ttyp);
14232
76a1c25b 14233 -- Get task declaration. In the case of a task type declaration, this is
14234 -- simply the parent of the task type entity. In the single task
ee6ba406 14235 -- declaration, this parent will be the implicit type, and we can find
76a1c25b 14236 -- the corresponding single task declaration by searching forward in the
14237 -- declaration list in the tree.
ee6ba406 14238
76a1c25b 14239 -- Is the test for N_Single_Task_Declaration needed here??? Nodes of
14240 -- this type should have been removed during semantic analysis.
ee6ba406 14241
76a1c25b 14242 Tdec := Parent (Ttyp);
5809835d 14243 while not Nkind_In (Tdec, N_Task_Type_Declaration,
14244 N_Single_Task_Declaration)
ee6ba406 14245 loop
14246 Next (Tdec);
14247 end loop;
14248
14249 -- Now we can find the task definition from this declaration
14250
14251 Tdef := Task_Definition (Tdec);
14252
14253 -- Build the parameter list for the call. Note that _Init is the name
14254 -- of the formal for the object to be initialized, which is the task
14255 -- value record itself.
14256
14257 Args := New_List;
14258
14259 -- Priority parameter. Set to Unspecified_Priority unless there is a
2fec2b51 14260 -- Priority rep item, in which case we take the value from the rep item.
ee6ba406 14261
06ef5f86 14262 if Has_Rep_Item (Ttyp, Name_Priority, Check_Parents => False) then
ee6ba406 14263 Append_To (Args,
14264 Make_Selected_Component (Loc,
55868293 14265 Prefix => Make_Identifier (Loc, Name_uInit),
ee6ba406 14266 Selector_Name => Make_Identifier (Loc, Name_uPriority)));
ee6ba406 14267 else
14268 Append_To (Args,
83c6c069 14269 New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
ee6ba406 14270 end if;
14271
fb4b3501 14272 -- Optional Stack parameter
14273
14274 if Restricted_Profile then
14275
14276 -- If the stack has been preallocated by the expander then
14277 -- pass its address. Otherwise, pass a null address.
14278
14279 if Preallocated_Stacks_On_Target then
14280 Append_To (Args,
14281 Make_Attribute_Reference (Loc,
55868293 14282 Prefix =>
14283 Make_Selected_Component (Loc,
14284 Prefix => Make_Identifier (Loc, Name_uInit),
14285 Selector_Name => Make_Identifier (Loc, Name_uStack)),
fb4b3501 14286 Attribute_Name => Name_Address));
14287
14288 else
14289 Append_To (Args,
83c6c069 14290 New_Occurrence_Of (RTE (RE_Null_Address), Loc));
fb4b3501 14291 end if;
14292 end if;
14293
ee6ba406 14294 -- Size parameter. If no Storage_Size pragma is present, then
14295 -- the size is taken from the taskZ variable for the type, which
14296 -- is either Unspecified_Size, or has been reset by the use of
14297 -- a Storage_Size attribute definition clause. If a pragma is
14298 -- present, then the size is taken from the _Size field of the
14299 -- task value record, which was set from the pragma value.
14300
c0688d2b 14301 if Present (Tdef) and then Has_Storage_Size_Pragma (Tdef) then
ee6ba406 14302 Append_To (Args,
14303 Make_Selected_Component (Loc,
55868293 14304 Prefix => Make_Identifier (Loc, Name_uInit),
ee6ba406 14305 Selector_Name => Make_Identifier (Loc, Name_uSize)));
14306
14307 else
14308 Append_To (Args,
83c6c069 14309 New_Occurrence_Of (Storage_Size_Variable (Ttyp), Loc));
ee6ba406 14310 end if;
14311
14312 -- Task_Info parameter. Set to Unspecified_Task_Info unless there is a
14313 -- Task_Info pragma, in which case we take the value from the pragma.
14314
89b3b365 14315 if Has_Rep_Pragma (Ttyp, Name_Task_Info, Check_Parents => False) then
ee6ba406 14316 Append_To (Args,
14317 Make_Selected_Component (Loc,
55868293 14318 Prefix => Make_Identifier (Loc, Name_uInit),
ee6ba406 14319 Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
14320
14321 else
14322 Append_To (Args,
83c6c069 14323 New_Occurrence_Of (RTE (RE_Unspecified_Task_Info), Loc));
ee6ba406 14324 end if;
14325
89f1e35c 14326 -- CPU parameter. Set to Unspecified_CPU unless there is a CPU rep item,
14327 -- in which case we take the value from the rep item. The parameter is
d9c927cc 14328 -- passed as an Integer because in the case of unspecified CPU the
14329 -- value is not in the range of CPU_Range.
14330
06ef5f86 14331 if Has_Rep_Item (Ttyp, Name_CPU, Check_Parents => False) then
d9c927cc 14332 Append_To (Args,
14333 Convert_To (Standard_Integer,
14334 Make_Selected_Component (Loc,
55868293 14335 Prefix => Make_Identifier (Loc, Name_uInit),
d9c927cc 14336 Selector_Name => Make_Identifier (Loc, Name_uCPU))));
d9c927cc 14337 else
14338 Append_To (Args,
83c6c069 14339 New_Occurrence_Of (RTE (RE_Unspecified_CPU), Loc));
d9c927cc 14340 end if;
14341
ee6ba406 14342 if not Restricted_Profile then
14343
57993a53 14344 -- Deadline parameter. If no Relative_Deadline pragma is present,
14345 -- then the deadline is Time_Span_Zero. If a pragma is present, then
14346 -- the deadline is taken from the _Relative_Deadline field of the
14347 -- task value record, which was set from the pragma value. Note that
14348 -- this parameter must not be generated for the restricted profiles
14349 -- since Ravenscar does not allow deadlines.
14350
14351 -- Case where pragma Relative_Deadline applies: use given value
14352
c0688d2b 14353 if Present (Tdef) and then Has_Relative_Deadline_Pragma (Tdef) then
57993a53 14354 Append_To (Args,
14355 Make_Selected_Component (Loc,
7ee08bca 14356 Prefix => Make_Identifier (Loc, Name_uInit),
57993a53 14357 Selector_Name =>
14358 Make_Identifier (Loc, Name_uRelative_Deadline)));
14359
14360 -- No pragma Relative_Deadline apply to the task
14361
14362 else
14363 Append_To (Args,
83c6c069 14364 New_Occurrence_Of (RTE (RE_Time_Span_Zero), Loc));
57993a53 14365 end if;
14366
89f1e35c 14367 -- Dispatching_Domain parameter. If no Dispatching_Domain rep item is
14368 -- present, then the dispatching domain is null. If a rep item is
14369 -- present, then the dispatching domain is taken from the
14370 -- _Dispatching_Domain field of the task value record, which was set
5a8fe506 14371 -- from the rep item value.
a7a4a7c2 14372
89f1e35c 14373 -- Case where Dispatching_Domain rep item applies: use given value
a7a4a7c2 14374
06ef5f86 14375 if Has_Rep_Item
14376 (Ttyp, Name_Dispatching_Domain, Check_Parents => False)
14377 then
a7a4a7c2 14378 Append_To (Args,
14379 Make_Selected_Component (Loc,
14380 Prefix =>
14381 Make_Identifier (Loc, Name_uInit),
14382 Selector_Name =>
14383 Make_Identifier (Loc, Name_uDispatching_Domain)));
14384
5a8fe506 14385 -- No pragma or aspect Dispatching_Domain applies to the task
a7a4a7c2 14386
14387 else
14388 Append_To (Args, Make_Null (Loc));
14389 end if;
14390
ee6ba406 14391 -- Number of entries. This is an expression of the form:
57993a53 14392
ee6ba406 14393 -- n + _Init.a'Length + _Init.a'B'Length + ...
57993a53 14394
ee6ba406 14395 -- where a,b... are the entry family names for the task definition
14396
57993a53 14397 Ecount :=
14398 Build_Entry_Count_Expression
14399 (Ttyp,
14400 Component_Items
14401 (Component_List
14402 (Type_Definition
14403 (Parent (Corresponding_Record_Type (Ttyp))))),
14404 Loc);
ee6ba406 14405 Append_To (Args, Ecount);
14406
14407 -- Master parameter. This is a reference to the _Master parameter of
14408 -- the initialization procedure, except in the case of the pragma
11bd2f46 14409 -- Restrictions (No_Task_Hierarchy) where the value is fixed to
14410 -- System.Tasking.Library_Task_Level.
ee6ba406 14411
1e16c51c 14412 if Restriction_Active (No_Task_Hierarchy) = False then
ee6ba406 14413 Append_To (Args, Make_Identifier (Loc, Name_uMaster));
14414 else
11bd2f46 14415 Append_To (Args,
14416 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
ee6ba406 14417 end if;
14418 end if;
14419
14420 -- State parameter. This is a pointer to the task body procedure. The
57993a53 14421 -- required value is obtained by taking 'Unrestricted_Access of the task
14422 -- body procedure and converting it (with an unchecked conversion) to
14423 -- the type required by the task kernel. For further details, see the
14424 -- description of Expand_N_Task_Body. We use 'Unrestricted_Access rather
14425 -- than 'Address in order to avoid creating trampolines.
ee6ba406 14426
57993a53 14427 declare
14428 Body_Proc : constant Node_Id := Get_Task_Body_Procedure (Ttyp);
14429 Subp_Ptr_Typ : constant Node_Id :=
14430 Create_Itype (E_Access_Subprogram_Type, Tdec);
14431 Ref : constant Node_Id := Make_Itype_Reference (Loc);
14432
14433 begin
14434 Set_Directly_Designated_Type (Subp_Ptr_Typ, Body_Proc);
14435 Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
14436
14437 -- Be sure to freeze a reference to the access-to-subprogram type,
14438 -- otherwise gigi will complain that it's in the wrong scope, because
14439 -- it's actually inside the init procedure for the record type that
14440 -- corresponds to the task type.
14441
36ac5fbb 14442 Set_Itype (Ref, Subp_Ptr_Typ);
14443 Append_Freeze_Action (Task_Rec, Ref);
57993a53 14444
36ac5fbb 14445 Append_To (Args,
14446 Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
14447 Make_Qualified_Expression (Loc,
14448 Subtype_Mark => New_Occurrence_Of (Subp_Ptr_Typ, Loc),
14449 Expression =>
14450 Make_Attribute_Reference (Loc,
14451 Prefix => New_Occurrence_Of (Body_Proc, Loc),
14452 Attribute_Name => Name_Unrestricted_Access))));
57993a53 14453 end;
ee6ba406 14454
14455 -- Discriminants parameter. This is just the address of the task
14456 -- value record itself (which contains the discriminant values
14457
14458 Append_To (Args,
14459 Make_Attribute_Reference (Loc,
14460 Prefix => Make_Identifier (Loc, Name_uInit),
14461 Attribute_Name => Name_Address));
14462
14463 -- Elaborated parameter. This is an access to the elaboration Boolean
14464
14465 Append_To (Args,
14466 Make_Attribute_Reference (Loc,
14467 Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
14468 Attribute_Name => Name_Unchecked_Access));
14469
d4f55b2a 14470 -- Add Chain parameter (not done for sequential elaboration policy, see
14471 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
ee6ba406 14472
d4f55b2a 14473 if Partition_Elaboration_Policy /= 'S' then
e8b5f25d 14474 Append_To (Args, Make_Identifier (Loc, Name_uChain));
14475 end if;
ee6ba406 14476
9dfe12ae 14477 -- Task name parameter. Take this from the _Task_Id parameter to the
ee6ba406 14478 -- init call unless there is a Task_Name pragma, in which case we take
14479 -- the value from the pragma.
14480
89b3b365 14481 if Has_Rep_Pragma (Ttyp, Name_Task_Name, Check_Parents => False) then
fa0b5df1 14482 -- Copy expression in full, because it may be dynamic and have
14483 -- side effects.
14484
ee6ba406 14485 Append_To (Args,
284a54ba 14486 New_Copy_Tree
89f1e35c 14487 (Expression
14488 (First
14489 (Pragma_Argument_Associations
89b3b365 14490 (Get_Rep_Pragma
14491 (Ttyp, Name_Task_Name, Check_Parents => False))))));
ee6ba406 14492
14493 else
9dfe12ae 14494 Append_To (Args, Make_Identifier (Loc, Name_uTask_Name));
ee6ba406 14495 end if;
14496
14497 -- Created_Task parameter. This is the _Task_Id field of the task
14498 -- record value
14499
14500 Append_To (Args,
14501 Make_Selected_Component (Loc,
55868293 14502 Prefix => Make_Identifier (Loc, Name_uInit),
ee6ba406 14503 Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
14504
d4f55b2a 14505 declare
14506 Create_RE : RE_Id;
27286d2b 14507
d4f55b2a 14508 begin
14509 if Restricted_Profile then
14510 if Partition_Elaboration_Policy = 'S' then
14511 Create_RE := RE_Create_Restricted_Task_Sequential;
14512 else
14513 Create_RE := RE_Create_Restricted_Task;
14514 end if;
14515 else
14516 Create_RE := RE_Create_Task;
14517 end if;
27286d2b 14518
83c6c069 14519 Name := New_Occurrence_Of (RTE (Create_RE), Loc);
d4f55b2a 14520 end;
ee6ba406 14521
f89cc618 14522 return
14523 Make_Procedure_Call_Statement (Loc,
7ee08bca 14524 Name => Name,
f89cc618 14525 Parameter_Associations => Args);
ee6ba406 14526 end Make_Task_Create_Call;
14527
14528 ------------------------------
14529 -- Next_Protected_Operation --
14530 ------------------------------
14531
14532 function Next_Protected_Operation (N : Node_Id) return Node_Id is
14533 Next_Op : Node_Id;
14534
14535 begin
ea6969d4 14536 -- Check whether there is a subsequent body for a protected operation
14537 -- in the current protected body. In Ada2012 that includes expression
14538 -- functions that are completions.
14539
ee6ba406 14540 Next_Op := Next (N);
ee6ba406 14541 while Present (Next_Op)
ea6969d4 14542 and then not Nkind_In (Next_Op,
14543 N_Subprogram_Body, N_Entry_Body, N_Expression_Function)
ee6ba406 14544 loop
14545 Next (Next_Op);
14546 end loop;
14547
14548 return Next_Op;
14549 end Next_Protected_Operation;
14550
d333ad56 14551 ---------------------
14552 -- Null_Statements --
14553 ---------------------
14554
14555 function Null_Statements (Stats : List_Id) return Boolean is
14556 Stmt : Node_Id;
14557
14558 begin
14559 Stmt := First (Stats);
14560 while Nkind (Stmt) /= N_Empty
14561 and then (Nkind_In (Stmt, N_Null_Statement, N_Label)
c0688d2b 14562 or else
14563 (Nkind (Stmt) = N_Pragma
14564 and then
14565 Nam_In (Pragma_Name (Stmt), Name_Unreferenced,
14566 Name_Unmodified,
14567 Name_Warnings)))
d333ad56 14568 loop
14569 Next (Stmt);
14570 end loop;
14571
14572 return Nkind (Stmt) = N_Empty;
14573 end Null_Statements;
14574
d62940bf 14575 --------------------------
14576 -- Parameter_Block_Pack --
14577 --------------------------
14578
14579 function Parameter_Block_Pack
14580 (Loc : Source_Ptr;
14581 Blk_Typ : Entity_Id;
14582 Actuals : List_Id;
14583 Formals : List_Id;
14584 Decls : List_Id;
14585 Stmts : List_Id) return Node_Id
14586 is
76a1c25b 14587 Actual : Entity_Id;
14588 Expr : Node_Id := Empty;
14589 Formal : Entity_Id;
14590 Has_Param : Boolean := False;
14591 P : Entity_Id;
14592 Params : List_Id;
14593 Temp_Asn : Node_Id;
14594 Temp_Nam : Node_Id;
d62940bf 14595
14596 begin
14597 Actual := First (Actuals);
14598 Formal := Defining_Identifier (First (Formals));
14599 Params := New_List;
d62940bf 14600 while Present (Actual) loop
14601 if Is_By_Copy_Type (Etype (Actual)) then
14602 -- Generate:
14603 -- Jnn : aliased <formal-type>
14604
ec97ce79 14605 Temp_Nam := Make_Temporary (Loc, 'J');
d62940bf 14606
14607 Append_To (Decls,
14608 Make_Object_Declaration (Loc,
7ee08bca 14609 Aliased_Present => True,
14610 Defining_Identifier => Temp_Nam,
14611 Object_Definition =>
83c6c069 14612 New_Occurrence_Of (Etype (Formal), Loc)));
d62940bf 14613
14614 if Ekind (Formal) /= E_Out_Parameter then
14615
14616 -- Generate:
14617 -- Jnn := <actual>
14618
14619 Temp_Asn :=
83c6c069 14620 New_Occurrence_Of (Temp_Nam, Loc);
d62940bf 14621
14622 Set_Assignment_OK (Temp_Asn);
14623
14624 Append_To (Stmts,
14625 Make_Assignment_Statement (Loc,
7ee08bca 14626 Name => Temp_Asn,
14627 Expression => New_Copy_Tree (Actual)));
d62940bf 14628 end if;
14629
14630 -- Generate:
14631 -- Jnn'unchecked_access
14632
14633 Append_To (Params,
14634 Make_Attribute_Reference (Loc,
7ee08bca 14635 Attribute_Name => Name_Unchecked_Access,
14636 Prefix => New_Occurrence_Of (Temp_Nam, Loc)));
76a1c25b 14637
14638 Has_Param := True;
14639
14640 -- The controlling parameter is omitted
14641
d62940bf 14642 else
76a1c25b 14643 if not Is_Controlling_Actual (Actual) then
14644 Append_To (Params,
14645 Make_Reference (Loc, New_Copy_Tree (Actual)));
14646
14647 Has_Param := True;
14648 end if;
d62940bf 14649 end if;
14650
14651 Next_Actual (Actual);
14652 Next_Formal_With_Extras (Formal);
14653 end loop;
14654
76a1c25b 14655 if Has_Param then
14656 Expr := Make_Aggregate (Loc, Params);
14657 end if;
14658
d62940bf 14659 -- Generate:
14660 -- P : Ann := (
14661 -- J1'unchecked_access;
14662 -- <actual2>'reference;
14663 -- ...);
14664
ec97ce79 14665 P := Make_Temporary (Loc, 'P');
d62940bf 14666
14667 Append_To (Decls,
14668 Make_Object_Declaration (Loc,
7ee08bca 14669 Defining_Identifier => P,
14670 Object_Definition => New_Occurrence_Of (Blk_Typ, Loc),
14671 Expression => Expr));
d62940bf 14672
76a1c25b 14673 return P;
d62940bf 14674 end Parameter_Block_Pack;
14675
14676 ----------------------------
14677 -- Parameter_Block_Unpack --
14678 ----------------------------
14679
14680 function Parameter_Block_Unpack
14681 (Loc : Source_Ptr;
76a1c25b 14682 P : Entity_Id;
d62940bf 14683 Actuals : List_Id;
14684 Formals : List_Id) return List_Id
14685 is
76a1c25b 14686 Actual : Entity_Id;
14687 Asnmt : Node_Id;
14688 Formal : Entity_Id;
14689 Has_Asnmt : Boolean := False;
14690 Result : constant List_Id := New_List;
d62940bf 14691
14692 begin
14693 Actual := First (Actuals);
14694 Formal := Defining_Identifier (First (Formals));
d62940bf 14695 while Present (Actual) loop
14696 if Is_By_Copy_Type (Etype (Actual))
14697 and then Ekind (Formal) /= E_In_Parameter
14698 then
d62940bf 14699 -- Generate:
14700 -- <actual> := P.<formal>;
14701
14702 Asnmt :=
14703 Make_Assignment_Statement (Loc,
7ee08bca 14704 Name =>
d62940bf 14705 New_Copy (Actual),
14706 Expression =>
14707 Make_Explicit_Dereference (Loc,
14708 Make_Selected_Component (Loc,
55868293 14709 Prefix =>
83c6c069 14710 New_Occurrence_Of (P, Loc),
d62940bf 14711 Selector_Name =>
14712 Make_Identifier (Loc, Chars (Formal)))));
14713
14714 Set_Assignment_OK (Name (Asnmt));
d62940bf 14715 Append_To (Result, Asnmt);
76a1c25b 14716
14717 Has_Asnmt := True;
d62940bf 14718 end if;
14719
14720 Next_Actual (Actual);
14721 Next_Formal_With_Extras (Formal);
14722 end loop;
14723
76a1c25b 14724 if Has_Asnmt then
d62940bf 14725 return Result;
76a1c25b 14726 else
14727 return New_List (Make_Null_Statement (Loc));
d62940bf 14728 end if;
d62940bf 14729 end Parameter_Block_Unpack;
14730
ee6ba406 14731 ----------------------
14732 -- Set_Discriminals --
14733 ----------------------
14734
f15731c4 14735 procedure Set_Discriminals (Dec : Node_Id) is
ee6ba406 14736 D : Entity_Id;
14737 Pdef : Entity_Id;
14738 D_Minal : Entity_Id;
14739
14740 begin
14741 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
14742 Pdef := Defining_Identifier (Dec);
14743
14744 if Has_Discriminants (Pdef) then
14745 D := First_Discriminant (Pdef);
ee6ba406 14746 while Present (D) loop
14747 D_Minal :=
14748 Make_Defining_Identifier (Sloc (D),
14749 Chars => New_External_Name (Chars (D), 'D'));
14750
14751 Set_Ekind (D_Minal, E_Constant);
14752 Set_Etype (D_Minal, Etype (D));
9dfe12ae 14753 Set_Scope (D_Minal, Pdef);
ee6ba406 14754 Set_Discriminal (D, D_Minal);
14755 Set_Discriminal_Link (D_Minal, D);
14756
14757 Next_Discriminant (D);
14758 end loop;
14759 end if;
14760 end Set_Discriminals;
14761
d333ad56 14762 -----------------------
14763 -- Trivial_Accept_OK --
14764 -----------------------
14765
14766 function Trivial_Accept_OK return Boolean is
14767 begin
14768 case Opt.Task_Dispatching_Policy is
14769
14770 -- If we have the default task dispatching policy in effect, we can
14771 -- definitely do the optimization (one way of looking at this is to
14772 -- think of the formal definition of the default policy being allowed
14773 -- to run any task it likes after a rendezvous, so even if notionally
14774 -- a full rescheduling occurs, we can say that our dispatching policy
14775 -- (i.e. the default dispatching policy) reorders the queue to be the
14776 -- same as just before the call.
14777
14778 when ' ' =>
14779 return True;
14780
bf3e1520 14781 -- FIFO_Within_Priorities certainly does not permit this
d333ad56 14782 -- optimization since the Rendezvous is a scheduling action that may
14783 -- require some other task to be run.
14784
14785 when 'F' =>
14786 return False;
14787
14788 -- For now, disallow the optimization for all other policies. This
14789 -- may be over-conservative, but it is certainly not incorrect.
14790
14791 when others =>
14792 return False;
14793
14794 end case;
14795 end Trivial_Accept_OK;
14796
ee6ba406 14797end Exp_Ch9;