]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/exp_disp.adb
2009-07-23 Javier Miranda <miranda@adacore.com>
[thirdparty/gcc.git] / gcc / ada / exp_disp.adb
CommitLineData
ee6ba406 1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ D I S P --
6-- --
7-- B o d y --
8-- --
294b942d 9-- Copyright (C) 1992-2009, 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- --
24971415 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 --
24971415 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;
aad6babd 28with Debug; use Debug;
ee6ba406 29with Einfo; use Einfo;
30with Elists; use Elists;
31with Errout; use Errout;
343d35dc 32with Exp_Atag; use Exp_Atag;
ee6ba406 33with Exp_Ch7; use Exp_Ch7;
76a1c25b 34with Exp_Dbug; use Exp_Dbug;
ee6ba406 35with Exp_Tss; use Exp_Tss;
36with Exp_Util; use Exp_Util;
af647dc7 37with Freeze; use Freeze;
ee6ba406 38with Itypes; use Itypes;
b6b96867 39with Layout; use Layout;
ee6ba406 40with Nlists; use Nlists;
41with Nmake; use Nmake;
aad6babd 42with Namet; use Namet;
ee6ba406 43with Opt; use Opt;
aad6babd 44with Output; use Output;
68f95949 45with Restrict; use Restrict;
46with Rident; use Rident;
ee6ba406 47with Rtsfind; use Rtsfind;
aad6babd 48with Sem; use Sem;
d60c9ff7 49with Sem_Aux; use Sem_Aux;
725a69d2 50with Sem_Ch6; use Sem_Ch6;
acf97c11 51with Sem_Ch7; use Sem_Ch7;
725a69d2 52with Sem_Ch8; use Sem_Ch8;
ee6ba406 53with Sem_Disp; use Sem_Disp;
725a69d2 54with Sem_Eval; use Sem_Eval;
ee6ba406 55with Sem_Res; use Sem_Res;
aad6babd 56with Sem_Type; use Sem_Type;
ee6ba406 57with Sem_Util; use Sem_Util;
58with Sinfo; use Sinfo;
59with Snames; use Snames;
60with Stand; use Stand;
725a69d2 61with Stringt; use Stringt;
ee6ba406 62with Tbuild; use Tbuild;
63with Uintp; use Uintp;
64
65package body Exp_Disp is
66
725a69d2 67 -----------------------
68 -- Local Subprograms --
69 -----------------------
ee6ba406 70
68f95949 71 function Default_Prim_Op_Position (E : Entity_Id) return Uint;
aad6babd 72 -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table
73 -- of the default primitive operations.
74
24971415 75 function Has_DT (Typ : Entity_Id) return Boolean;
76 pragma Inline (Has_DT);
77 -- Returns true if we generate a dispatch table for tagged type Typ
78
af647dc7 79 function Is_Predefined_Dispatching_Alias (Prim : Entity_Id) return Boolean;
80 -- Returns true if Prim is not a predefined dispatching primitive but it is
36b938a3 81 -- an alias of a predefined dispatching primitive (i.e. through a renaming)
af647dc7 82
cd534f03 83 function New_Value (From : Node_Id) return Node_Id;
84 -- From is the original Expression. New_Value is equivalent to a call
85 -- to Duplicate_Subexpr with an explicit dereference when From is an
86 -- access parameter.
87
ee6ba406 88 function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean;
89 -- Check if the type has a private view or if the public view appears
90 -- in the visible part of a package spec.
91
d62940bf 92 function Prim_Op_Kind
93 (Prim : Entity_Id;
94 Typ : Entity_Id) return Node_Id;
95 -- Ada 2005 (AI-345): Determine the primitive operation kind of Prim
952af0b9 96 -- according to its type Typ. Return a reference to an RE_Prim_Op_Kind
d62940bf 97 -- enumeration value.
aad6babd 98
952af0b9 99 function Tagged_Kind (T : Entity_Id) return Node_Id;
100 -- Ada 2005 (AI-345): Determine the tagged kind of T and return a reference
101 -- to an RE_Tagged_Kind enumeration value.
102
cd534f03 103 ----------------------
104 -- Apply_Tag_Checks --
105 ----------------------
106
107 procedure Apply_Tag_Checks (Call_Node : Node_Id) is
108 Loc : constant Source_Ptr := Sloc (Call_Node);
109 Ctrl_Arg : constant Node_Id := Controlling_Argument (Call_Node);
110 Ctrl_Typ : constant Entity_Id := Base_Type (Etype (Ctrl_Arg));
111 Param_List : constant List_Id := Parameter_Associations (Call_Node);
112
113 Subp : Entity_Id;
114 CW_Typ : Entity_Id;
115 Param : Node_Id;
116 Typ : Entity_Id;
117 Eq_Prim_Op : Entity_Id := Empty;
118
119 begin
120 if No_Run_Time_Mode then
121 Error_Msg_CRT ("tagged types", Call_Node);
122 return;
123 end if;
124
125 -- Apply_Tag_Checks is called directly from the semantics, so we need
126 -- a check to see whether expansion is active before proceeding. In
127 -- addition, there is no need to expand the call when compiling under
128 -- restriction No_Dispatching_Calls; the semantic analyzer has
129 -- previously notified the violation of this restriction.
130
131 if not Expander_Active
132 or else Restriction_Active (No_Dispatching_Calls)
133 then
134 return;
135 end if;
136
137 -- Set subprogram. If this is an inherited operation that was
138 -- overridden, the body that is being called is its alias.
139
140 Subp := Entity (Name (Call_Node));
141
142 if Present (Alias (Subp))
143 and then Is_Inherited_Operation (Subp)
144 and then No (DTC_Entity (Subp))
145 then
146 Subp := Alias (Subp);
147 end if;
148
149 -- Definition of the class-wide type and the tagged type
150
151 -- If the controlling argument is itself a tag rather than a tagged
152 -- object, then use the class-wide type associated with the subprogram's
153 -- controlling type. This case can occur when a call to an inherited
154 -- primitive has an actual that originated from a default parameter
155 -- given by a tag-indeterminate call and when there is no other
156 -- controlling argument providing the tag (AI-239 requires dispatching).
157 -- This capability of dispatching directly by tag is also needed by the
158 -- implementation of AI-260 (for the generic dispatching constructors).
159
160 if Ctrl_Typ = RTE (RE_Tag)
161 or else (RTE_Available (RE_Interface_Tag)
162 and then Ctrl_Typ = RTE (RE_Interface_Tag))
163 then
164 CW_Typ := Class_Wide_Type (Find_Dispatching_Type (Subp));
165
166 -- Class_Wide_Type is applied to the expressions used to initialize
167 -- CW_Typ, to ensure that CW_Typ always denotes a class-wide type, since
168 -- there are cases where the controlling type is resolved to a specific
169 -- type (such as for designated types of arguments such as CW'Access).
170
171 elsif Is_Access_Type (Ctrl_Typ) then
172 CW_Typ := Class_Wide_Type (Designated_Type (Ctrl_Typ));
173
174 else
175 CW_Typ := Class_Wide_Type (Ctrl_Typ);
176 end if;
177
178 Typ := Root_Type (CW_Typ);
179
180 if Ekind (Typ) = E_Incomplete_Type then
181 Typ := Non_Limited_View (Typ);
182 end if;
183
184 if not Is_Limited_Type (Typ) then
185 Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
186 end if;
187
188 -- Dispatching call to C++ primitive
189
190 if Is_CPP_Class (Typ) then
191 null;
192
193 -- Dispatching call to Ada primitive
194
195 elsif Present (Param_List) then
196
197 -- Generate the Tag checks when appropriate
198
199 Param := First_Actual (Call_Node);
200 while Present (Param) loop
201
202 -- No tag check with itself
203
204 if Param = Ctrl_Arg then
205 null;
206
207 -- No tag check for parameter whose type is neither tagged nor
208 -- access to tagged (for access parameters)
209
210 elsif No (Find_Controlling_Arg (Param)) then
211 null;
212
213 -- No tag check for function dispatching on result if the
214 -- Tag given by the context is this one
215
216 elsif Find_Controlling_Arg (Param) = Ctrl_Arg then
217 null;
218
219 -- "=" is the only dispatching operation allowed to get
220 -- operands with incompatible tags (it just returns false).
221 -- We use Duplicate_Subexpr_Move_Checks instead of calling
222 -- Relocate_Node because the value will be duplicated to
223 -- check the tags.
224
225 elsif Subp = Eq_Prim_Op then
226 null;
227
228 -- No check in presence of suppress flags
229
230 elsif Tag_Checks_Suppressed (Etype (Param))
231 or else (Is_Access_Type (Etype (Param))
232 and then Tag_Checks_Suppressed
233 (Designated_Type (Etype (Param))))
234 then
235 null;
236
237 -- Optimization: no tag checks if the parameters are identical
238
239 elsif Is_Entity_Name (Param)
240 and then Is_Entity_Name (Ctrl_Arg)
241 and then Entity (Param) = Entity (Ctrl_Arg)
242 then
243 null;
244
245 -- Now we need to generate the Tag check
246
247 else
248 -- Generate code for tag equality check
249 -- Perhaps should have Checks.Apply_Tag_Equality_Check???
250
251 Insert_Action (Ctrl_Arg,
252 Make_Implicit_If_Statement (Call_Node,
253 Condition =>
254 Make_Op_Ne (Loc,
255 Left_Opnd =>
256 Make_Selected_Component (Loc,
257 Prefix => New_Value (Ctrl_Arg),
258 Selector_Name =>
259 New_Reference_To
260 (First_Tag_Component (Typ), Loc)),
261
262 Right_Opnd =>
263 Make_Selected_Component (Loc,
264 Prefix =>
265 Unchecked_Convert_To (Typ, New_Value (Param)),
266 Selector_Name =>
267 New_Reference_To
268 (First_Tag_Component (Typ), Loc))),
269
270 Then_Statements =>
271 New_List (New_Constraint_Error (Loc))));
272 end if;
273
274 Next_Actual (Param);
275 end loop;
276 end if;
277 end Apply_Tag_Checks;
278
24971415 279 ------------------------
280 -- Building_Static_DT --
281 ------------------------
282
283 function Building_Static_DT (Typ : Entity_Id) return Boolean is
cc60bd16 284 Root_Typ : Entity_Id := Root_Type (Typ);
285
24971415 286 begin
cc60bd16 287 -- Handle private types
288
289 if Present (Full_View (Root_Typ)) then
290 Root_Typ := Full_View (Root_Typ);
291 end if;
292
24971415 293 return Static_Dispatch_Tables
e7e688dd 294 and then Is_Library_Level_Tagged_Type (Typ)
295
296 -- If the type is derived from a CPP class we cannot statically
297 -- build the dispatch tables because we must inherit primitives
298 -- from the CPP side.
299
cc60bd16 300 and then not Is_CPP_Class (Root_Typ);
24971415 301 end Building_Static_DT;
302
17e14451 303 ----------------------------------
304 -- Build_Static_Dispatch_Tables --
305 ----------------------------------
306
307 procedure Build_Static_Dispatch_Tables (N : Entity_Id) is
308 Target_List : List_Id;
309
310 procedure Build_Dispatch_Tables (List : List_Id);
311 -- Build the static dispatch table of tagged types found in the list of
312 -- declarations. The generated nodes are added at the end of Target_List
313
314 procedure Build_Package_Dispatch_Tables (N : Node_Id);
315 -- Build static dispatch tables associated with package declaration N
316
317 ---------------------------
318 -- Build_Dispatch_Tables --
319 ---------------------------
320
321 procedure Build_Dispatch_Tables (List : List_Id) is
322 D : Node_Id;
323
324 begin
325 D := First (List);
326 while Present (D) loop
327
328 -- Handle nested packages and package bodies recursively. The
329 -- generated code is placed on the Target_List established for
330 -- the enclosing compilation unit.
331
332 if Nkind (D) = N_Package_Declaration then
333 Build_Package_Dispatch_Tables (D);
334
335 elsif Nkind (D) = N_Package_Body then
336 Build_Dispatch_Tables (Declarations (D));
337
338 elsif Nkind (D) = N_Package_Body_Stub
339 and then Present (Library_Unit (D))
340 then
341 Build_Dispatch_Tables
342 (Declarations (Proper_Body (Unit (Library_Unit (D)))));
343
344 -- Handle full type declarations and derivations of library
345 -- level tagged types
346
3164ed99 347 elsif Nkind_In (D, N_Full_Type_Declaration,
348 N_Derived_Type_Definition)
17e14451 349 and then Is_Library_Level_Tagged_Type (Defining_Entity (D))
350 and then Ekind (Defining_Entity (D)) /= E_Record_Subtype
351 and then not Is_Private_Type (Defining_Entity (D))
352 then
442049cc 353 -- We do not generate dispatch tables for the internal types
d9fac90e 354 -- created for a type extension with unknown discriminants
355 -- The needed information is shared with the source type,
356 -- See Expand_N_Record_Extension.
357
442049cc 358 if Is_Underlying_Record_View (Defining_Entity (D))
359 or else
360 (not Comes_From_Source (Defining_Entity (D))
361 and then
2f29393f 362 Has_Unknown_Discriminants (Etype (Defining_Entity (D)))
442049cc 363 and then
2f29393f 364 not Comes_From_Source
365 (First_Subtype (Defining_Entity (D))))
d9fac90e 366 then
367 null;
d9fac90e 368 else
369 Insert_List_After_And_Analyze (Last (Target_List),
370 Make_DT (Defining_Entity (D)));
371 end if;
17e14451 372
373 -- Handle private types of library level tagged types. We must
374 -- exchange the private and full-view to ensure the correct
a735d663 375 -- expansion. If the full view is a synchronized type ignore
376 -- the type because the table will be built for the corresponding
377 -- record type, that has its own declaration.
17e14451 378
379 elsif (Nkind (D) = N_Private_Type_Declaration
380 or else Nkind (D) = N_Private_Extension_Declaration)
381 and then Present (Full_View (Defining_Entity (D)))
17e14451 382 then
383 declare
acf97c11 384 E1 : constant Entity_Id := Defining_Entity (D);
a735d663 385 E2 : constant Entity_Id := Full_View (E1);
acf97c11 386
17e14451 387 begin
a735d663 388 if Is_Library_Level_Tagged_Type (E2)
389 and then Ekind (E2) /= E_Record_Subtype
390 and then not Is_Concurrent_Type (E2)
391 then
392 Exchange_Declarations (E1);
393 Insert_List_After_And_Analyze (Last (Target_List),
394 Make_DT (E1));
395 Exchange_Declarations (E2);
396 end if;
17e14451 397 end;
398 end if;
399
400 Next (D);
401 end loop;
402 end Build_Dispatch_Tables;
403
404 -----------------------------------
405 -- Build_Package_Dispatch_Tables --
406 -----------------------------------
407
408 procedure Build_Package_Dispatch_Tables (N : Node_Id) is
409 Spec : constant Node_Id := Specification (N);
410 Id : constant Entity_Id := Defining_Entity (N);
411 Vis_Decls : constant List_Id := Visible_Declarations (Spec);
412 Priv_Decls : constant List_Id := Private_Declarations (Spec);
413
414 begin
415 Push_Scope (Id);
416
417 if Present (Priv_Decls) then
418 Build_Dispatch_Tables (Vis_Decls);
419 Build_Dispatch_Tables (Priv_Decls);
420
421 elsif Present (Vis_Decls) then
422 Build_Dispatch_Tables (Vis_Decls);
423 end if;
424
425 Pop_Scope;
426 end Build_Package_Dispatch_Tables;
427
428 -- Start of processing for Build_Static_Dispatch_Tables
429
430 begin
431 if not Expander_Active
662256db 432 or else not Tagged_Type_Expansion
17e14451 433 then
434 return;
435 end if;
436
437 if Nkind (N) = N_Package_Declaration then
438 declare
439 Spec : constant Node_Id := Specification (N);
440 Vis_Decls : constant List_Id := Visible_Declarations (Spec);
441 Priv_Decls : constant List_Id := Private_Declarations (Spec);
442
443 begin
444 if Present (Priv_Decls)
445 and then Is_Non_Empty_List (Priv_Decls)
446 then
447 Target_List := Priv_Decls;
448
449 elsif not Present (Vis_Decls) then
450 Target_List := New_List;
451 Set_Private_Declarations (Spec, Target_List);
452 else
453 Target_List := Vis_Decls;
454 end if;
455
456 Build_Package_Dispatch_Tables (N);
457 end;
458
459 else pragma Assert (Nkind (N) = N_Package_Body);
460 Target_List := Declarations (N);
461 Build_Dispatch_Tables (Target_List);
462 end if;
463 end Build_Static_Dispatch_Tables;
464
aad6babd 465 ------------------------------
466 -- Default_Prim_Op_Position --
467 ------------------------------
468
68f95949 469 function Default_Prim_Op_Position (E : Entity_Id) return Uint is
aad6babd 470 TSS_Name : TSS_Name_Type;
aad6babd 471
472 begin
aad6babd 473 Get_Name_String (Chars (E));
474 TSS_Name :=
475 TSS_Name_Type
476 (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
477
478 if Chars (E) = Name_uSize then
479 return Uint_1;
480
481 elsif Chars (E) = Name_uAlignment then
482 return Uint_2;
483
484 elsif TSS_Name = TSS_Stream_Read then
485 return Uint_3;
486
487 elsif TSS_Name = TSS_Stream_Write then
488 return Uint_4;
489
490 elsif TSS_Name = TSS_Stream_Input then
491 return Uint_5;
492
493 elsif TSS_Name = TSS_Stream_Output then
494 return Uint_6;
495
496 elsif Chars (E) = Name_Op_Eq then
497 return Uint_7;
498
499 elsif Chars (E) = Name_uAssign then
500 return Uint_8;
501
502 elsif TSS_Name = TSS_Deep_Adjust then
503 return Uint_9;
504
505 elsif TSS_Name = TSS_Deep_Finalize then
506 return Uint_10;
507
76a1c25b 508 elsif Ada_Version >= Ada_05 then
509 if Chars (E) = Name_uDisp_Asynchronous_Select then
510 return Uint_11;
d62940bf 511
76a1c25b 512 elsif Chars (E) = Name_uDisp_Conditional_Select then
513 return Uint_12;
d62940bf 514
76a1c25b 515 elsif Chars (E) = Name_uDisp_Get_Prim_Op_Kind then
516 return Uint_13;
d62940bf 517
76a1c25b 518 elsif Chars (E) = Name_uDisp_Get_Task_Id then
519 return Uint_14;
d62940bf 520
cdb1c38f 521 elsif Chars (E) = Name_uDisp_Requeue then
76a1c25b 522 return Uint_15;
cdb1c38f 523
524 elsif Chars (E) = Name_uDisp_Timed_Select then
525 return Uint_16;
76a1c25b 526 end if;
aad6babd 527 end if;
76a1c25b 528
529 raise Program_Error;
aad6babd 530 end Default_Prim_Op_Position;
531
7189d17f 532 -----------------------------
533 -- Expand_Dispatching_Call --
534 -----------------------------
ee6ba406 535
7189d17f 536 procedure Expand_Dispatching_Call (Call_Node : Node_Id) is
ee6ba406 537 Loc : constant Source_Ptr := Sloc (Call_Node);
538 Call_Typ : constant Entity_Id := Etype (Call_Node);
539
2ea346ac 540 Ctrl_Arg : constant Node_Id := Controlling_Argument (Call_Node);
541 Ctrl_Typ : constant Entity_Id := Base_Type (Etype (Ctrl_Arg));
542 Param_List : constant List_Id := Parameter_Associations (Call_Node);
ee6ba406 543
af647dc7 544 Subp : Entity_Id;
7189d17f 545 CW_Typ : Entity_Id;
546 New_Call : Node_Id;
547 New_Call_Name : Node_Id;
548 New_Params : List_Id := No_List;
549 Param : Node_Id;
550 Res_Typ : Entity_Id;
551 Subp_Ptr_Typ : Entity_Id;
552 Subp_Typ : Entity_Id;
553 Typ : Entity_Id;
554 Eq_Prim_Op : Entity_Id := Empty;
555 Controlling_Tag : Node_Id;
ee6ba406 556
557 function New_Value (From : Node_Id) return Node_Id;
9dfe12ae 558 -- From is the original Expression. New_Value is equivalent to a call
559 -- to Duplicate_Subexpr with an explicit dereference when From is an
7189d17f 560 -- access parameter.
561
9dfe12ae 562 ---------------
563 -- New_Value --
564 ---------------
565
ee6ba406 566 function New_Value (From : Node_Id) return Node_Id is
567 Res : constant Node_Id := Duplicate_Subexpr (From);
ee6ba406 568 begin
569 if Is_Access_Type (Etype (From)) then
af647dc7 570 return
571 Make_Explicit_Dereference (Sloc (From),
572 Prefix => Res);
ee6ba406 573 else
574 return Res;
575 end if;
576 end New_Value;
577
7189d17f 578 -- Start of processing for Expand_Dispatching_Call
ee6ba406 579
580 begin
725a69d2 581 if No_Run_Time_Mode then
582 Error_Msg_CRT ("tagged types", Call_Node);
583 return;
584 end if;
585
343d35dc 586 -- Expand_Dispatching_Call is called directly from the semantics,
587 -- so we need a check to see whether expansion is active before
588 -- proceeding. In addition, there is no need to expand the call
589 -- if we are compiling under restriction No_Dispatching_Calls;
590 -- the semantic analyzer has previously notified the violation
591 -- of this restriction.
592
593 if not Expander_Active
594 or else Restriction_Active (No_Dispatching_Calls)
595 then
596 return;
597 end if;
68f95949 598
af647dc7 599 -- Set subprogram. If this is an inherited operation that was
600 -- overridden, the body that is being called is its alias.
601
602 Subp := Entity (Name (Call_Node));
ee6ba406 603
604 if Present (Alias (Subp))
605 and then Is_Inherited_Operation (Subp)
606 and then No (DTC_Entity (Subp))
607 then
608 Subp := Alias (Subp);
609 end if;
610
7189d17f 611 -- Definition of the class-wide type and the tagged type
ee6ba406 612
7189d17f 613 -- If the controlling argument is itself a tag rather than a tagged
614 -- object, then use the class-wide type associated with the subprogram's
615 -- controlling type. This case can occur when a call to an inherited
616 -- primitive has an actual that originated from a default parameter
617 -- given by a tag-indeterminate call and when there is no other
618 -- controlling argument providing the tag (AI-239 requires dispatching).
619 -- This capability of dispatching directly by tag is also needed by the
620 -- implementation of AI-260 (for the generic dispatching constructors).
621
2ea346ac 622 if Ctrl_Typ = RTE (RE_Tag)
68f95949 623 or else (RTE_Available (RE_Interface_Tag)
2ea346ac 624 and then Ctrl_Typ = RTE (RE_Interface_Tag))
aad6babd 625 then
af647dc7 626 CW_Typ := Class_Wide_Type (Find_Dispatching_Type (Subp));
7189d17f 627
725a69d2 628 -- Class_Wide_Type is applied to the expressions used to initialize
629 -- CW_Typ, to ensure that CW_Typ always denotes a class-wide type, since
630 -- there are cases where the controlling type is resolved to a specific
631 -- type (such as for designated types of arguments such as CW'Access).
632
2ea346ac 633 elsif Is_Access_Type (Ctrl_Typ) then
634 CW_Typ := Class_Wide_Type (Designated_Type (Ctrl_Typ));
7189d17f 635
ee6ba406 636 else
2ea346ac 637 CW_Typ := Class_Wide_Type (Ctrl_Typ);
ee6ba406 638 end if;
639
640 Typ := Root_Type (CW_Typ);
641
d62940bf 642 if Ekind (Typ) = E_Incomplete_Type then
643 Typ := Non_Limited_View (Typ);
644 end if;
645
9af28f61 646 -- Comment needed ???
647
3dbca0d5 648 if Generate_SCIL then
649 Insert_Action (Call_Node,
650 New_Scil_Node
651 (Nkind => Dispatching_Call,
652 Related_Node => Call_Node,
653 Entity => Typ,
654 Target_Prim => Subp));
655 end if;
656
ee6ba406 657 if not Is_Limited_Type (Typ) then
658 Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
659 end if;
660
343d35dc 661 -- Dispatching call to C++ primitive. Create a new parameter list
662 -- with no tag checks.
ee6ba406 663
cd534f03 664 New_Params := New_List;
665
343d35dc 666 if Is_CPP_Class (Typ) then
ee6ba406 667 Param := First_Actual (Call_Node);
668 while Present (Param) loop
aad6babd 669 Append_To (New_Params, Relocate_Node (Param));
ee6ba406 670 Next_Actual (Param);
671 end loop;
672
343d35dc 673 -- Dispatching call to Ada primitive
674
ee6ba406 675 elsif Present (Param_List) then
cd534f03 676 Apply_Tag_Checks (Call_Node);
ee6ba406 677
ee6ba406 678 Param := First_Actual (Call_Node);
679 while Present (Param) loop
cd534f03 680 -- Cases in which we may have generated runtime checks
ee6ba406 681
cd534f03 682 if Param = Ctrl_Arg
683 or else Subp = Eq_Prim_Op
684 then
9dfe12ae 685 Append_To (New_Params,
686 Duplicate_Subexpr_Move_Checks (Param));
ee6ba406 687
ee6ba406 688 else
ee6ba406 689 Append_To (New_Params, Relocate_Node (Param));
690 end if;
691
692 Next_Actual (Param);
693 end loop;
694 end if;
695
696 -- Generate the appropriate subprogram pointer type
697
68f95949 698 if Etype (Subp) = Typ then
ee6ba406 699 Res_Typ := CW_Typ;
700 else
7189d17f 701 Res_Typ := Etype (Subp);
ee6ba406 702 end if;
703
b6b96867 704 Subp_Typ := Create_Itype (E_Subprogram_Type, Call_Node);
ee6ba406 705 Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node);
706 Set_Etype (Subp_Typ, Res_Typ);
ee6ba406 707 Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp));
708
709 -- Create a new list of parameters which is a copy of the old formal
710 -- list including the creation of a new set of matching entities.
711
712 declare
713 Old_Formal : Entity_Id := First_Formal (Subp);
714 New_Formal : Entity_Id;
725a69d2 715 Extra : Entity_Id := Empty;
ee6ba406 716
717 begin
718 if Present (Old_Formal) then
719 New_Formal := New_Copy (Old_Formal);
720 Set_First_Entity (Subp_Typ, New_Formal);
721 Param := First_Actual (Call_Node);
722
723 loop
724 Set_Scope (New_Formal, Subp_Typ);
725
726 -- Change all the controlling argument types to be class-wide
7189d17f 727 -- to avoid a recursion in dispatching.
ee6ba406 728
7189d17f 729 if Is_Controlling_Formal (New_Formal) then
ee6ba406 730 Set_Etype (New_Formal, Etype (Param));
731 end if;
732
cc60bd16 733 -- If the type of the formal is an itype, there was code here
734 -- introduced in 1998 in revision 1.46, to create a new itype
735 -- by copy. This seems useless, and in fact leads to semantic
736 -- errors when the itype is the completion of a type derived
737 -- from a private type.
ee6ba406 738
739 Extra := New_Formal;
740 Next_Formal (Old_Formal);
741 exit when No (Old_Formal);
742
743 Set_Next_Entity (New_Formal, New_Copy (Old_Formal));
744 Next_Entity (New_Formal);
745 Next_Actual (Param);
746 end loop;
af647dc7 747
748 Set_Next_Entity (New_Formal, Empty);
ee6ba406 749 Set_Last_Entity (Subp_Typ, Extra);
725a69d2 750 end if;
ee6ba406 751
725a69d2 752 -- Now that the explicit formals have been duplicated, any extra
753 -- formals needed by the subprogram must be created.
ee6ba406 754
725a69d2 755 if Present (Extra) then
756 Set_Extra_Formal (Extra, Empty);
ee6ba406 757 end if;
725a69d2 758
759 Create_Extra_Formals (Subp_Typ);
ee6ba406 760 end;
761
b6b96867 762 -- Complete description of pointer type, including size information, as
763 -- must be done with itypes to prevent order-of-elaboration anomalies
764 -- in gigi.
765
ee6ba406 766 Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
767 Set_Directly_Designated_Type (Subp_Ptr_Typ, Subp_Typ);
acf97c11 768 Set_Convention (Subp_Ptr_Typ, Convention (Subp_Typ));
b6b96867 769 Layout_Type (Subp_Ptr_Typ);
ee6ba406 770
68f95949 771 -- If the controlling argument is a value of type Ada.Tag or an abstract
772 -- interface class-wide type then use it directly. Otherwise, the tag
773 -- must be extracted from the controlling object.
7189d17f 774
2ea346ac 775 if Ctrl_Typ = RTE (RE_Tag)
68f95949 776 or else (RTE_Available (RE_Interface_Tag)
2ea346ac 777 and then Ctrl_Typ = RTE (RE_Interface_Tag))
68f95949 778 then
779 Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
780
343d35dc 781 -- Extract the tag from an unchecked type conversion. Done to avoid
782 -- the expansion of additional code just to obtain the value of such
783 -- tag because the current management of interface type conversions
784 -- generates in some cases this unchecked type conversion with the
785 -- tag of the object (see Expand_Interface_Conversion).
786
787 elsif Nkind (Ctrl_Arg) = N_Unchecked_Type_Conversion
788 and then
789 (Etype (Expression (Ctrl_Arg)) = RTE (RE_Tag)
790 or else
791 (RTE_Available (RE_Interface_Tag)
792 and then
793 Etype (Expression (Ctrl_Arg)) = RTE (RE_Interface_Tag)))
794 then
795 Controlling_Tag := Duplicate_Subexpr (Expression (Ctrl_Arg));
796
68f95949 797 -- Ada 2005 (AI-251): Abstract interface class-wide type
798
2ea346ac 799 elsif Is_Interface (Ctrl_Typ)
800 and then Is_Class_Wide_Type (Ctrl_Typ)
aad6babd 801 then
7189d17f 802 Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
803
804 else
805 Controlling_Tag :=
806 Make_Selected_Component (Loc,
807 Prefix => Duplicate_Subexpr_Move_Checks (Ctrl_Arg),
808 Selector_Name => New_Reference_To (DTC_Entity (Subp), Loc));
809 end if;
810
343d35dc 811 -- Handle dispatching calls to predefined primitives
ee6ba406 812
af647dc7 813 if Is_Predefined_Dispatching_Operation (Subp)
814 or else Is_Predefined_Dispatching_Alias (Subp)
815 then
68f95949 816 New_Call_Name :=
817 Unchecked_Convert_To (Subp_Ptr_Typ,
343d35dc 818 Build_Get_Predefined_Prim_Op_Address (Loc,
819 Tag_Node => Controlling_Tag,
725a69d2 820 Position => DT_Position (Subp)));
ee6ba406 821
343d35dc 822 -- Handle dispatching calls to user-defined primitives
68f95949 823
824 else
825 New_Call_Name :=
826 Unchecked_Convert_To (Subp_Ptr_Typ,
343d35dc 827 Build_Get_Prim_Op_Address (Loc,
725a69d2 828 Typ => Find_Dispatching_Type (Subp),
829 Tag_Node => Controlling_Tag,
830 Position => DT_Position (Subp)));
68f95949 831 end if;
ee6ba406 832
833 if Nkind (Call_Node) = N_Function_Call then
ee6ba406 834
725a69d2 835 New_Call :=
836 Make_Function_Call (Loc,
837 Name => New_Call_Name,
838 Parameter_Associations => New_Params);
ee6ba406 839
725a69d2 840 -- If this is a dispatching "=", we must first compare the tags so
841 -- we generate: x.tag = y.tag and then x = y
ee6ba406 842
725a69d2 843 if Subp = Eq_Prim_Op then
844 Param := First_Actual (Call_Node);
aad6babd 845 New_Call :=
725a69d2 846 Make_And_Then (Loc,
847 Left_Opnd =>
848 Make_Op_Eq (Loc,
849 Left_Opnd =>
850 Make_Selected_Component (Loc,
851 Prefix => New_Value (Param),
852 Selector_Name =>
853 New_Reference_To (First_Tag_Component (Typ),
854 Loc)),
ee6ba406 855
725a69d2 856 Right_Opnd =>
857 Make_Selected_Component (Loc,
858 Prefix =>
859 Unchecked_Convert_To (Typ,
860 New_Value (Next_Actual (Param))),
861 Selector_Name =>
862 New_Reference_To (First_Tag_Component (Typ),
863 Loc))),
864 Right_Opnd => New_Call);
ee6ba406 865 end if;
866
867 else
868 New_Call :=
869 Make_Procedure_Call_Statement (Loc,
870 Name => New_Call_Name,
871 Parameter_Associations => New_Params);
872 end if;
873
874 Rewrite (Call_Node, New_Call);
725a69d2 875
876 -- Suppress all checks during the analysis of the expanded code
36b938a3 877 -- to avoid the generation of spurious warnings under ZFP run-time.
725a69d2 878
879 Analyze_And_Resolve (Call_Node, Call_Typ, Suppress => All_Checks);
7189d17f 880 end Expand_Dispatching_Call;
ee6ba406 881
aad6babd 882 ---------------------------------
883 -- Expand_Interface_Conversion --
884 ---------------------------------
885
952af0b9 886 procedure Expand_Interface_Conversion
887 (N : Node_Id;
888 Is_Static : Boolean := True)
889 is
aad6babd 890 Loc : constant Source_Ptr := Sloc (N);
af647dc7 891 Etyp : constant Entity_Id := Etype (N);
aad6babd 892 Operand : constant Node_Id := Expression (N);
893 Operand_Typ : Entity_Id := Etype (Operand);
d62940bf 894 Func : Node_Id;
af647dc7 895 Iface_Typ : Entity_Id := Etype (N);
896 Iface_Tag : Entity_Id;
aad6babd 897
898 begin
343d35dc 899 -- Ada 2005 (AI-345): Handle synchronized interface type derivations
aad6babd 900
343d35dc 901 if Is_Concurrent_Type (Operand_Typ) then
902 Operand_Typ := Base_Type (Corresponding_Record_Type (Operand_Typ));
aad6babd 903 end if;
904
e7e688dd 905 -- Handle access to class-wide interface types
aad6babd 906
d62940bf 907 if Is_Access_Type (Iface_Typ) then
908 Iface_Typ := Etype (Directly_Designated_Type (Iface_Typ));
aad6babd 909 end if;
910
d62940bf 911 -- Handle class-wide interface types. This conversion can appear
912 -- explicitly in the source code. Example: I'Class (Obj)
aad6babd 913
d62940bf 914 if Is_Class_Wide_Type (Iface_Typ) then
725a69d2 915 Iface_Typ := Root_Type (Iface_Typ);
d62940bf 916 end if;
917
79a72728 918 -- If the target type is a tagged synchronized type, the dispatch table
bf3e1520 919 -- info is in the corresponding record type.
79a72728 920
921 if Is_Concurrent_Type (Iface_Typ) then
922 Iface_Typ := Corresponding_Record_Type (Iface_Typ);
923 end if;
924
a17cc77d 925 -- Freeze the entity associated with the target interface to have
926 -- available the attribute Access_Disp_Table.
927
928 Freeze_Before (N, Iface_Typ);
929
af647dc7 930 pragma Assert (not Is_Static
931 or else (not Is_Class_Wide_Type (Iface_Typ)
932 and then Is_Interface (Iface_Typ)));
aad6babd 933
662256db 934 if not Tagged_Type_Expansion then
725a69d2 935
936 -- For VM, just do a conversion ???
937
938 Rewrite (N, Unchecked_Convert_To (Etype (N), N));
939 Analyze (N);
940 return;
941 end if;
942
952af0b9 943 if not Is_Static then
68f95949 944
945 -- Give error if configurable run time and Displace not available
946
947 if not RTE_Available (RE_Displace) then
cc60bd16 948 Error_Msg_CRT ("dynamic interface conversion", N);
68f95949 949 return;
950 end if;
951
725a69d2 952 -- Handle conversion of access-to-class-wide interface types. Target
953 -- can be an access to an object or an access to another class-wide
954 -- interface (see -1- and -2- in the following example):
af647dc7 955
956 -- type Iface1_Ref is access all Iface1'Class;
957 -- type Iface2_Ref is access all Iface1'Class;
958
959 -- Acc1 : Iface1_Ref := new ...
960 -- Obj : Obj_Ref := Obj_Ref (Acc); -- 1
961 -- Acc2 : Iface2_Ref := Iface2_Ref (Acc); -- 2
962
963 if Is_Access_Type (Operand_Typ) then
af647dc7 964 Rewrite (N,
965 Unchecked_Convert_To (Etype (N),
966 Make_Function_Call (Loc,
967 Name => New_Reference_To (RTE (RE_Displace), Loc),
968 Parameter_Associations => New_List (
969
970 Unchecked_Convert_To (RTE (RE_Address),
971 Relocate_Node (Expression (N))),
972
973 New_Occurrence_Of
974 (Node (First_Elmt (Access_Disp_Table (Iface_Typ))),
975 Loc)))));
976
977 Analyze (N);
978 return;
979 end if;
980
952af0b9 981 Rewrite (N,
982 Make_Function_Call (Loc,
983 Name => New_Reference_To (RTE (RE_Displace), Loc),
984 Parameter_Associations => New_List (
985 Make_Attribute_Reference (Loc,
986 Prefix => Relocate_Node (Expression (N)),
987 Attribute_Name => Name_Address),
af647dc7 988
952af0b9 989 New_Occurrence_Of
990 (Node (First_Elmt (Access_Disp_Table (Iface_Typ))),
991 Loc))));
992
993 Analyze (N);
994
af647dc7 995 -- If the target is a class-wide interface we change the type of the
996 -- data returned by IW_Convert to indicate that this is a dispatching
997 -- call.
952af0b9 998
17e14451 999 declare
1000 New_Itype : Entity_Id;
952af0b9 1001
17e14451 1002 begin
1003 New_Itype := Create_Itype (E_Anonymous_Access_Type, N);
cc60bd16 1004 Set_Etype (New_Itype, New_Itype);
17e14451 1005 Set_Directly_Designated_Type (New_Itype, Etyp);
952af0b9 1006
17e14451 1007 Rewrite (N,
1008 Make_Explicit_Dereference (Loc,
1009 Prefix =>
1010 Unchecked_Convert_To (New_Itype, Relocate_Node (N))));
1011 Analyze (N);
1012 Freeze_Itype (New_Itype, N);
1013
1014 return;
1015 end;
952af0b9 1016 end if;
1017
d62940bf 1018 Iface_Tag := Find_Interface_Tag (Operand_Typ, Iface_Typ);
aad6babd 1019 pragma Assert (Iface_Tag /= Empty);
1020
d62940bf 1021 -- Keep separate access types to interfaces because one internal
1022 -- function is used to handle the null value (see following comment)
1023
1024 if not Is_Access_Type (Etype (N)) then
1025 Rewrite (N,
1026 Unchecked_Convert_To (Etype (N),
1027 Make_Selected_Component (Loc,
1028 Prefix => Relocate_Node (Expression (N)),
1029 Selector_Name =>
1030 New_Occurrence_Of (Iface_Tag, Loc))));
1031
1032 else
1033 -- Build internal function to handle the case in which the
1034 -- actual is null. If the actual is null returns null because
1035 -- no displacement is required; otherwise performs a type
1036 -- conversion that will be expanded in the code that returns
1037 -- the value of the displaced actual. That is:
1038
af647dc7 1039 -- function Func (O : Address) return Iface_Typ is
17e14451 1040 -- type Op_Typ is access all Operand_Typ;
1041 -- Aux : Op_Typ := To_Op_Typ (O);
d62940bf 1042 -- begin
af647dc7 1043 -- if O = Null_Address then
d62940bf 1044 -- return null;
1045 -- else
17e14451 1046 -- return Iface_Typ!(Aux.Iface_Tag'Address);
d62940bf 1047 -- end if;
1048 -- end Func;
1049
af647dc7 1050 declare
17e14451 1051 Desig_Typ : Entity_Id;
1052 Fent : Entity_Id;
1053 New_Typ_Decl : Node_Id;
17e14451 1054 Stats : List_Id;
1055
af647dc7 1056 begin
1057 Desig_Typ := Etype (Expression (N));
d62940bf 1058
af647dc7 1059 if Is_Access_Type (Desig_Typ) then
865909d3 1060 Desig_Typ :=
1061 Available_View (Directly_Designated_Type (Desig_Typ));
af647dc7 1062 end if;
d62940bf 1063
e7e688dd 1064 if Is_Concurrent_Type (Desig_Typ) then
1065 Desig_Typ := Base_Type (Corresponding_Record_Type (Desig_Typ));
1066 end if;
1067
17e14451 1068 New_Typ_Decl :=
1069 Make_Full_Type_Declaration (Loc,
1070 Defining_Identifier =>
1071 Make_Defining_Identifier (Loc, New_Internal_Name ('T')),
1072 Type_Definition =>
1073 Make_Access_To_Object_Definition (Loc,
1074 All_Present => True,
1075 Null_Exclusion_Present => False,
1076 Constant_Present => False,
1077 Subtype_Indication =>
1078 New_Reference_To (Desig_Typ, Loc)));
d62940bf 1079
725a69d2 1080 Stats := New_List (
17e14451 1081 Make_Simple_Return_Statement (Loc,
1082 Unchecked_Convert_To (Etype (N),
1083 Make_Attribute_Reference (Loc,
1084 Prefix =>
1085 Make_Selected_Component (Loc,
1086 Prefix =>
e7e688dd 1087 Unchecked_Convert_To
1088 (Defining_Identifier (New_Typ_Decl),
1089 Make_Identifier (Loc, Name_uO)),
17e14451 1090 Selector_Name =>
1091 New_Occurrence_Of (Iface_Tag, Loc)),
1092 Attribute_Name => Name_Address))));
725a69d2 1093
17e14451 1094 -- If the type is null-excluding, no need for the null branch.
1095 -- Otherwise we need to check for it and return null.
1096
1097 if not Can_Never_Be_Null (Etype (N)) then
1098 Stats := New_List (
1099 Make_If_Statement (Loc,
1100 Condition =>
1101 Make_Op_Eq (Loc,
1102 Left_Opnd => Make_Identifier (Loc, Name_uO),
1103 Right_Opnd => New_Reference_To
1104 (RTE (RE_Null_Address), Loc)),
1105
1106 Then_Statements => New_List (
1107 Make_Simple_Return_Statement (Loc,
1108 Make_Null (Loc))),
1109 Else_Statements => Stats));
1110 end if;
d62940bf 1111
17e14451 1112 Fent :=
1113 Make_Defining_Identifier (Loc,
1114 New_Internal_Name ('F'));
af647dc7 1115
17e14451 1116 Func :=
1117 Make_Subprogram_Body (Loc,
1118 Specification =>
1119 Make_Function_Specification (Loc,
1120 Defining_Unit_Name => Fent,
d62940bf 1121
17e14451 1122 Parameter_Specifications => New_List (
1123 Make_Parameter_Specification (Loc,
1124 Defining_Identifier =>
1125 Make_Defining_Identifier (Loc, Name_uO),
1126 Parameter_Type =>
1127 New_Reference_To (RTE (RE_Address), Loc))),
d62940bf 1128
17e14451 1129 Result_Definition =>
1130 New_Reference_To (Etype (N), Loc)),
d62940bf 1131
e7e688dd 1132 Declarations => New_List (New_Typ_Decl),
d62940bf 1133
17e14451 1134 Handled_Statement_Sequence =>
1135 Make_Handled_Sequence_Of_Statements (Loc, Stats));
d62940bf 1136
17e14451 1137 -- Place function body before the expression containing the
1138 -- conversion. We suppress all checks because the body of the
1139 -- internally generated function already takes care of the case
1140 -- in which the actual is null; therefore there is no need to
1141 -- double check that the pointer is not null when the program
1142 -- executes the alternative that performs the type conversion).
af647dc7 1143
17e14451 1144 Insert_Action (N, Func, Suppress => All_Checks);
af647dc7 1145
17e14451 1146 if Is_Access_Type (Etype (Expression (N))) then
af647dc7 1147
e7e688dd 1148 -- Generate: Func (Address!(Expression))
af647dc7 1149
17e14451 1150 Rewrite (N,
1151 Make_Function_Call (Loc,
1152 Name => New_Reference_To (Fent, Loc),
1153 Parameter_Associations => New_List (
e7e688dd 1154 Unchecked_Convert_To (RTE (RE_Address),
1155 Relocate_Node (Expression (N))))));
17e14451 1156
1157 else
e7e688dd 1158 -- Generate: Func (Operand_Typ!(Expression)'Address)
17e14451 1159
1160 Rewrite (N,
1161 Make_Function_Call (Loc,
1162 Name => New_Reference_To (Fent, Loc),
1163 Parameter_Associations => New_List (
1164 Make_Attribute_Reference (Loc,
1165 Prefix => Unchecked_Convert_To (Operand_Typ,
1166 Relocate_Node (Expression (N))),
1167 Attribute_Name => Name_Address))));
1168 end if;
1169 end;
d62940bf 1170 end if;
aad6babd 1171
1172 Analyze (N);
1173 end Expand_Interface_Conversion;
1174
1175 ------------------------------
1176 -- Expand_Interface_Actuals --
1177 ------------------------------
1178
1179 procedure Expand_Interface_Actuals (Call_Node : Node_Id) is
aad6babd 1180 Actual : Node_Id;
d62940bf 1181 Actual_Dup : Node_Id;
aad6babd 1182 Actual_Typ : Entity_Id;
d62940bf 1183 Anon : Entity_Id;
aad6babd 1184 Conversion : Node_Id;
1185 Formal : Entity_Id;
1186 Formal_Typ : Entity_Id;
1187 Subp : Entity_Id;
d62940bf 1188 Formal_DDT : Entity_Id;
1189 Actual_DDT : Entity_Id;
aad6babd 1190
1191 begin
1192 -- This subprogram is called directly from the semantics, so we need a
1193 -- check to see whether expansion is active before proceeding.
1194
1195 if not Expander_Active then
1196 return;
1197 end if;
1198
1199 -- Call using access to subprogram with explicit dereference
1200
1201 if Nkind (Name (Call_Node)) = N_Explicit_Dereference then
1202 Subp := Etype (Name (Call_Node));
1203
4e5db562 1204 -- Call using selected component
1205
1206 elsif Nkind (Name (Call_Node)) = N_Selected_Component then
1207 Subp := Entity (Selector_Name (Name (Call_Node)));
1208
1209 -- Call using direct name
aad6babd 1210
1211 else
1212 Subp := Entity (Name (Call_Node));
1213 end if;
1214
725a69d2 1215 -- Ada 2005 (AI-251): Look for interface type formals to force "this"
1216 -- displacement
1217
aad6babd 1218 Formal := First_Formal (Subp);
1219 Actual := First_Actual (Call_Node);
aad6babd 1220 while Present (Formal) loop
725a69d2 1221 Formal_Typ := Etype (Formal);
d62940bf 1222
1223 if Ekind (Formal_Typ) = E_Record_Type_With_Private then
1224 Formal_Typ := Full_View (Formal_Typ);
1225 end if;
1226
1227 if Is_Access_Type (Formal_Typ) then
1228 Formal_DDT := Directly_Designated_Type (Formal_Typ);
1229 end if;
1230
aad6babd 1231 Actual_Typ := Etype (Actual);
1232
d62940bf 1233 if Is_Access_Type (Actual_Typ) then
1234 Actual_DDT := Directly_Designated_Type (Actual_Typ);
1235 end if;
1236
725a69d2 1237 if Is_Interface (Formal_Typ)
1238 and then Is_Class_Wide_Type (Formal_Typ)
1239 then
d62940bf 1240 -- No need to displace the pointer if the type of the actual
725a69d2 1241 -- coindices with the type of the formal.
aad6babd 1242
725a69d2 1243 if Actual_Typ = Formal_Typ then
d62940bf 1244 null;
1245
725a69d2 1246 -- No need to displace the pointer if the interface type is
1247 -- a parent of the type of the actual because in this case the
1248 -- interface primitives are located in the primary dispatch table.
aad6babd 1249
a652dd51 1250 elsif Is_Ancestor (Formal_Typ, Actual_Typ) then
d62940bf 1251 null;
1252
725a69d2 1253 -- Implicit conversion to the class-wide formal type to force
1254 -- the displacement of the pointer.
1255
d62940bf 1256 else
1257 Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual));
725a69d2 1258 Rewrite (Actual, Conversion);
d62940bf 1259 Analyze_And_Resolve (Actual, Formal_Typ);
1260 end if;
aad6babd 1261
725a69d2 1262 -- Access to class-wide interface type
aad6babd 1263
1264 elsif Is_Access_Type (Formal_Typ)
725a69d2 1265 and then Is_Interface (Formal_DDT)
1266 and then Is_Class_Wide_Type (Formal_DDT)
aad6babd 1267 and then Interface_Present_In_Ancestor
d62940bf 1268 (Typ => Actual_DDT,
1269 Iface => Etype (Formal_DDT))
aad6babd 1270 then
725a69d2 1271 -- Handle attributes 'Access and 'Unchecked_Access
1272
aad6babd 1273 if Nkind (Actual) = N_Attribute_Reference
1274 and then
1275 (Attribute_Name (Actual) = Name_Access
1276 or else Attribute_Name (Actual) = Name_Unchecked_Access)
1277 then
5e82d8fe 1278 -- This case must have been handled by the analysis and
1279 -- expansion of 'Access. The only exception is when types
1280 -- match and no further expansion is required.
aad6babd 1281
5e82d8fe 1282 pragma Assert (Base_Type (Etype (Prefix (Actual)))
1283 = Base_Type (Formal_DDT));
1284 null;
aad6babd 1285
725a69d2 1286 -- No need to displace the pointer if the type of the actual
1287 -- coincides with the type of the formal.
d62940bf 1288
725a69d2 1289 elsif Actual_DDT = Formal_DDT then
d62940bf 1290 null;
1291
725a69d2 1292 -- No need to displace the pointer if the interface type is
1293 -- a parent of the type of the actual because in this case the
1294 -- interface primitives are located in the primary dispatch table.
d62940bf 1295
a652dd51 1296 elsif Is_Ancestor (Formal_DDT, Actual_DDT) then
d62940bf 1297 null;
1298
aad6babd 1299 else
d62940bf 1300 Actual_Dup := Relocate_Node (Actual);
1301
1302 if From_With_Type (Actual_Typ) then
1303
1304 -- If the type of the actual parameter comes from a limited
1305 -- with-clause and the non-limited view is already available
9ced80be 1306 -- we replace the anonymous access type by a duplicate
1307 -- declaration whose designated type is the non-limited view
d62940bf 1308
1309 if Ekind (Actual_DDT) = E_Incomplete_Type
1310 and then Present (Non_Limited_View (Actual_DDT))
1311 then
1312 Anon := New_Copy (Actual_Typ);
1313
1314 if Is_Itype (Anon) then
1315 Set_Scope (Anon, Current_Scope);
1316 end if;
1317
1318 Set_Directly_Designated_Type (Anon,
1319 Non_Limited_View (Actual_DDT));
1320 Set_Etype (Actual_Dup, Anon);
1321
1322 elsif Is_Class_Wide_Type (Actual_DDT)
1323 and then Ekind (Etype (Actual_DDT)) = E_Incomplete_Type
1324 and then Present (Non_Limited_View (Etype (Actual_DDT)))
1325 then
1326 Anon := New_Copy (Actual_Typ);
1327
1328 if Is_Itype (Anon) then
1329 Set_Scope (Anon, Current_Scope);
1330 end if;
1331
1332 Set_Directly_Designated_Type (Anon,
1333 New_Copy (Actual_DDT));
1334 Set_Class_Wide_Type (Directly_Designated_Type (Anon),
1335 New_Copy (Class_Wide_Type (Actual_DDT)));
1336 Set_Etype (Directly_Designated_Type (Anon),
1337 Non_Limited_View (Etype (Actual_DDT)));
1338 Set_Etype (
1339 Class_Wide_Type (Directly_Designated_Type (Anon)),
1340 Non_Limited_View (Etype (Actual_DDT)));
1341 Set_Etype (Actual_Dup, Anon);
1342 end if;
1343 end if;
1344
1345 Conversion := Convert_To (Formal_Typ, Actual_Dup);
1346 Rewrite (Actual, Conversion);
aad6babd 1347 Analyze_And_Resolve (Actual, Formal_Typ);
1348 end if;
1349 end if;
1350
1351 Next_Actual (Actual);
1352 Next_Formal (Formal);
1353 end loop;
1354 end Expand_Interface_Actuals;
1355
1356 ----------------------------
1357 -- Expand_Interface_Thunk --
1358 ----------------------------
1359
725a69d2 1360 procedure Expand_Interface_Thunk
17e14451 1361 (Prim : Node_Id;
1362 Thunk_Id : out Entity_Id;
1363 Thunk_Code : out Node_Id)
aad6babd 1364 is
17e14451 1365 Loc : constant Source_Ptr := Sloc (Prim);
725a69d2 1366 Actuals : constant List_Id := New_List;
1367 Decl : constant List_Id := New_List;
1368 Formals : constant List_Id := New_List;
1369
1370 Controlling_Typ : Entity_Id;
1371 Decl_1 : Node_Id;
1372 Decl_2 : Node_Id;
1373 Formal : Node_Id;
cc60bd16 1374 New_Arg : Node_Id;
1375 Offset_To_Top : Node_Id;
725a69d2 1376 Target : Entity_Id;
1377 Target_Formal : Entity_Id;
aad6babd 1378
1379 begin
725a69d2 1380 Thunk_Id := Empty;
1381 Thunk_Code := Empty;
1382
aad6babd 1383 -- Traverse the list of alias to find the final target
1384
17e14451 1385 Target := Prim;
aad6babd 1386 while Present (Alias (Target)) loop
1387 Target := Alias (Target);
1388 end loop;
1389
725a69d2 1390 -- In case of primitives that are functions without formals and
1391 -- a controlling result there is no need to build the thunk.
1392
1393 if not Present (First_Formal (Target)) then
1394 pragma Assert (Ekind (Target) = E_Function
1395 and then Has_Controlling_Result (Target));
1396 return;
1397 end if;
1398
aad6babd 1399 -- Duplicate the formals
1400
d62940bf 1401 Formal := First_Formal (Target);
aad6babd 1402 while Present (Formal) loop
725a69d2 1403 Append_To (Formals,
1404 Make_Parameter_Specification (Loc,
1405 Defining_Identifier =>
1406 Make_Defining_Identifier (Sloc (Formal),
1407 Chars => Chars (Formal)),
1408 In_Present => In_Present (Parent (Formal)),
1409 Out_Present => Out_Present (Parent (Formal)),
1410 Parameter_Type =>
1411 New_Reference_To (Etype (Formal), Loc),
1412 Expression => New_Copy_Tree (Expression (Parent (Formal)))));
d62940bf 1413
aad6babd 1414 Next_Formal (Formal);
1415 end loop;
1416
17e14451 1417 Controlling_Typ := Find_Dispatching_Type (Target);
aad6babd 1418
725a69d2 1419 Target_Formal := First_Formal (Target);
1420 Formal := First (Formals);
1421 while Present (Formal) loop
1422 if Ekind (Target_Formal) = E_In_Parameter
1423 and then Ekind (Etype (Target_Formal)) = E_Anonymous_Access_Type
1424 and then Directly_Designated_Type (Etype (Target_Formal))
1425 = Controlling_Typ
1426 then
1427 -- Generate:
aad6babd 1428
17e14451 1429 -- type T is access all <<type of the target formal>>
1430 -- S : Storage_Offset := Storage_Offset!(Formal)
1431 -- - Offset_To_Top (address!(Formal))
725a69d2 1432
1433 Decl_2 :=
1434 Make_Full_Type_Declaration (Loc,
1435 Defining_Identifier =>
1436 Make_Defining_Identifier (Loc,
1437 New_Internal_Name ('T')),
1438 Type_Definition =>
1439 Make_Access_To_Object_Definition (Loc,
1440 All_Present => True,
1441 Null_Exclusion_Present => False,
1442 Constant_Present => False,
1443 Subtype_Indication =>
aad6babd 1444 New_Reference_To
725a69d2 1445 (Directly_Designated_Type
1446 (Etype (Target_Formal)), Loc)));
1447
cc60bd16 1448 New_Arg :=
1449 Unchecked_Convert_To (RTE (RE_Address),
1450 New_Reference_To (Defining_Identifier (Formal), Loc));
1451
1452 if not RTE_Available (RE_Offset_To_Top) then
1453 Offset_To_Top :=
1454 Build_Offset_To_Top (Loc, New_Arg);
1455 else
1456 Offset_To_Top :=
1457 Make_Function_Call (Loc,
1458 Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc),
1459 Parameter_Associations => New_List (New_Arg));
1460 end if;
1461
725a69d2 1462 Decl_1 :=
1463 Make_Object_Declaration (Loc,
1464 Defining_Identifier =>
1465 Make_Defining_Identifier (Loc,
1466 New_Internal_Name ('S')),
1467 Constant_Present => True,
1468 Object_Definition =>
1469 New_Reference_To (RTE (RE_Storage_Offset), Loc),
1470 Expression =>
1471 Make_Op_Subtract (Loc,
1472 Left_Opnd =>
1473 Unchecked_Convert_To
1474 (RTE (RE_Storage_Offset),
1475 New_Reference_To (Defining_Identifier (Formal), Loc)),
1476 Right_Opnd =>
cc60bd16 1477 Offset_To_Top));
725a69d2 1478
1479 Append_To (Decl, Decl_2);
1480 Append_To (Decl, Decl_1);
1481
17e14451 1482 -- Reference the new actual. Generate:
1483 -- T!(S)
725a69d2 1484
1485 Append_To (Actuals,
1486 Unchecked_Convert_To
1487 (Defining_Identifier (Decl_2),
1488 New_Reference_To (Defining_Identifier (Decl_1), Loc)));
1489
1490 elsif Etype (Target_Formal) = Controlling_Typ then
1491 -- Generate:
aad6babd 1492
17e14451 1493 -- S1 : Storage_Offset := Storage_Offset!(Formal'Address)
1494 -- - Offset_To_Top (Formal'Address)
1495 -- S2 : Addr_Ptr := Addr_Ptr!(S1)
aad6babd 1496
cc60bd16 1497 New_Arg :=
1498 Make_Attribute_Reference (Loc,
1499 Prefix =>
1500 New_Reference_To (Defining_Identifier (Formal), Loc),
1501 Attribute_Name =>
1502 Name_Address);
1503
1504 if not RTE_Available (RE_Offset_To_Top) then
1505 Offset_To_Top :=
1506 Build_Offset_To_Top (Loc, New_Arg);
1507 else
1508 Offset_To_Top :=
1509 Make_Function_Call (Loc,
1510 Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc),
1511 Parameter_Associations => New_List (New_Arg));
1512 end if;
1513
725a69d2 1514 Decl_1 :=
1515 Make_Object_Declaration (Loc,
1516 Defining_Identifier =>
1517 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
1518 Constant_Present => True,
1519 Object_Definition =>
1520 New_Reference_To (RTE (RE_Storage_Offset), Loc),
1521 Expression =>
1522 Make_Op_Subtract (Loc,
1523 Left_Opnd =>
1524 Unchecked_Convert_To
1525 (RTE (RE_Storage_Offset),
1526 Make_Attribute_Reference (Loc,
1527 Prefix =>
1528 New_Reference_To
1529 (Defining_Identifier (Formal), Loc),
1530 Attribute_Name => Name_Address)),
1531 Right_Opnd =>
cc60bd16 1532 Offset_To_Top));
aad6babd 1533
725a69d2 1534 Decl_2 :=
1535 Make_Object_Declaration (Loc,
1536 Defining_Identifier =>
1537 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
1538 Constant_Present => True,
1539 Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc),
1540 Expression =>
1541 Unchecked_Convert_To
1542 (RTE (RE_Addr_Ptr),
1543 New_Reference_To (Defining_Identifier (Decl_1), Loc)));
aad6babd 1544
725a69d2 1545 Append_To (Decl, Decl_1);
1546 Append_To (Decl, Decl_2);
952af0b9 1547
17e14451 1548 -- Reference the new actual. Generate:
1549 -- Target_Formal (S2.all)
aad6babd 1550
725a69d2 1551 Append_To (Actuals,
1552 Unchecked_Convert_To
17e14451 1553 (Etype (Target_Formal),
725a69d2 1554 Make_Explicit_Dereference (Loc,
1555 New_Reference_To (Defining_Identifier (Decl_2), Loc))));
aad6babd 1556
725a69d2 1557 -- No special management required for this actual
aad6babd 1558
725a69d2 1559 else
1560 Append_To (Actuals,
1561 New_Reference_To (Defining_Identifier (Formal), Loc));
1562 end if;
1563
1564 Next_Formal (Target_Formal);
aad6babd 1565 Next (Formal);
1566 end loop;
1567
725a69d2 1568 Thunk_Id :=
1569 Make_Defining_Identifier (Loc,
1570 Chars => New_Internal_Name ('T'));
1571
e7e688dd 1572 Set_Is_Thunk (Thunk_Id);
1573
d62940bf 1574 if Ekind (Target) = E_Procedure then
725a69d2 1575 Thunk_Code :=
aad6babd 1576 Make_Subprogram_Body (Loc,
1577 Specification =>
1578 Make_Procedure_Specification (Loc,
1579 Defining_Unit_Name => Thunk_Id,
1580 Parameter_Specifications => Formals),
1581 Declarations => Decl,
1582 Handled_Statement_Sequence =>
1583 Make_Handled_Sequence_Of_Statements (Loc,
1584 Statements => New_List (
1585 Make_Procedure_Call_Statement (Loc,
725a69d2 1586 Name => New_Occurrence_Of (Target, Loc),
1587 Parameter_Associations => Actuals))));
aad6babd 1588
d62940bf 1589 else pragma Assert (Ekind (Target) = E_Function);
aad6babd 1590
725a69d2 1591 Thunk_Code :=
aad6babd 1592 Make_Subprogram_Body (Loc,
1593 Specification =>
1594 Make_Function_Specification (Loc,
1595 Defining_Unit_Name => Thunk_Id,
1596 Parameter_Specifications => Formals,
d62940bf 1597 Result_Definition =>
1598 New_Copy (Result_Definition (Parent (Target)))),
aad6babd 1599 Declarations => Decl,
1600 Handled_Statement_Sequence =>
1601 Make_Handled_Sequence_Of_Statements (Loc,
1602 Statements => New_List (
17e14451 1603 Make_Simple_Return_Statement (Loc,
aad6babd 1604 Make_Function_Call (Loc,
1605 Name => New_Occurrence_Of (Target, Loc),
1606 Parameter_Associations => Actuals)))));
1607 end if;
aad6babd 1608 end Expand_Interface_Thunk;
1609
3dbca0d5 1610 ------------------------
1611 -- Get_Scil_Node_Kind --
1612 ------------------------
1613
1614 function Get_Scil_Node_Kind (Node : Node_Id) return Scil_Node_Kind is
1615 begin
9af28f61 1616 pragma Assert
1617 (Nkind (Node) = N_Null_Statement and then Is_Scil_Node (Node));
3dbca0d5 1618 return Scil_Node_Kind'Val (UI_To_Int (Scil_Nkind (Node)));
1619 end Get_Scil_Node_Kind;
1620
24971415 1621 ------------
1622 -- Has_DT --
1623 ------------
1624
1625 function Has_DT (Typ : Entity_Id) return Boolean is
1626 begin
1627 return not Is_Interface (Typ)
1628 and then not Restriction_Active (No_Dispatching_Calls);
1629 end Has_DT;
1630
a652dd51 1631 -----------------------------------------
1632 -- Is_Predefined_Dispatching_Operation --
1633 -----------------------------------------
1634
1635 function Is_Predefined_Dispatching_Operation
1636 (E : Entity_Id) return Boolean
1637 is
1638 TSS_Name : TSS_Name_Type;
1639
1640 begin
1641 if not Is_Dispatching_Operation (E) then
1642 return False;
1643 end if;
1644
1645 Get_Name_String (Chars (E));
1646
1647 -- Most predefined primitives have internally generated names. Equality
1648 -- must be treated differently; the predefined operation is recognized
1649 -- as a homogeneous binary operator that returns Boolean.
1650
1651 if Name_Len > TSS_Name_Type'Last then
1652 TSS_Name := TSS_Name_Type (Name_Buffer (Name_Len - TSS_Name'Length + 1
1653 .. Name_Len));
1654 if Chars (E) = Name_uSize
1655 or else Chars (E) = Name_uAlignment
1656 or else TSS_Name = TSS_Stream_Read
1657 or else TSS_Name = TSS_Stream_Write
1658 or else TSS_Name = TSS_Stream_Input
1659 or else TSS_Name = TSS_Stream_Output
1660 or else
1661 (Chars (E) = Name_Op_Eq
1662 and then Etype (First_Entity (E)) = Etype (Last_Entity (E)))
1663 or else Chars (E) = Name_uAssign
1664 or else TSS_Name = TSS_Deep_Adjust
1665 or else TSS_Name = TSS_Deep_Finalize
1666 or else Is_Predefined_Interface_Primitive (E)
1667 then
1668 return True;
1669 end if;
1670 end if;
1671
1672 return False;
1673 end Is_Predefined_Dispatching_Operation;
1674
af647dc7 1675 -------------------------------------
1676 -- Is_Predefined_Dispatching_Alias --
1677 -------------------------------------
1678
1679 function Is_Predefined_Dispatching_Alias (Prim : Entity_Id) return Boolean
1680 is
1681 E : Entity_Id;
1682
1683 begin
1684 if not Is_Predefined_Dispatching_Operation (Prim)
1685 and then Present (Alias (Prim))
1686 then
1687 E := Prim;
1688 while Present (Alias (E)) loop
1689 E := Alias (E);
1690 end loop;
1691
1692 if Is_Predefined_Dispatching_Operation (E) then
1693 return True;
1694 end if;
1695 end if;
1696
1697 return False;
1698 end Is_Predefined_Dispatching_Alias;
1699
a652dd51 1700 ---------------------------------------
1701 -- Is_Predefined_Interface_Primitive --
1702 ---------------------------------------
1703
1704 function Is_Predefined_Interface_Primitive (E : Entity_Id) return Boolean is
1705 begin
1706 return Ada_Version >= Ada_05
1707 and then (Chars (E) = Name_uDisp_Asynchronous_Select or else
1708 Chars (E) = Name_uDisp_Conditional_Select or else
1709 Chars (E) = Name_uDisp_Get_Prim_Op_Kind or else
1710 Chars (E) = Name_uDisp_Get_Task_Id or else
1711 Chars (E) = Name_uDisp_Requeue or else
1712 Chars (E) = Name_uDisp_Timed_Select);
1713 end Is_Predefined_Interface_Primitive;
1714
76a1c25b 1715 ----------------------------------------
1716 -- Make_Disp_Asynchronous_Select_Body --
1717 ----------------------------------------
ee6ba406 1718
cdb1c38f 1719 -- For interface types, generate:
1720
1721 -- procedure _Disp_Asynchronous_Select
1722 -- (T : in out <Typ>;
1723 -- S : Integer;
1724 -- P : System.Address;
1725 -- B : out System.Storage_Elements.Dummy_Communication_Block;
1726 -- F : out Boolean)
1727 -- is
1728 -- begin
1729 -- null;
1730 -- end _Disp_Asynchronous_Select;
1731
1732 -- For protected types, generate:
1733
1734 -- procedure _Disp_Asynchronous_Select
1735 -- (T : in out <Typ>;
1736 -- S : Integer;
1737 -- P : System.Address;
1738 -- B : out System.Storage_Elements.Dummy_Communication_Block;
1739 -- F : out Boolean)
1740 -- is
1741 -- I : Integer :=
1742 -- Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP, S));
1743 -- Bnn : System.Tasking.Protected_Objects.Operations.
1744 -- Communication_Block;
1745 -- begin
1746 -- System.Tasking.Protected_Objects.Operations.Protected_Entry_Call
1747 -- (T._object'Access,
1748 -- System.Tasking.Protected_Objects.Protected_Entry_Index (I),
1749 -- P,
1750 -- System.Tasking.Asynchronous_Call,
1751 -- Bnn);
1752 -- B := System.Storage_Elements.Dummy_Communication_Block (Bnn);
1753 -- end _Disp_Asynchronous_Select;
1754
1755 -- For task types, generate:
1756
1757 -- procedure _Disp_Asynchronous_Select
1758 -- (T : in out <Typ>;
1759 -- S : Integer;
1760 -- P : System.Address;
1761 -- B : out System.Storage_Elements.Dummy_Communication_Block;
1762 -- F : out Boolean)
1763 -- is
1764 -- I : Integer :=
1765 -- Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP, S));
1766 -- begin
1767 -- System.Tasking.Rendezvous.Task_Entry_Call
1768 -- (T._task_id,
1769 -- System.Tasking.Task_Entry_Index (I),
1770 -- P,
1771 -- System.Tasking.Asynchronous_Call,
1772 -- F);
1773 -- end _Disp_Asynchronous_Select;
1774
76a1c25b 1775 function Make_Disp_Asynchronous_Select_Body
1776 (Typ : Entity_Id) return Node_Id
1777 is
725a69d2 1778 Com_Block : Entity_Id;
1779 Conc_Typ : Entity_Id := Empty;
1780 Decls : constant List_Id := New_List;
1781 DT_Ptr : Entity_Id;
1782 Loc : constant Source_Ptr := Sloc (Typ);
acf97c11 1783 Obj_Ref : Node_Id;
725a69d2 1784 Stmts : constant List_Id := New_List;
ee6ba406 1785
1786 begin
68f95949 1787 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
1788
952af0b9 1789 -- Null body is generated for interface types
1790
76a1c25b 1791 if Is_Interface (Typ) then
1792 return
1793 Make_Subprogram_Body (Loc,
1794 Specification =>
1795 Make_Disp_Asynchronous_Select_Spec (Typ),
1796 Declarations =>
1797 New_List,
1798 Handled_Statement_Sequence =>
1799 Make_Handled_Sequence_Of_Statements (Loc,
1800 New_List (Make_Null_Statement (Loc))));
9dfe12ae 1801 end if;
1802
76a1c25b 1803 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
aad6babd 1804
952af0b9 1805 if Is_Concurrent_Record_Type (Typ) then
1806 Conc_Typ := Corresponding_Concurrent_Type (Typ);
aad6babd 1807
76a1c25b 1808 -- Generate:
cdb1c38f 1809 -- I : Integer :=
1810 -- Ada.Tags.Get_Entry_Index (Ada.Tags.Tag! (<type>VP), S);
aad6babd 1811
76a1c25b 1812 -- where I will be used to capture the entry index of the primitive
1813 -- wrapper at position S.
aad6babd 1814
76a1c25b 1815 Append_To (Decls,
1816 Make_Object_Declaration (Loc,
1817 Defining_Identifier =>
1818 Make_Defining_Identifier (Loc, Name_uI),
1819 Object_Definition =>
1820 New_Reference_To (Standard_Integer, Loc),
1821 Expression =>
725a69d2 1822 Make_Function_Call (Loc,
cdb1c38f 1823 Name =>
1824 New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
1825 Parameter_Associations =>
1826 New_List (
1827 Unchecked_Convert_To (RTE (RE_Tag),
1828 New_Reference_To (DT_Ptr, Loc)),
1829 Make_Identifier (Loc, Name_uS)))));
aad6babd 1830
76a1c25b 1831 if Ekind (Conc_Typ) = E_Protected_Type then
aad6babd 1832
725a69d2 1833 -- Generate:
cdb1c38f 1834 -- Bnn : Communication_Block;
725a69d2 1835
1836 Com_Block :=
1837 Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
1838
1839 Append_To (Decls,
1840 Make_Object_Declaration (Loc,
1841 Defining_Identifier =>
1842 Com_Block,
1843 Object_Definition =>
1844 New_Reference_To (RTE (RE_Communication_Block), Loc)));
1845
acf97c11 1846 -- Build T._object'Access for calls below
aad6babd 1847
acf97c11 1848 Obj_Ref :=
1849 Make_Attribute_Reference (Loc,
1850 Attribute_Name => Name_Unchecked_Access,
1851 Prefix =>
1852 Make_Selected_Component (Loc,
1853 Prefix => Make_Identifier (Loc, Name_uT),
1854 Selector_Name => Make_Identifier (Loc, Name_uObject)));
aad6babd 1855
acf97c11 1856 case Corresponding_Runtime_Package (Conc_Typ) is
1857 when System_Tasking_Protected_Objects_Entries =>
aad6babd 1858
acf97c11 1859 -- Generate:
1860 -- Protected_Entry_Call
1861 -- (T._object'Access, -- Object
1862 -- Protected_Entry_Index! (I), -- E
1863 -- P, -- Uninterpreted_Data
1864 -- Asynchronous_Call, -- Mode
1865 -- Bnn); -- Communication_Block
1866
1867 -- where T is the protected object, I is the entry index, P
1868 -- is the wrapped parameters and B is the name of the
1869 -- communication block.
1870
1871 Append_To (Stmts,
1872 Make_Procedure_Call_Statement (Loc,
1873 Name =>
1874 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
1875 Parameter_Associations =>
1876 New_List (
1877 Obj_Ref,
aad6babd 1878
acf97c11 1879 Make_Unchecked_Type_Conversion (Loc, -- entry index
1880 Subtype_Mark =>
1881 New_Reference_To
1882 (RTE (RE_Protected_Entry_Index), Loc),
1883 Expression => Make_Identifier (Loc, Name_uI)),
d62940bf 1884
acf97c11 1885 Make_Identifier (Loc, Name_uP), -- parameter block
1886 New_Reference_To ( -- Asynchronous_Call
1887 RTE (RE_Asynchronous_Call), Loc),
1888
1889 New_Reference_To (Com_Block, Loc)))); -- comm block
1890
1891 when System_Tasking_Protected_Objects_Single_Entry =>
1892
1893 -- Generate:
1894 -- procedure Protected_Single_Entry_Call
1895 -- (Object : Protection_Entry_Access;
1896 -- Uninterpreted_Data : System.Address;
1897 -- Mode : Call_Modes);
725a69d2 1898
acf97c11 1899 Append_To (Stmts,
1900 Make_Procedure_Call_Statement (Loc,
1901 Name =>
1902 New_Reference_To
1903 (RTE (RE_Protected_Single_Entry_Call), Loc),
1904 Parameter_Associations =>
1905 New_List (
1906 Obj_Ref,
1907
1908 Make_Attribute_Reference (Loc,
1909 Prefix => Make_Identifier (Loc, Name_uP),
1910 Attribute_Name => Name_Address),
1911
1912 New_Reference_To
1913 (RTE (RE_Asynchronous_Call), Loc))));
1914
1915 when others =>
1916 raise Program_Error;
1917 end case;
725a69d2 1918
1919 -- Generate:
cdb1c38f 1920 -- B := Dummy_Communication_Block (Bnn);
725a69d2 1921
1922 Append_To (Stmts,
1923 Make_Assignment_Statement (Loc,
1924 Name =>
1925 Make_Identifier (Loc, Name_uB),
1926 Expression =>
1927 Make_Unchecked_Type_Conversion (Loc,
1928 Subtype_Mark =>
1929 New_Reference_To (
1930 RTE (RE_Dummy_Communication_Block), Loc),
1931 Expression =>
1932 New_Reference_To (Com_Block, Loc))));
1933
76a1c25b 1934 else
1935 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
d62940bf 1936
76a1c25b 1937 -- Generate:
cdb1c38f 1938 -- Task_Entry_Call
1939 -- (T._task_id, -- Acceptor
1940 -- Task_Entry_Index! (I), -- E
1941 -- P, -- Uninterpreted_Data
1942 -- Asynchronous_Call, -- Mode
1943 -- F); -- Rendezvous_Successful
ee6ba406 1944
acf97c11 1945 -- where T is the task object, I is the entry index, P is the
76a1c25b 1946 -- wrapped parameters and F is the status flag.
ee6ba406 1947
76a1c25b 1948 Append_To (Stmts,
1949 Make_Procedure_Call_Statement (Loc,
1950 Name =>
1951 New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
1952 Parameter_Associations =>
1953 New_List (
76a1c25b 1954 Make_Selected_Component (Loc, -- T._task_id
1955 Prefix =>
1956 Make_Identifier (Loc, Name_uT),
1957 Selector_Name =>
1958 Make_Identifier (Loc, Name_uTask_Id)),
ee6ba406 1959
76a1c25b 1960 Make_Unchecked_Type_Conversion (Loc, -- entry index
1961 Subtype_Mark =>
1962 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
1963 Expression =>
1964 Make_Identifier (Loc, Name_uI)),
ee6ba406 1965
76a1c25b 1966 Make_Identifier (Loc, Name_uP), -- parameter block
1967 New_Reference_To ( -- Asynchronous_Call
1968 RTE (RE_Asynchronous_Call), Loc),
1969 Make_Identifier (Loc, Name_uF)))); -- status flag
1970 end if;
7c949aad 1971
1972 else
1973 -- Ensure that the statements list is non-empty
1974
1975 Append_To (Stmts, Make_Null_Statement (Loc));
76a1c25b 1976 end if;
ee6ba406 1977
76a1c25b 1978 return
1979 Make_Subprogram_Body (Loc,
1980 Specification =>
1981 Make_Disp_Asynchronous_Select_Spec (Typ),
1982 Declarations =>
1983 Decls,
1984 Handled_Statement_Sequence =>
1985 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
1986 end Make_Disp_Asynchronous_Select_Body;
ee6ba406 1987
76a1c25b 1988 ----------------------------------------
1989 -- Make_Disp_Asynchronous_Select_Spec --
1990 ----------------------------------------
ee6ba406 1991
76a1c25b 1992 function Make_Disp_Asynchronous_Select_Spec
1993 (Typ : Entity_Id) return Node_Id
1994 is
1995 Loc : constant Source_Ptr := Sloc (Typ);
1996 Def_Id : constant Node_Id :=
1997 Make_Defining_Identifier (Loc,
1998 Name_uDisp_Asynchronous_Select);
1999 Params : constant List_Id := New_List;
ee6ba406 2000
76a1c25b 2001 begin
68f95949 2002 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2003
725a69d2 2004 -- T : in out Typ; -- Object parameter
2005 -- S : Integer; -- Primitive operation slot
2006 -- P : Address; -- Wrapped parameters
2007 -- B : out Dummy_Communication_Block; -- Communication block dummy
2008 -- F : out Boolean; -- Status flag
ee6ba406 2009
725a69d2 2010 Append_List_To (Params, New_List (
2011
2012 Make_Parameter_Specification (Loc,
2013 Defining_Identifier =>
2014 Make_Defining_Identifier (Loc, Name_uT),
2015 Parameter_Type =>
2016 New_Reference_To (Typ, Loc),
2017 In_Present => True,
2018 Out_Present => True),
2019
2020 Make_Parameter_Specification (Loc,
2021 Defining_Identifier =>
2022 Make_Defining_Identifier (Loc, Name_uS),
2023 Parameter_Type =>
2024 New_Reference_To (Standard_Integer, Loc)),
2025
2026 Make_Parameter_Specification (Loc,
2027 Defining_Identifier =>
2028 Make_Defining_Identifier (Loc, Name_uP),
2029 Parameter_Type =>
2030 New_Reference_To (RTE (RE_Address), Loc)),
2031
2032 Make_Parameter_Specification (Loc,
2033 Defining_Identifier =>
2034 Make_Defining_Identifier (Loc, Name_uB),
2035 Parameter_Type =>
2036 New_Reference_To (RTE (RE_Dummy_Communication_Block), Loc),
2037 Out_Present => True),
ee6ba406 2038
725a69d2 2039 Make_Parameter_Specification (Loc,
2040 Defining_Identifier =>
2041 Make_Defining_Identifier (Loc, Name_uF),
2042 Parameter_Type =>
2043 New_Reference_To (Standard_Boolean, Loc),
2044 Out_Present => True)));
7189d17f 2045
76a1c25b 2046 return
725a69d2 2047 Make_Procedure_Specification (Loc,
2048 Defining_Unit_Name => Def_Id,
2049 Parameter_Specifications => Params);
76a1c25b 2050 end Make_Disp_Asynchronous_Select_Spec;
ee6ba406 2051
76a1c25b 2052 ---------------------------------------
2053 -- Make_Disp_Conditional_Select_Body --
2054 ---------------------------------------
ee6ba406 2055
cdb1c38f 2056 -- For interface types, generate:
2057
2058 -- procedure _Disp_Conditional_Select
2059 -- (T : in out <Typ>;
2060 -- S : Integer;
2061 -- P : System.Address;
2062 -- C : out Ada.Tags.Prim_Op_Kind;
2063 -- F : out Boolean)
2064 -- is
2065 -- begin
2066 -- null;
2067 -- end _Disp_Conditional_Select;
2068
2069 -- For protected types, generate:
2070
2071 -- procedure _Disp_Conditional_Select
2072 -- (T : in out <Typ>;
2073 -- S : Integer;
2074 -- P : System.Address;
2075 -- C : out Ada.Tags.Prim_Op_Kind;
2076 -- F : out Boolean)
2077 -- is
2078 -- I : Integer;
2079 -- Bnn : System.Tasking.Protected_Objects.Operations.
2080 -- Communication_Block;
2081
2082 -- begin
2083 -- C := Ada.Tags.Get_Prim_Op_Kind (Ada.Tags.Tag (<Typ>VP, S));
2084
2085 -- if C = Ada.Tags.POK_Procedure
2086 -- or else C = Ada.Tags.POK_Protected_Procedure
2087 -- or else C = Ada.Tags.POK_Task_Procedure
2088 -- then
2089 -- F := True;
2090 -- return;
2091 -- end if;
2092
2093 -- I := Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP, S));
2094 -- System.Tasking.Protected_Objects.Operations.Protected_Entry_Call
2095 -- (T.object'Access,
2096 -- System.Tasking.Protected_Objects.Protected_Entry_Index (I),
2097 -- P,
2098 -- System.Tasking.Conditional_Call,
2099 -- Bnn);
2100 -- F := not Cancelled (Bnn);
2101 -- end _Disp_Conditional_Select;
2102
2103 -- For task types, generate:
2104
2105 -- procedure _Disp_Conditional_Select
2106 -- (T : in out <Typ>;
2107 -- S : Integer;
2108 -- P : System.Address;
2109 -- C : out Ada.Tags.Prim_Op_Kind;
2110 -- F : out Boolean)
2111 -- is
2112 -- I : Integer;
2113
2114 -- begin
2115 -- I := Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP, S));
2116 -- System.Tasking.Rendezvous.Task_Entry_Call
2117 -- (T._task_id,
2118 -- System.Tasking.Task_Entry_Index (I),
2119 -- P,
2120 -- System.Tasking.Conditional_Call,
2121 -- F);
2122 -- end _Disp_Conditional_Select;
2123
76a1c25b 2124 function Make_Disp_Conditional_Select_Body
2125 (Typ : Entity_Id) return Node_Id
2126 is
2127 Loc : constant Source_Ptr := Sloc (Typ);
2128 Blk_Nam : Entity_Id;
2129 Conc_Typ : Entity_Id := Empty;
2130 Decls : constant List_Id := New_List;
2131 DT_Ptr : Entity_Id;
acf97c11 2132 Obj_Ref : Node_Id;
76a1c25b 2133 Stmts : constant List_Id := New_List;
ee6ba406 2134
76a1c25b 2135 begin
68f95949 2136 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2137
952af0b9 2138 -- Null body is generated for interface types
2139
76a1c25b 2140 if Is_Interface (Typ) then
2141 return
2142 Make_Subprogram_Body (Loc,
2143 Specification =>
2144 Make_Disp_Conditional_Select_Spec (Typ),
2145 Declarations =>
2146 No_List,
2147 Handled_Statement_Sequence =>
2148 Make_Handled_Sequence_Of_Statements (Loc,
2149 New_List (Make_Null_Statement (Loc))));
2150 end if;
ee6ba406 2151
76a1c25b 2152 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
ee6ba406 2153
952af0b9 2154 if Is_Concurrent_Record_Type (Typ) then
2155 Conc_Typ := Corresponding_Concurrent_Type (Typ);
ee6ba406 2156
76a1c25b 2157 -- Generate:
2158 -- I : Integer;
ee6ba406 2159
76a1c25b 2160 -- where I will be used to capture the entry index of the primitive
2161 -- wrapper at position S.
ee6ba406 2162
76a1c25b 2163 Append_To (Decls,
2164 Make_Object_Declaration (Loc,
2165 Defining_Identifier =>
2166 Make_Defining_Identifier (Loc, Name_uI),
2167 Object_Definition =>
2168 New_Reference_To (Standard_Integer, Loc)));
ee6ba406 2169
952af0b9 2170 -- Generate:
cdb1c38f 2171 -- C := Ada.Tags.Get_Prim_Op_Kind (Ada.Tags.Tag! (<type>VP), S);
ee6ba406 2172
952af0b9 2173 -- if C = POK_Procedure
2174 -- or else C = POK_Protected_Procedure
2175 -- or else C = POK_Task_Procedure;
2176 -- then
2177 -- F := True;
2178 -- return;
2179 -- end if;
aad6babd 2180
725a69d2 2181 Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts);
aad6babd 2182
76a1c25b 2183 -- Generate:
2184 -- Bnn : Communication_Block;
aad6babd 2185
cdb1c38f 2186 -- where Bnn is the name of the communication block used in the
2187 -- call to Protected_Entry_Call.
aad6babd 2188
76a1c25b 2189 Blk_Nam := Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
aad6babd 2190
76a1c25b 2191 Append_To (Decls,
2192 Make_Object_Declaration (Loc,
2193 Defining_Identifier =>
2194 Blk_Nam,
2195 Object_Definition =>
2196 New_Reference_To (RTE (RE_Communication_Block), Loc)));
aad6babd 2197
76a1c25b 2198 -- Generate:
cdb1c38f 2199 -- I := Ada.Tags.Get_Entry_Index (Ada.Tags.Tag! (<type>VP), S);
aad6babd 2200
76a1c25b 2201 -- I is the entry index and S is the dispatch table slot
aad6babd 2202
76a1c25b 2203 Append_To (Stmts,
2204 Make_Assignment_Statement (Loc,
2205 Name =>
2206 Make_Identifier (Loc, Name_uI),
2207 Expression =>
725a69d2 2208 Make_Function_Call (Loc,
cdb1c38f 2209 Name =>
2210 New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
2211 Parameter_Associations =>
2212 New_List (
2213 Unchecked_Convert_To (RTE (RE_Tag),
2214 New_Reference_To (DT_Ptr, Loc)),
2215 Make_Identifier (Loc, Name_uS)))));
ee6ba406 2216
76a1c25b 2217 if Ekind (Conc_Typ) = E_Protected_Type then
ee6ba406 2218
acf97c11 2219 Obj_Ref := -- T._object'Access
2220 Make_Attribute_Reference (Loc,
2221 Attribute_Name => Name_Unchecked_Access,
2222 Prefix =>
2223 Make_Selected_Component (Loc,
2224 Prefix => Make_Identifier (Loc, Name_uT),
2225 Selector_Name => Make_Identifier (Loc, Name_uObject)));
ee6ba406 2226
acf97c11 2227 case Corresponding_Runtime_Package (Conc_Typ) is
2228 when System_Tasking_Protected_Objects_Entries =>
2229 -- Generate:
e1c20931 2230
acf97c11 2231 -- Protected_Entry_Call
2232 -- (T._object'Access, -- Object
2233 -- Protected_Entry_Index! (I), -- E
2234 -- P, -- Uninterpreted_Data
2235 -- Conditional_Call, -- Mode
2236 -- Bnn); -- Block
e1c20931 2237
acf97c11 2238 -- where T is the protected object, I is the entry index, P
2239 -- are the wrapped parameters and Bnn is the name of the
2240 -- communication block.
d62940bf 2241
acf97c11 2242 Append_To (Stmts,
2243 Make_Procedure_Call_Statement (Loc,
2244 Name =>
2245 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
2246 Parameter_Associations =>
2247 New_List (
2248 Obj_Ref,
d62940bf 2249
acf97c11 2250 Make_Unchecked_Type_Conversion (Loc, -- entry index
2251 Subtype_Mark =>
2252 New_Reference_To
2253 (RTE (RE_Protected_Entry_Index), Loc),
2254 Expression => Make_Identifier (Loc, Name_uI)),
2255
2256 Make_Identifier (Loc, Name_uP), -- parameter block
2257
2258 New_Reference_To ( -- Conditional_Call
2259 RTE (RE_Conditional_Call), Loc),
2260 New_Reference_To ( -- Bnn
2261 Blk_Nam, Loc))));
2262
2263 when System_Tasking_Protected_Objects_Single_Entry =>
2264
2265 -- If we are compiling for a restricted run-time, the call
2266 -- uses the simpler form.
2267
2268 Append_To (Stmts,
2269 Make_Procedure_Call_Statement (Loc,
2270 Name =>
2271 New_Reference_To
2272 (RTE (RE_Protected_Single_Entry_Call), Loc),
2273 Parameter_Associations =>
2274 New_List (
2275 Obj_Ref,
2276
2277 Make_Attribute_Reference (Loc,
2278 Prefix => Make_Identifier (Loc, Name_uP),
2279 Attribute_Name => Name_Address),
2280
2281 New_Reference_To
2282 (RTE (RE_Conditional_Call), Loc))));
2283 when others =>
2284 raise Program_Error;
2285 end case;
d62940bf 2286
76a1c25b 2287 -- Generate:
2288 -- F := not Cancelled (Bnn);
e1c20931 2289
76a1c25b 2290 -- where F is the success flag. The status of Cancelled is negated
2291 -- in order to match the behaviour of the version for task types.
e1c20931 2292
76a1c25b 2293 Append_To (Stmts,
2294 Make_Assignment_Statement (Loc,
2295 Name =>
2296 Make_Identifier (Loc, Name_uF),
2297 Expression =>
2298 Make_Op_Not (Loc,
2299 Right_Opnd =>
2300 Make_Function_Call (Loc,
2301 Name =>
2302 New_Reference_To (RTE (RE_Cancelled), Loc),
2303 Parameter_Associations =>
2304 New_List (
2305 New_Reference_To (Blk_Nam, Loc))))));
2306 else
2307 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
d62940bf 2308
76a1c25b 2309 -- Generate:
cdb1c38f 2310 -- Task_Entry_Call
2311 -- (T._task_id, -- Acceptor
2312 -- Task_Entry_Index! (I), -- E
2313 -- P, -- Uninterpreted_Data
2314 -- Conditional_Call, -- Mode
2315 -- F); -- Rendezvous_Successful
d62940bf 2316
76a1c25b 2317 -- where T is the task object, I is the entry index, P are the
2318 -- wrapped parameters and F is the status flag.
e1c20931 2319
76a1c25b 2320 Append_To (Stmts,
2321 Make_Procedure_Call_Statement (Loc,
2322 Name =>
2323 New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
2324 Parameter_Associations =>
2325 New_List (
2326
2327 Make_Selected_Component (Loc, -- T._task_id
2328 Prefix =>
2329 Make_Identifier (Loc, Name_uT),
2330 Selector_Name =>
2331 Make_Identifier (Loc, Name_uTask_Id)),
2332
2333 Make_Unchecked_Type_Conversion (Loc, -- entry index
2334 Subtype_Mark =>
2335 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2336 Expression =>
2337 Make_Identifier (Loc, Name_uI)),
2338
2339 Make_Identifier (Loc, Name_uP), -- parameter block
2340 New_Reference_To ( -- Conditional_Call
2341 RTE (RE_Conditional_Call), Loc),
2342 Make_Identifier (Loc, Name_uF)))); -- status flag
d62940bf 2343 end if;
7c949aad 2344
2345 else
2346 -- Ensure that the statements list is non-empty
2347
2348 Append_To (Stmts, Make_Null_Statement (Loc));
76a1c25b 2349 end if;
2350
2351 return
2352 Make_Subprogram_Body (Loc,
2353 Specification =>
2354 Make_Disp_Conditional_Select_Spec (Typ),
2355 Declarations =>
2356 Decls,
2357 Handled_Statement_Sequence =>
2358 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
2359 end Make_Disp_Conditional_Select_Body;
2360
2361 ---------------------------------------
2362 -- Make_Disp_Conditional_Select_Spec --
2363 ---------------------------------------
2364
2365 function Make_Disp_Conditional_Select_Spec
2366 (Typ : Entity_Id) return Node_Id
2367 is
2368 Loc : constant Source_Ptr := Sloc (Typ);
2369 Def_Id : constant Node_Id :=
2370 Make_Defining_Identifier (Loc,
2371 Name_uDisp_Conditional_Select);
2372 Params : constant List_Id := New_List;
2373
2374 begin
68f95949 2375 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2376
725a69d2 2377 -- T : in out Typ; -- Object parameter
2378 -- S : Integer; -- Primitive operation slot
2379 -- P : Address; -- Wrapped parameters
2380 -- C : out Prim_Op_Kind; -- Call kind
2381 -- F : out Boolean; -- Status flag
2382
2383 Append_List_To (Params, New_List (
2384
2385 Make_Parameter_Specification (Loc,
2386 Defining_Identifier =>
2387 Make_Defining_Identifier (Loc, Name_uT),
2388 Parameter_Type =>
2389 New_Reference_To (Typ, Loc),
2390 In_Present => True,
2391 Out_Present => True),
2392
2393 Make_Parameter_Specification (Loc,
2394 Defining_Identifier =>
2395 Make_Defining_Identifier (Loc, Name_uS),
2396 Parameter_Type =>
2397 New_Reference_To (Standard_Integer, Loc)),
2398
2399 Make_Parameter_Specification (Loc,
2400 Defining_Identifier =>
2401 Make_Defining_Identifier (Loc, Name_uP),
2402 Parameter_Type =>
2403 New_Reference_To (RTE (RE_Address), Loc)),
76a1c25b 2404
725a69d2 2405 Make_Parameter_Specification (Loc,
2406 Defining_Identifier =>
2407 Make_Defining_Identifier (Loc, Name_uC),
2408 Parameter_Type =>
2409 New_Reference_To (RTE (RE_Prim_Op_Kind), Loc),
2410 Out_Present => True),
76a1c25b 2411
725a69d2 2412 Make_Parameter_Specification (Loc,
2413 Defining_Identifier =>
2414 Make_Defining_Identifier (Loc, Name_uF),
2415 Parameter_Type =>
2416 New_Reference_To (Standard_Boolean, Loc),
2417 Out_Present => True)));
76a1c25b 2418
2419 return
2420 Make_Procedure_Specification (Loc,
2421 Defining_Unit_Name => Def_Id,
2422 Parameter_Specifications => Params);
2423 end Make_Disp_Conditional_Select_Spec;
2424
2425 -------------------------------------
2426 -- Make_Disp_Get_Prim_Op_Kind_Body --
2427 -------------------------------------
2428
2429 function Make_Disp_Get_Prim_Op_Kind_Body
2430 (Typ : Entity_Id) return Node_Id
2431 is
2432 Loc : constant Source_Ptr := Sloc (Typ);
2433 DT_Ptr : Entity_Id;
2434
2435 begin
68f95949 2436 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2437
76a1c25b 2438 if Is_Interface (Typ) then
2439 return
2440 Make_Subprogram_Body (Loc,
2441 Specification =>
2442 Make_Disp_Get_Prim_Op_Kind_Spec (Typ),
2443 Declarations =>
2444 New_List,
2445 Handled_Statement_Sequence =>
2446 Make_Handled_Sequence_Of_Statements (Loc,
2447 New_List (Make_Null_Statement (Loc))));
e1c20931 2448 end if;
2449
76a1c25b 2450 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
2451
d62940bf 2452 -- Generate:
76a1c25b 2453 -- C := get_prim_op_kind (tag! (<type>VP), S);
ee6ba406 2454
76a1c25b 2455 -- where C is the out parameter capturing the call kind and S is the
2456 -- dispatch table slot number.
ee6ba406 2457
76a1c25b 2458 return
2459 Make_Subprogram_Body (Loc,
2460 Specification =>
2461 Make_Disp_Get_Prim_Op_Kind_Spec (Typ),
2462 Declarations =>
2463 New_List,
2464 Handled_Statement_Sequence =>
2465 Make_Handled_Sequence_Of_Statements (Loc,
2466 New_List (
2467 Make_Assignment_Statement (Loc,
2468 Name =>
2469 Make_Identifier (Loc, Name_uC),
2470 Expression =>
725a69d2 2471 Make_Function_Call (Loc,
2472 Name =>
2473 New_Reference_To (RTE (RE_Get_Prim_Op_Kind), Loc),
2474 Parameter_Associations => New_List (
2475 Unchecked_Convert_To (RTE (RE_Tag),
2476 New_Reference_To (DT_Ptr, Loc)),
2477 Make_Identifier (Loc, Name_uS)))))));
76a1c25b 2478 end Make_Disp_Get_Prim_Op_Kind_Body;
e1c20931 2479
76a1c25b 2480 -------------------------------------
2481 -- Make_Disp_Get_Prim_Op_Kind_Spec --
2482 -------------------------------------
e1c20931 2483
76a1c25b 2484 function Make_Disp_Get_Prim_Op_Kind_Spec
2485 (Typ : Entity_Id) return Node_Id
2486 is
2487 Loc : constant Source_Ptr := Sloc (Typ);
2488 Def_Id : constant Node_Id :=
2489 Make_Defining_Identifier (Loc,
2490 Name_uDisp_Get_Prim_Op_Kind);
2491 Params : constant List_Id := New_List;
e1c20931 2492
76a1c25b 2493 begin
68f95949 2494 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2495
725a69d2 2496 -- T : in out Typ; -- Object parameter
2497 -- S : Integer; -- Primitive operation slot
2498 -- C : out Prim_Op_Kind; -- Call kind
2499
2500 Append_List_To (Params, New_List (
2501
2502 Make_Parameter_Specification (Loc,
2503 Defining_Identifier =>
2504 Make_Defining_Identifier (Loc, Name_uT),
2505 Parameter_Type =>
2506 New_Reference_To (Typ, Loc),
2507 In_Present => True,
2508 Out_Present => True),
ee6ba406 2509
725a69d2 2510 Make_Parameter_Specification (Loc,
2511 Defining_Identifier =>
2512 Make_Defining_Identifier (Loc, Name_uS),
2513 Parameter_Type =>
2514 New_Reference_To (Standard_Integer, Loc)),
ee6ba406 2515
725a69d2 2516 Make_Parameter_Specification (Loc,
2517 Defining_Identifier =>
2518 Make_Defining_Identifier (Loc, Name_uC),
2519 Parameter_Type =>
2520 New_Reference_To (RTE (RE_Prim_Op_Kind), Loc),
2521 Out_Present => True)));
76a1c25b 2522
2523 return
2524 Make_Procedure_Specification (Loc,
2525 Defining_Unit_Name => Def_Id,
2526 Parameter_Specifications => Params);
2527 end Make_Disp_Get_Prim_Op_Kind_Spec;
2528
2529 --------------------------------
2530 -- Make_Disp_Get_Task_Id_Body --
2531 --------------------------------
2532
2533 function Make_Disp_Get_Task_Id_Body
2534 (Typ : Entity_Id) return Node_Id
2535 is
2536 Loc : constant Source_Ptr := Sloc (Typ);
2537 Ret : Node_Id;
2538
2539 begin
68f95949 2540 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2541
76a1c25b 2542 if Is_Concurrent_Record_Type (Typ)
2543 and then Ekind (Corresponding_Concurrent_Type (Typ)) = E_Task_Type
2544 then
725a69d2 2545 -- Generate:
2546 -- return To_Address (_T._task_id);
2547
76a1c25b 2548 Ret :=
17e14451 2549 Make_Simple_Return_Statement (Loc,
76a1c25b 2550 Expression =>
725a69d2 2551 Make_Unchecked_Type_Conversion (Loc,
2552 Subtype_Mark =>
2553 New_Reference_To (RTE (RE_Address), Loc),
2554 Expression =>
2555 Make_Selected_Component (Loc,
2556 Prefix =>
2557 Make_Identifier (Loc, Name_uT),
2558 Selector_Name =>
2559 Make_Identifier (Loc, Name_uTask_Id))));
76a1c25b 2560
2561 -- A null body is constructed for non-task types
2562
2563 else
725a69d2 2564 -- Generate:
2565 -- return Null_Address;
2566
76a1c25b 2567 Ret :=
17e14451 2568 Make_Simple_Return_Statement (Loc,
76a1c25b 2569 Expression =>
725a69d2 2570 New_Reference_To (RTE (RE_Null_Address), Loc));
76a1c25b 2571 end if;
2572
2573 return
2574 Make_Subprogram_Body (Loc,
2575 Specification =>
2576 Make_Disp_Get_Task_Id_Spec (Typ),
2577 Declarations =>
2578 New_List,
2579 Handled_Statement_Sequence =>
2580 Make_Handled_Sequence_Of_Statements (Loc,
2581 New_List (Ret)));
2582 end Make_Disp_Get_Task_Id_Body;
2583
2584 --------------------------------
2585 -- Make_Disp_Get_Task_Id_Spec --
2586 --------------------------------
2587
2588 function Make_Disp_Get_Task_Id_Spec
2589 (Typ : Entity_Id) return Node_Id
2590 is
725a69d2 2591 Loc : constant Source_Ptr := Sloc (Typ);
76a1c25b 2592
2593 begin
68f95949 2594 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2595
76a1c25b 2596 return
2597 Make_Function_Specification (Loc,
725a69d2 2598 Defining_Unit_Name =>
2599 Make_Defining_Identifier (Loc, Name_uDisp_Get_Task_Id),
76a1c25b 2600 Parameter_Specifications => New_List (
2601 Make_Parameter_Specification (Loc,
2602 Defining_Identifier =>
2603 Make_Defining_Identifier (Loc, Name_uT),
2604 Parameter_Type =>
2605 New_Reference_To (Typ, Loc))),
2606 Result_Definition =>
725a69d2 2607 New_Reference_To (RTE (RE_Address), Loc));
76a1c25b 2608 end Make_Disp_Get_Task_Id_Spec;
2609
cdb1c38f 2610 ----------------------------
2611 -- Make_Disp_Requeue_Body --
2612 ----------------------------
2613
2614 function Make_Disp_Requeue_Body
2615 (Typ : Entity_Id) return Node_Id
2616 is
2617 Loc : constant Source_Ptr := Sloc (Typ);
2618 Conc_Typ : Entity_Id := Empty;
2619 Stmts : constant List_Id := New_List;
2620
2621 begin
2622 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2623
2624 -- Null body is generated for interface types and non-concurrent
2625 -- tagged types.
2626
2627 if Is_Interface (Typ)
2628 or else not Is_Concurrent_Record_Type (Typ)
2629 then
2630 return
2631 Make_Subprogram_Body (Loc,
2632 Specification =>
2633 Make_Disp_Requeue_Spec (Typ),
2634 Declarations =>
2635 No_List,
2636 Handled_Statement_Sequence =>
2637 Make_Handled_Sequence_Of_Statements (Loc,
2638 New_List (Make_Null_Statement (Loc))));
2639 end if;
2640
2641 Conc_Typ := Corresponding_Concurrent_Type (Typ);
2642
2643 if Ekind (Conc_Typ) = E_Protected_Type then
2644
2645 -- Generate statements:
2646 -- if F then
2647 -- System.Tasking.Protected_Objects.Operations.
2648 -- Requeue_Protected_Entry
2649 -- (Protection_Entries_Access (P),
2650 -- O._object'Unchecked_Access,
2651 -- Protected_Entry_Index (I),
2652 -- A);
2653 -- else
2654 -- System.Tasking.Protected_Objects.Operations.
2655 -- Requeue_Task_To_Protected_Entry
2656 -- (O._object'Unchecked_Access,
2657 -- Protected_Entry_Index (I),
2658 -- A);
2659 -- end if;
2660
acf97c11 2661 if Restriction_Active (No_Entry_Queue) then
2662 Append_To (Stmts, Make_Null_Statement (Loc));
2663 else
2664 Append_To (Stmts,
2665 Make_If_Statement (Loc,
2666 Condition =>
2667 Make_Identifier (Loc, Name_uF),
cdb1c38f 2668
acf97c11 2669 Then_Statements =>
2670 New_List (
cdb1c38f 2671
acf97c11 2672 -- Call to Requeue_Protected_Entry
cdb1c38f 2673
acf97c11 2674 Make_Procedure_Call_Statement (Loc,
2675 Name =>
2676 New_Reference_To (
2677 RTE (RE_Requeue_Protected_Entry), Loc),
2678 Parameter_Associations =>
2679 New_List (
2680
2681 Make_Unchecked_Type_Conversion (Loc, -- PEA (P)
2682 Subtype_Mark =>
2683 New_Reference_To (
2684 RTE (RE_Protection_Entries_Access), Loc),
2685 Expression =>
2686 Make_Identifier (Loc, Name_uP)),
2687
2688 Make_Attribute_Reference (Loc, -- O._object'Acc
2689 Attribute_Name =>
2690 Name_Unchecked_Access,
2691 Prefix =>
2692 Make_Selected_Component (Loc,
2693 Prefix =>
2694 Make_Identifier (Loc, Name_uO),
2695 Selector_Name =>
2696 Make_Identifier (Loc, Name_uObject))),
2697
2698 Make_Unchecked_Type_Conversion (Loc, -- entry index
2699 Subtype_Mark =>
2700 New_Reference_To (
2701 RTE (RE_Protected_Entry_Index), Loc),
2702 Expression =>
2703 Make_Identifier (Loc, Name_uI)),
cdb1c38f 2704
acf97c11 2705 Make_Identifier (Loc, Name_uA)))), -- abort status
cdb1c38f 2706
acf97c11 2707 Else_Statements =>
2708 New_List (
cdb1c38f 2709
acf97c11 2710 -- Call to Requeue_Task_To_Protected_Entry
cdb1c38f 2711
acf97c11 2712 Make_Procedure_Call_Statement (Loc,
2713 Name =>
2714 New_Reference_To (
2715 RTE (RE_Requeue_Task_To_Protected_Entry), Loc),
2716 Parameter_Associations =>
2717 New_List (
2718
2719 Make_Attribute_Reference (Loc, -- O._object'Acc
2720 Attribute_Name =>
2721 Name_Unchecked_Access,
2722 Prefix =>
2723 Make_Selected_Component (Loc,
2724 Prefix =>
2725 Make_Identifier (Loc, Name_uO),
2726 Selector_Name =>
2727 Make_Identifier (Loc, Name_uObject))),
2728
2729 Make_Unchecked_Type_Conversion (Loc, -- entry index
2730 Subtype_Mark =>
2731 New_Reference_To (
2732 RTE (RE_Protected_Entry_Index), Loc),
2733 Expression =>
2734 Make_Identifier (Loc, Name_uI)),
cdb1c38f 2735
acf97c11 2736 Make_Identifier (Loc, Name_uA)))))); -- abort status
2737 end if;
cdb1c38f 2738 else
2739 pragma Assert (Is_Task_Type (Conc_Typ));
2740
2741 -- Generate:
2742 -- if F then
2743 -- System.Tasking.Rendezvous.Requeue_Protected_To_Task_Entry
2744 -- (Protection_Entries_Access (P),
2745 -- O._task_id,
2746 -- Task_Entry_Index (I),
2747 -- A);
2748 -- else
2749 -- System.Tasking.Rendezvous.Requeue_Task_Entry
2750 -- (O._task_id,
2751 -- Task_Entry_Index (I),
2752 -- A);
2753 -- end if;
2754
2755 Append_To (Stmts,
2756 Make_If_Statement (Loc,
2757 Condition =>
2758 Make_Identifier (Loc, Name_uF),
2759
2760 Then_Statements =>
2761 New_List (
2762
2763 -- Call to Requeue_Protected_To_Task_Entry
2764
2765 Make_Procedure_Call_Statement (Loc,
2766 Name =>
2767 New_Reference_To (
2768 RTE (RE_Requeue_Protected_To_Task_Entry), Loc),
2769
2770 Parameter_Associations =>
2771 New_List (
2772
2773 Make_Unchecked_Type_Conversion (Loc, -- PEA (P)
2774 Subtype_Mark =>
2775 New_Reference_To (
2776 RTE (RE_Protection_Entries_Access), Loc),
2777 Expression =>
2778 Make_Identifier (Loc, Name_uP)),
2779
2780 Make_Selected_Component (Loc, -- O._task_id
2781 Prefix =>
2782 Make_Identifier (Loc, Name_uO),
2783 Selector_Name =>
2784 Make_Identifier (Loc, Name_uTask_Id)),
2785
2786 Make_Unchecked_Type_Conversion (Loc, -- entry index
2787 Subtype_Mark =>
2788 New_Reference_To (
2789 RTE (RE_Task_Entry_Index), Loc),
2790 Expression =>
2791 Make_Identifier (Loc, Name_uI)),
2792
2793 Make_Identifier (Loc, Name_uA)))), -- abort status
2794
2795 Else_Statements =>
2796 New_List (
2797
2798 -- Call to Requeue_Task_Entry
2799
2800 Make_Procedure_Call_Statement (Loc,
2801 Name =>
2802 New_Reference_To (RTE (RE_Requeue_Task_Entry), Loc),
2803
2804 Parameter_Associations =>
2805 New_List (
2806
2807 Make_Selected_Component (Loc, -- O._task_id
2808 Prefix =>
2809 Make_Identifier (Loc, Name_uO),
2810 Selector_Name =>
2811 Make_Identifier (Loc, Name_uTask_Id)),
2812
2813 Make_Unchecked_Type_Conversion (Loc, -- entry index
2814 Subtype_Mark =>
2815 New_Reference_To (
2816 RTE (RE_Task_Entry_Index), Loc),
2817 Expression =>
2818 Make_Identifier (Loc, Name_uI)),
2819
2820 Make_Identifier (Loc, Name_uA)))))); -- abort status
2821 end if;
2822
2823 -- Even though no declarations are needed in both cases, we allocate
2824 -- a list for entities added by Freeze.
2825
2826 return
2827 Make_Subprogram_Body (Loc,
2828 Specification =>
2829 Make_Disp_Requeue_Spec (Typ),
2830 Declarations =>
2831 New_List,
2832 Handled_Statement_Sequence =>
2833 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
2834 end Make_Disp_Requeue_Body;
2835
2836 ----------------------------
2837 -- Make_Disp_Requeue_Spec --
2838 ----------------------------
2839
2840 function Make_Disp_Requeue_Spec
2841 (Typ : Entity_Id) return Node_Id
2842 is
2843 Loc : constant Source_Ptr := Sloc (Typ);
2844
2845 begin
2846 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2847
2848 -- O : in out Typ; - Object parameter
2849 -- F : Boolean; - Protected (True) / task (False) flag
2850 -- P : Address; - Protection_Entries_Access value
2851 -- I : Entry_Index - Index of entry call
2852 -- A : Boolean - Abort flag
2853
2854 -- Note that the Protection_Entries_Access value is represented as a
2855 -- System.Address in order to avoid dragging in the tasking runtime
2856 -- when compiling sources without tasking constructs.
2857
2858 return
2859 Make_Procedure_Specification (Loc,
2860 Defining_Unit_Name =>
2861 Make_Defining_Identifier (Loc, Name_uDisp_Requeue),
2862
2863 Parameter_Specifications =>
2864 New_List (
2865
2866 Make_Parameter_Specification (Loc, -- O
2867 Defining_Identifier =>
2868 Make_Defining_Identifier (Loc, Name_uO),
2869 Parameter_Type =>
2870 New_Reference_To (Typ, Loc),
2871 In_Present => True,
2872 Out_Present => True),
2873
2874 Make_Parameter_Specification (Loc, -- F
2875 Defining_Identifier =>
2876 Make_Defining_Identifier (Loc, Name_uF),
2877 Parameter_Type =>
2878 New_Reference_To (Standard_Boolean, Loc)),
2879
2880 Make_Parameter_Specification (Loc, -- P
2881 Defining_Identifier =>
2882 Make_Defining_Identifier (Loc, Name_uP),
2883 Parameter_Type =>
2884 New_Reference_To (RTE (RE_Address), Loc)),
2885
2886 Make_Parameter_Specification (Loc, -- I
2887 Defining_Identifier =>
2888 Make_Defining_Identifier (Loc, Name_uI),
2889 Parameter_Type =>
2890 New_Reference_To (Standard_Integer, Loc)),
2891
2892 Make_Parameter_Specification (Loc, -- A
2893 Defining_Identifier =>
2894 Make_Defining_Identifier (Loc, Name_uA),
2895 Parameter_Type =>
2896 New_Reference_To (Standard_Boolean, Loc))));
2897 end Make_Disp_Requeue_Spec;
2898
76a1c25b 2899 ---------------------------------
2900 -- Make_Disp_Timed_Select_Body --
2901 ---------------------------------
2902
cdb1c38f 2903 -- For interface types, generate:
2904
2905 -- procedure _Disp_Timed_Select
2906 -- (T : in out <Typ>;
2907 -- S : Integer;
2908 -- P : System.Address;
2909 -- D : Duration;
2910 -- M : Integer;
2911 -- C : out Ada.Tags.Prim_Op_Kind;
2912 -- F : out Boolean)
2913 -- is
2914 -- begin
2915 -- null;
2916 -- end _Disp_Timed_Select;
2917
2918 -- For protected types, generate:
2919
2920 -- procedure _Disp_Timed_Select
2921 -- (T : in out <Typ>;
2922 -- S : Integer;
2923 -- P : System.Address;
2924 -- D : Duration;
2925 -- M : Integer;
2926 -- C : out Ada.Tags.Prim_Op_Kind;
2927 -- F : out Boolean)
2928 -- is
2929 -- I : Integer;
2930
2931 -- begin
2932 -- C := Ada.Tags.Get_Prim_Op_Kind (Ada.Tags.Tag (<Typ>VP), S);
2933
2934 -- if C = Ada.Tags.POK_Procedure
2935 -- or else C = Ada.Tags.POK_Protected_Procedure
2936 -- or else C = Ada.Tags.POK_Task_Procedure
2937 -- then
2938 -- F := True;
2939 -- return;
2940 -- end if;
2941
2942 -- I := Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP), S);
2943 -- System.Tasking.Protected_Objects.Operations.
2944 -- Timed_Protected_Entry_Call
2945 -- (T._object'Access,
2946 -- System.Tasking.Protected_Objects.Protected_Entry_Index (I),
2947 -- P,
2948 -- D,
2949 -- M,
2950 -- F);
2951 -- end _Disp_Timed_Select;
2952
2953 -- For task types, generate:
2954
2955 -- procedure _Disp_Timed_Select
2956 -- (T : in out <Typ>;
2957 -- S : Integer;
2958 -- P : System.Address;
2959 -- D : Duration;
2960 -- M : Integer;
2961 -- C : out Ada.Tags.Prim_Op_Kind;
2962 -- F : out Boolean)
2963 -- is
2964 -- I : Integer;
2965
2966 -- begin
2967 -- I := Ada.Tags.Get_Entry_Index (Ada.Tags.Tag (<Typ>VP), S);
2968 -- System.Tasking.Rendezvous.Timed_Task_Entry_Call
2969 -- (T._task_id,
2970 -- System.Tasking.Task_Entry_Index (I),
2971 -- P,
2972 -- D,
2973 -- M,
2974 -- D);
2975 -- end _Disp_Time_Select;
2976
76a1c25b 2977 function Make_Disp_Timed_Select_Body
2978 (Typ : Entity_Id) return Node_Id
2979 is
2980 Loc : constant Source_Ptr := Sloc (Typ);
2981 Conc_Typ : Entity_Id := Empty;
2982 Decls : constant List_Id := New_List;
2983 DT_Ptr : Entity_Id;
acf97c11 2984 Obj_Ref : Node_Id;
76a1c25b 2985 Stmts : constant List_Id := New_List;
2986
2987 begin
68f95949 2988 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2989
952af0b9 2990 -- Null body is generated for interface types
2991
76a1c25b 2992 if Is_Interface (Typ) then
2993 return
2994 Make_Subprogram_Body (Loc,
2995 Specification =>
2996 Make_Disp_Timed_Select_Spec (Typ),
2997 Declarations =>
2998 New_List,
2999 Handled_Statement_Sequence =>
3000 Make_Handled_Sequence_Of_Statements (Loc,
3001 New_List (Make_Null_Statement (Loc))));
3002 end if;
3003
76a1c25b 3004 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
3005
952af0b9 3006 if Is_Concurrent_Record_Type (Typ) then
3007 Conc_Typ := Corresponding_Concurrent_Type (Typ);
76a1c25b 3008
3009 -- Generate:
3010 -- I : Integer;
3011
3012 -- where I will be used to capture the entry index of the primitive
3013 -- wrapper at position S.
3014
3015 Append_To (Decls,
3016 Make_Object_Declaration (Loc,
3017 Defining_Identifier =>
3018 Make_Defining_Identifier (Loc, Name_uI),
3019 Object_Definition =>
3020 New_Reference_To (Standard_Integer, Loc)));
76a1c25b 3021
952af0b9 3022 -- Generate:
3023 -- C := Get_Prim_Op_Kind (tag! (<type>VP), S);
76a1c25b 3024
952af0b9 3025 -- if C = POK_Procedure
3026 -- or else C = POK_Protected_Procedure
3027 -- or else C = POK_Task_Procedure;
3028 -- then
3029 -- F := True;
3030 -- return;
3031 -- end if;
76a1c25b 3032
725a69d2 3033 Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts);
76a1c25b 3034
3035 -- Generate:
952af0b9 3036 -- I := Get_Entry_Index (tag! (<type>VP), S);
76a1c25b 3037
3038 -- I is the entry index and S is the dispatch table slot
3039
3040 Append_To (Stmts,
3041 Make_Assignment_Statement (Loc,
3042 Name =>
3043 Make_Identifier (Loc, Name_uI),
3044 Expression =>
725a69d2 3045 Make_Function_Call (Loc,
cdb1c38f 3046 Name =>
3047 New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
3048 Parameter_Associations =>
3049 New_List (
3050 Unchecked_Convert_To (RTE (RE_Tag),
3051 New_Reference_To (DT_Ptr, Loc)),
3052 Make_Identifier (Loc, Name_uS)))));
76a1c25b 3053
acf97c11 3054 -- Protected case
3055
76a1c25b 3056 if Ekind (Conc_Typ) = E_Protected_Type then
3057
acf97c11 3058 -- Build T._object'Access
3059
3060 Obj_Ref :=
3061 Make_Attribute_Reference (Loc,
3062 Attribute_Name => Name_Unchecked_Access,
3063 Prefix =>
3064 Make_Selected_Component (Loc,
3065 Prefix => Make_Identifier (Loc, Name_uT),
3066 Selector_Name => Make_Identifier (Loc, Name_uObject)));
3067
3068 -- Normal case, No_Entry_Queue restriction not active. In this
3069 -- case we generate:
3070
3071 -- Timed_Protected_Entry_Call
3072 -- (T._object'access,
cdb1c38f 3073 -- Protected_Entry_Index! (I),
acf97c11 3074 -- P, D, M, F);
76a1c25b 3075
3076 -- where T is the protected object, I is the entry index, P are
3077 -- the wrapped parameters, D is the delay amount, M is the delay
3078 -- mode and F is the status flag.
3079
acf97c11 3080 case Corresponding_Runtime_Package (Conc_Typ) is
3081 when System_Tasking_Protected_Objects_Entries =>
3082 Append_To (Stmts,
3083 Make_Procedure_Call_Statement (Loc,
3084 Name =>
3085 New_Reference_To
3086 (RTE (RE_Timed_Protected_Entry_Call), Loc),
3087 Parameter_Associations =>
3088 New_List (
3089 Obj_Ref,
3090
3091 Make_Unchecked_Type_Conversion (Loc, -- entry index
3092 Subtype_Mark =>
3093 New_Reference_To
3094 (RTE (RE_Protected_Entry_Index), Loc),
3095 Expression =>
3096 Make_Identifier (Loc, Name_uI)),
76a1c25b 3097
acf97c11 3098 Make_Identifier (Loc, Name_uP), -- parameter block
3099 Make_Identifier (Loc, Name_uD), -- delay
3100 Make_Identifier (Loc, Name_uM), -- delay mode
3101 Make_Identifier (Loc, Name_uF)))); -- status flag
76a1c25b 3102
acf97c11 3103 when System_Tasking_Protected_Objects_Single_Entry =>
3104 -- Generate:
76a1c25b 3105
acf97c11 3106 -- Timed_Protected_Single_Entry_Call
3107 -- (T._object'access, P, D, M, F);
3108
3109 -- where T is the protected object, P is the wrapped
3110 -- parameters, D is the delay amount, M is the delay mode, F
3111 -- is the status flag.
3112
3113 Append_To (Stmts,
3114 Make_Procedure_Call_Statement (Loc,
3115 Name =>
3116 New_Reference_To
3117 (RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
3118 Parameter_Associations =>
3119 New_List (
3120 Obj_Ref,
3121 Make_Identifier (Loc, Name_uP), -- parameter block
3122 Make_Identifier (Loc, Name_uD), -- delay
3123 Make_Identifier (Loc, Name_uM), -- delay mode
3124 Make_Identifier (Loc, Name_uF)))); -- status flag
3125
3126 when others =>
3127 raise Program_Error;
3128 end case;
3129
3130 -- Task case
ee6ba406 3131
ee6ba406 3132 else
76a1c25b 3133 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
3134
3135 -- Generate:
3136 -- Timed_Task_Entry_Call (
3137 -- T._task_id,
cdb1c38f 3138 -- Task_Entry_Index! (I),
76a1c25b 3139 -- P,
3140 -- D,
3141 -- M,
3142 -- F);
3143
3144 -- where T is the task object, I is the entry index, P are the
3145 -- wrapped parameters, D is the delay amount, M is the delay
3146 -- mode and F is the status flag.
3147
3148 Append_To (Stmts,
3149 Make_Procedure_Call_Statement (Loc,
3150 Name =>
3151 New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc),
3152 Parameter_Associations =>
3153 New_List (
3154
3155 Make_Selected_Component (Loc, -- T._task_id
3156 Prefix =>
3157 Make_Identifier (Loc, Name_uT),
3158 Selector_Name =>
3159 Make_Identifier (Loc, Name_uTask_Id)),
3160
3161 Make_Unchecked_Type_Conversion (Loc, -- entry index
3162 Subtype_Mark =>
3163 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
3164 Expression =>
3165 Make_Identifier (Loc, Name_uI)),
3166
3167 Make_Identifier (Loc, Name_uP), -- parameter block
3168 Make_Identifier (Loc, Name_uD), -- delay
3169 Make_Identifier (Loc, Name_uM), -- delay mode
3170 Make_Identifier (Loc, Name_uF)))); -- status flag
ee6ba406 3171 end if;
7c949aad 3172
3173 else
3174 -- Ensure that the statements list is non-empty
3175
3176 Append_To (Stmts, Make_Null_Statement (Loc));
76a1c25b 3177 end if;
3178
3179 return
3180 Make_Subprogram_Body (Loc,
3181 Specification =>
3182 Make_Disp_Timed_Select_Spec (Typ),
3183 Declarations =>
3184 Decls,
3185 Handled_Statement_Sequence =>
3186 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
3187 end Make_Disp_Timed_Select_Body;
3188
3189 ---------------------------------
3190 -- Make_Disp_Timed_Select_Spec --
3191 ---------------------------------
3192
3193 function Make_Disp_Timed_Select_Spec
3194 (Typ : Entity_Id) return Node_Id
3195 is
3196 Loc : constant Source_Ptr := Sloc (Typ);
3197 Def_Id : constant Node_Id :=
3198 Make_Defining_Identifier (Loc,
3199 Name_uDisp_Timed_Select);
3200 Params : constant List_Id := New_List;
ee6ba406 3201
76a1c25b 3202 begin
68f95949 3203 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
3204
725a69d2 3205 -- T : in out Typ; -- Object parameter
3206 -- S : Integer; -- Primitive operation slot
3207 -- P : Address; -- Wrapped parameters
3208 -- D : Duration; -- Delay
3209 -- M : Integer; -- Delay Mode
3210 -- C : out Prim_Op_Kind; -- Call kind
3211 -- F : out Boolean; -- Status flag
76a1c25b 3212
725a69d2 3213 Append_List_To (Params, New_List (
3214
3215 Make_Parameter_Specification (Loc,
3216 Defining_Identifier =>
3217 Make_Defining_Identifier (Loc, Name_uT),
3218 Parameter_Type =>
3219 New_Reference_To (Typ, Loc),
3220 In_Present => True,
3221 Out_Present => True),
3222
3223 Make_Parameter_Specification (Loc,
3224 Defining_Identifier =>
3225 Make_Defining_Identifier (Loc, Name_uS),
3226 Parameter_Type =>
3227 New_Reference_To (Standard_Integer, Loc)),
3228
3229 Make_Parameter_Specification (Loc,
3230 Defining_Identifier =>
3231 Make_Defining_Identifier (Loc, Name_uP),
3232 Parameter_Type =>
3233 New_Reference_To (RTE (RE_Address), Loc)),
76a1c25b 3234
76a1c25b 3235 Make_Parameter_Specification (Loc,
3236 Defining_Identifier =>
3237 Make_Defining_Identifier (Loc, Name_uD),
3238 Parameter_Type =>
725a69d2 3239 New_Reference_To (Standard_Duration, Loc)),
76a1c25b 3240
76a1c25b 3241 Make_Parameter_Specification (Loc,
3242 Defining_Identifier =>
3243 Make_Defining_Identifier (Loc, Name_uM),
3244 Parameter_Type =>
725a69d2 3245 New_Reference_To (Standard_Integer, Loc)),
ee6ba406 3246
725a69d2 3247 Make_Parameter_Specification (Loc,
3248 Defining_Identifier =>
3249 Make_Defining_Identifier (Loc, Name_uC),
3250 Parameter_Type =>
3251 New_Reference_To (RTE (RE_Prim_Op_Kind), Loc),
3252 Out_Present => True)));
ee6ba406 3253
725a69d2 3254 Append_To (Params,
3255 Make_Parameter_Specification (Loc,
3256 Defining_Identifier =>
3257 Make_Defining_Identifier (Loc, Name_uF),
3258 Parameter_Type =>
3259 New_Reference_To (Standard_Boolean, Loc),
3260 Out_Present => True));
ee6ba406 3261
76a1c25b 3262 return
3263 Make_Procedure_Specification (Loc,
3264 Defining_Unit_Name => Def_Id,
3265 Parameter_Specifications => Params);
3266 end Make_Disp_Timed_Select_Spec;
ee6ba406 3267
76a1c25b 3268 -------------
3269 -- Make_DT --
3270 -------------
ee6ba406 3271
725a69d2 3272 -- The frontend supports two models for expanding dispatch tables
3273 -- associated with library-level defined tagged types: statically
3274 -- and non-statically allocated dispatch tables. In the former case
3275 -- the object containing the dispatch table is constant and it is
3276 -- initialized by means of a positional aggregate. In the latter case,
3277 -- the object containing the dispatch table is a variable which is
3278 -- initialized by means of assignments.
3279
3280 -- In case of locally defined tagged types, the object containing the
3281 -- object containing the dispatch table is always a variable (instead
3282 -- of a constant). This is currently required to give support to late
3283 -- overriding of primitives. For example:
3284
3285 -- procedure Example is
3286 -- package Pkg is
3287 -- type T1 is tagged null record;
3288 -- procedure Prim (O : T1);
3289 -- end Pkg;
3290
3291 -- type T2 is new Pkg.T1 with null record;
3292 -- procedure Prim (X : T2) is -- late overriding
3293 -- begin
3294 -- ...
3295 -- ...
3296 -- end;
952af0b9 3297
17e14451 3298 function Make_DT (Typ : Entity_Id; N : Node_Id := Empty) return List_Id is
3299 Loc : constant Source_Ptr := Sloc (Typ);
3300
725a69d2 3301 Max_Predef_Prims : constant Int :=
3302 UI_To_Int
3303 (Intval
3304 (Expression
17e14451 3305 (Parent (RTE (RE_Max_Predef_Prims)))));
3306
cc60bd16 3307 DT_Decl : constant Elist_Id := New_Elmt_List;
3308 DT_Aggr : constant Elist_Id := New_Elmt_List;
3309 -- Entities marked with attribute Is_Dispatch_Table_Entity
3310
17e14451 3311 procedure Check_Premature_Freezing (Subp : Entity_Id; Typ : Entity_Id);
3312 -- Verify that all non-tagged types in the profile of a subprogram
3313 -- are frozen at the point the subprogram is frozen. This enforces
3314 -- the rule on RM 13.14 (14) as modified by AI05-019. At the point a
3315 -- subprogram is frozen, enough must be known about it to build the
3316 -- activation record for it, which requires at least that the size of
3317 -- all parameters be known. Controlling arguments are by-reference,
3318 -- and therefore the rule only applies to non-tagged types.
3319 -- Typical violation of the rule involves an object declaration that
3320 -- freezes a tagged type, when one of its primitive operations has a
3321 -- type in its profile whose full view has not been analyzed yet.
725a69d2 3322
f301a57b 3323 procedure Export_DT (Typ : Entity_Id; DT : Entity_Id; Index : Nat := 0);
3324 -- Export the dispatch table DT of tagged type Typ. Required to generate
3325 -- forward references and statically allocate the table. For primary
3326 -- dispatch tables Index is 0; for secondary dispatch tables the value
3327 -- of index must match the Suffix_Index value assigned to the table by
3328 -- Make_Tags when generating its unique external name, and it is used to
3329 -- retrieve from the Dispatch_Table_Wrappers list associated with Typ
3330 -- the external name generated by Import_DT.
24971415 3331
725a69d2 3332 procedure Make_Secondary_DT
acf97c11 3333 (Typ : Entity_Id;
3334 Iface : Entity_Id;
f301a57b 3335 Suffix_Index : Int;
acf97c11 3336 Num_Iface_Prims : Nat;
3337 Iface_DT_Ptr : Entity_Id;
3338 Predef_Prims_Ptr : Entity_Id;
3339 Build_Thunks : Boolean;
3340 Result : List_Id);
cdb1c38f 3341 -- Ada 2005 (AI-251): Expand the declarations for a Secondary Dispatch
3342 -- Table of Typ associated with Iface. Each abstract interface of Typ
3343 -- has two secondary dispatch tables: one containing pointers to thunks
3344 -- and another containing pointers to the primitives covering the
3345 -- interface primitives. The former secondary table is generated when
3346 -- Build_Thunks is True, and provides common support for dispatching
3347 -- calls through interface types; the latter secondary table is
3348 -- generated when Build_Thunks is False, and provides support for
3349 -- Generic Dispatching Constructors that dispatch calls through
f301a57b 3350 -- interface types. When constructing this latter table the value
3351 -- of Suffix_Index is -1 to indicate that there is no need to export
3352 -- such table when building statically allocated dispatch tables; a
3353 -- positive value of Suffix_Index must match the Suffix_Index value
3354 -- assigned to this secondary dispatch table by Make_Tags when its
3355 -- unique external name was generated.
9dfe12ae 3356
17e14451 3357 ------------------------------
3358 -- Check_Premature_Freezing --
3359 ------------------------------
3360
3361 procedure Check_Premature_Freezing (Subp : Entity_Id; Typ : Entity_Id) is
3362 begin
3363 if Present (N)
3364 and then Is_Private_Type (Typ)
3365 and then No (Full_View (Typ))
3366 and then not Is_Generic_Type (Typ)
3367 and then not Is_Tagged_Type (Typ)
3368 and then not Is_Frozen (Typ)
3369 then
3370 Error_Msg_Sloc := Sloc (Subp);
3371 Error_Msg_NE
3372 ("declaration must appear after completion of type &", N, Typ);
3373 Error_Msg_NE
3374 ("\which is an untagged type in the profile of"
3375 & " primitive operation & declared#",
3376 N, Subp);
3377 end if;
3378 end Check_Premature_Freezing;
3379
24971415 3380 ---------------
3381 -- Export_DT --
3382 ---------------
3383
f301a57b 3384 procedure Export_DT (Typ : Entity_Id; DT : Entity_Id; Index : Nat := 0)
3385 is
3386 Count : Nat;
3387 Elmt : Elmt_Id;
3388
24971415 3389 begin
3390 Set_Is_Statically_Allocated (DT);
3391 Set_Is_True_Constant (DT);
3392 Set_Is_Exported (DT);
3393
f301a57b 3394 Count := 0;
3395 Elmt := First_Elmt (Dispatch_Table_Wrappers (Typ));
3396 while Count /= Index loop
3397 Next_Elmt (Elmt);
3398 Count := Count + 1;
3399 end loop;
3400
3401 pragma Assert (Related_Type (Node (Elmt)) = Typ);
3402
3403 Get_External_Name
3404 (Entity => Node (Elmt),
3405 Has_Suffix => True);
3406
24971415 3407 Set_Interface_Name (DT,
3408 Make_String_Literal (Loc,
3409 Strval => String_From_Name_Buffer));
3410
3411 -- Ensure proper Sprint output of this implicit importation
3412
3413 Set_Is_Internal (DT);
3414 Set_Is_Public (DT);
3415 end Export_DT;
3416
725a69d2 3417 -----------------------
3418 -- Make_Secondary_DT --
3419 -----------------------
ee6ba406 3420
725a69d2 3421 procedure Make_Secondary_DT
acf97c11 3422 (Typ : Entity_Id;
3423 Iface : Entity_Id;
f301a57b 3424 Suffix_Index : Int;
acf97c11 3425 Num_Iface_Prims : Nat;
3426 Iface_DT_Ptr : Entity_Id;
3427 Predef_Prims_Ptr : Entity_Id;
3428 Build_Thunks : Boolean;
3429 Result : List_Id)
725a69d2 3430 is
3431 Loc : constant Source_Ptr := Sloc (Typ);
f301a57b 3432 Exporting_Table : constant Boolean :=
3433 Building_Static_DT (Typ)
3434 and then Suffix_Index > 0;
725a69d2 3435 Iface_DT : constant Entity_Id :=
f301a57b 3436 Make_Defining_Identifier (Loc,
3437 Chars => New_Internal_Name ('T'));
725a69d2 3438 Name_Predef_Prims : constant Name_Id := New_Internal_Name ('R');
3439 Predef_Prims : constant Entity_Id :=
3440 Make_Defining_Identifier (Loc,
f301a57b 3441 Chars => Name_Predef_Prims);
725a69d2 3442 DT_Constr_List : List_Id;
3443 DT_Aggr_List : List_Id;
3444 Empty_DT : Boolean := False;
3445 Nb_Predef_Prims : Nat := 0;
3446 Nb_Prim : Nat;
3447 New_Node : Node_Id;
3448 OSD : Entity_Id;
3449 OSD_Aggr_List : List_Id;
3450 Pos : Nat;
3451 Prim : Entity_Id;
3452 Prim_Elmt : Elmt_Id;
3453 Prim_Ops_Aggr_List : List_Id;
343d35dc 3454
725a69d2 3455 begin
17e14451 3456 -- Handle cases in which we do not generate statically allocated
3457 -- dispatch tables.
343d35dc 3458
24971415 3459 if not Building_Static_DT (Typ) then
725a69d2 3460 Set_Ekind (Predef_Prims, E_Variable);
725a69d2 3461 Set_Ekind (Iface_DT, E_Variable);
343d35dc 3462
725a69d2 3463 -- Statically allocated dispatch tables and related entities are
3464 -- constants.
343d35dc 3465
725a69d2 3466 else
3467 Set_Ekind (Predef_Prims, E_Constant);
3468 Set_Is_Statically_Allocated (Predef_Prims);
3469 Set_Is_True_Constant (Predef_Prims);
343d35dc 3470
725a69d2 3471 Set_Ekind (Iface_DT, E_Constant);
3472 Set_Is_Statically_Allocated (Iface_DT);
3473 Set_Is_True_Constant (Iface_DT);
343d35dc 3474 end if;
3475
f301a57b 3476 -- Calculate the number of slots of the dispatch table. If the number
3477 -- of primitives of Typ is 0 we reserve a dummy single entry for its
3478 -- DT because at run-time the pointer to this dummy entry will be
3479 -- used as the tag.
68f95949 3480
cdb1c38f 3481 if Num_Iface_Prims = 0 then
725a69d2 3482 Empty_DT := True;
3483 Nb_Prim := 1;
cdb1c38f 3484 else
3485 Nb_Prim := Num_Iface_Prims;
725a69d2 3486 end if;
76a1c25b 3487
725a69d2 3488 -- Generate:
952af0b9 3489
725a69d2 3490 -- Predef_Prims : Address_Array (1 .. Default_Prim_Ops_Count) :=
3491 -- (predef-prim-op-thunk-1'address,
3492 -- predef-prim-op-thunk-2'address,
3493 -- ...
3494 -- predef-prim-op-thunk-n'address);
3495 -- for Predef_Prims'Alignment use Address'Alignment
952af0b9 3496
725a69d2 3497 -- Stage 1: Calculate the number of predefined primitives
76a1c25b 3498
24971415 3499 if not Building_Static_DT (Typ) then
725a69d2 3500 Nb_Predef_Prims := Max_Predef_Prims;
3501 else
3502 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3503 while Present (Prim_Elmt) loop
3504 Prim := Node (Prim_Elmt);
aad6babd 3505
725a69d2 3506 if Is_Predefined_Dispatching_Operation (Prim)
3507 and then not Is_Abstract_Subprogram (Prim)
3508 then
3509 Pos := UI_To_Int (DT_Position (Prim));
aad6babd 3510
725a69d2 3511 if Pos > Nb_Predef_Prims then
3512 Nb_Predef_Prims := Pos;
3513 end if;
3514 end if;
aad6babd 3515
725a69d2 3516 Next_Elmt (Prim_Elmt);
3517 end loop;
3518 end if;
aad6babd 3519
725a69d2 3520 -- Stage 2: Create the thunks associated with the predefined
3521 -- primitives and save their entity to fill the aggregate.
ee6ba406 3522
725a69d2 3523 declare
3524 Prim_Table : array (Nat range 1 .. Nb_Predef_Prims) of Entity_Id;
cc60bd16 3525 Decl : Node_Id;
725a69d2 3526 Thunk_Id : Entity_Id;
3527 Thunk_Code : Node_Id;
aad6babd 3528
725a69d2 3529 begin
3530 Prim_Ops_Aggr_List := New_List;
3531 Prim_Table := (others => Empty);
aad6babd 3532
cdb1c38f 3533 if Building_Static_DT (Typ) then
3534 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3535 while Present (Prim_Elmt) loop
3536 Prim := Node (Prim_Elmt);
aad6babd 3537
cdb1c38f 3538 if Is_Predefined_Dispatching_Operation (Prim)
3539 and then not Is_Abstract_Subprogram (Prim)
3540 and then not Present (Prim_Table
3541 (UI_To_Int (DT_Position (Prim))))
3542 then
3543 if not Build_Thunks then
3544 Prim_Table (UI_To_Int (DT_Position (Prim))) :=
3545 Alias (Prim);
aad6babd 3546
cdb1c38f 3547 else
3548 while Present (Alias (Prim)) loop
3549 Prim := Alias (Prim);
3550 end loop;
3551
3552 Expand_Interface_Thunk (Prim, Thunk_Id, Thunk_Code);
aad6babd 3553
cdb1c38f 3554 if Present (Thunk_Id) then
3555 Append_To (Result, Thunk_Code);
3556 Prim_Table (UI_To_Int (DT_Position (Prim)))
3557 := Thunk_Id;
3558 end if;
3559 end if;
725a69d2 3560 end if;
aad6babd 3561
cdb1c38f 3562 Next_Elmt (Prim_Elmt);
3563 end loop;
3564 end if;
aad6babd 3565
725a69d2 3566 for J in Prim_Table'Range loop
3567 if Present (Prim_Table (J)) then
3568 New_Node :=
cc60bd16 3569 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 3570 Make_Attribute_Reference (Loc,
3571 Prefix => New_Reference_To (Prim_Table (J), Loc),
3572 Attribute_Name => Name_Unrestricted_Access));
725a69d2 3573 else
cc60bd16 3574 New_Node := Make_Null (Loc);
725a69d2 3575 end if;
952af0b9 3576
725a69d2 3577 Append_To (Prim_Ops_Aggr_List, New_Node);
3578 end loop;
952af0b9 3579
cc60bd16 3580 New_Node :=
3581 Make_Aggregate (Loc,
3582 Expressions => Prim_Ops_Aggr_List);
3583
3584 -- Remember aggregates initializing dispatch tables
3585
3586 Append_Elmt (New_Node, DT_Aggr);
3587
3588 Decl :=
3589 Make_Subtype_Declaration (Loc,
3590 Defining_Identifier =>
3591 Make_Defining_Identifier (Loc,
3592 New_Internal_Name ('S')),
3593 Subtype_Indication =>
3594 New_Reference_To (RTE (RE_Address_Array), Loc));
3595
3596 Append_To (Result, Decl);
3597
725a69d2 3598 Append_To (Result,
3599 Make_Object_Declaration (Loc,
3600 Defining_Identifier => Predef_Prims,
24971415 3601 Constant_Present => Building_Static_DT (Typ),
725a69d2 3602 Aliased_Present => True,
cc60bd16 3603 Object_Definition => New_Reference_To
3604 (Defining_Identifier (Decl), Loc),
3605 Expression => New_Node));
aad6babd 3606
725a69d2 3607 Append_To (Result,
3608 Make_Attribute_Definition_Clause (Loc,
3609 Name => New_Reference_To (Predef_Prims, Loc),
3610 Chars => Name_Alignment,
3611 Expression =>
3612 Make_Attribute_Reference (Loc,
3613 Prefix =>
3614 New_Reference_To (RTE (RE_Integer_Address), Loc),
3615 Attribute_Name => Name_Alignment)));
3616 end;
aad6babd 3617
725a69d2 3618 -- Generate
76a1c25b 3619
725a69d2 3620 -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims) :=
3621 -- (OSD_Table => (1 => <value>,
3622 -- ...
3623 -- N => <value>));
76a1c25b 3624
725a69d2 3625 -- Iface_DT : Dispatch_Table (Nb_Prims) :=
3626 -- ([ Signature => <sig-value> ],
3627 -- Tag_Kind => <tag_kind-value>,
3628 -- Predef_Prims => Predef_Prims'Address,
3629 -- Offset_To_Top => 0,
3630 -- OSD => OSD'Address,
3631 -- Prims_Ptr => (prim-op-1'address,
3632 -- prim-op-2'address,
3633 -- ...
3634 -- prim-op-n'address));
f301a57b 3635 -- for Iface_DT'Alignment use Address'Alignment;
76a1c25b 3636
725a69d2 3637 -- Stage 3: Initialize the discriminant and the record components
aad6babd 3638
725a69d2 3639 DT_Constr_List := New_List;
3640 DT_Aggr_List := New_List;
343d35dc 3641
725a69d2 3642 -- Nb_Prim. If the tagged type has no primitives we add a dummy
3643 -- slot whose address will be the tag of this type.
343d35dc 3644
725a69d2 3645 if Nb_Prim = 0 then
3646 New_Node := Make_Integer_Literal (Loc, 1);
3647 else
3648 New_Node := Make_Integer_Literal (Loc, Nb_Prim);
3649 end if;
343d35dc 3650
725a69d2 3651 Append_To (DT_Constr_List, New_Node);
3652 Append_To (DT_Aggr_List, New_Copy (New_Node));
343d35dc 3653
725a69d2 3654 -- Signature
343d35dc 3655
725a69d2 3656 if RTE_Record_Component_Available (RE_Signature) then
3657 Append_To (DT_Aggr_List,
3658 New_Reference_To (RTE (RE_Secondary_DT), Loc));
3659 end if;
343d35dc 3660
725a69d2 3661 -- Tag_Kind
343d35dc 3662
725a69d2 3663 if RTE_Record_Component_Available (RE_Tag_Kind) then
3664 Append_To (DT_Aggr_List, Tagged_Kind (Typ));
3665 end if;
aad6babd 3666
725a69d2 3667 -- Predef_Prims
aad6babd 3668
725a69d2 3669 Append_To (DT_Aggr_List,
3670 Make_Attribute_Reference (Loc,
3671 Prefix => New_Reference_To (Predef_Prims, Loc),
3672 Attribute_Name => Name_Address));
aad6babd 3673
725a69d2 3674 -- Note: The correct value of Offset_To_Top will be set by the init
3675 -- subprogram
aad6babd 3676
725a69d2 3677 Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0));
aad6babd 3678
725a69d2 3679 -- Generate the Object Specific Data table required to dispatch calls
3680 -- through synchronized interfaces.
aad6babd 3681
725a69d2 3682 if Empty_DT
3683 or else Is_Abstract_Type (Typ)
3684 or else Is_Controlled (Typ)
3685 or else Restriction_Active (No_Dispatching_Calls)
3686 or else not Is_Limited_Type (Typ)
a652dd51 3687 or else not Has_Interfaces (Typ)
cdb1c38f 3688 or else not Build_Thunks
38d2fa31 3689 or else not RTE_Record_Component_Available (RE_OSD_Table)
725a69d2 3690 then
3691 -- No OSD table required
ee6ba406 3692
725a69d2 3693 Append_To (DT_Aggr_List,
3694 New_Reference_To (RTE (RE_Null_Address), Loc));
d62940bf 3695
725a69d2 3696 else
3697 OSD_Aggr_List := New_List;
d62940bf 3698
725a69d2 3699 declare
3700 Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id;
3701 Prim : Entity_Id;
3702 Prim_Alias : Entity_Id;
3703 Prim_Elmt : Elmt_Id;
3704 E : Entity_Id;
3705 Count : Nat := 0;
3706 Pos : Nat;
d62940bf 3707
725a69d2 3708 begin
3709 Prim_Table := (others => Empty);
3710 Prim_Alias := Empty;
d62940bf 3711
725a69d2 3712 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3713 while Present (Prim_Elmt) loop
3714 Prim := Node (Prim_Elmt);
d62940bf 3715
a652dd51 3716 if Present (Interface_Alias (Prim))
725a69d2 3717 and then Find_Dispatching_Type
a652dd51 3718 (Interface_Alias (Prim)) = Iface
725a69d2 3719 then
a652dd51 3720 Prim_Alias := Interface_Alias (Prim);
d62940bf 3721
725a69d2 3722 E := Prim;
3723 while Present (Alias (E)) loop
3724 E := Alias (E);
3725 end loop;
68f95949 3726
725a69d2 3727 Pos := UI_To_Int (DT_Position (Prim_Alias));
68f95949 3728
725a69d2 3729 if Present (Prim_Table (Pos)) then
3730 pragma Assert (Prim_Table (Pos) = E);
3731 null;
68f95949 3732
725a69d2 3733 else
3734 Prim_Table (Pos) := E;
3735
3736 Append_To (OSD_Aggr_List,
3737 Make_Component_Association (Loc,
3738 Choices => New_List (
3739 Make_Integer_Literal (Loc,
3740 DT_Position (Prim_Alias))),
3741 Expression =>
3742 Make_Integer_Literal (Loc,
3743 DT_Position (Alias (Prim)))));
3744
3745 Count := Count + 1;
3746 end if;
3747 end if;
3748
3749 Next_Elmt (Prim_Elmt);
3750 end loop;
3751 pragma Assert (Count = Nb_Prim);
3752 end;
3753
3754 OSD := Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
3755
3756 Append_To (Result,
3757 Make_Object_Declaration (Loc,
3758 Defining_Identifier => OSD,
3759 Object_Definition =>
3760 Make_Subtype_Indication (Loc,
3761 Subtype_Mark =>
3762 New_Reference_To (RTE (RE_Object_Specific_Data), Loc),
3763 Constraint =>
3764 Make_Index_Or_Discriminant_Constraint (Loc,
3765 Constraints => New_List (
3766 Make_Integer_Literal (Loc, Nb_Prim)))),
3767 Expression => Make_Aggregate (Loc,
3768 Component_Associations => New_List (
3769 Make_Component_Association (Loc,
3770 Choices => New_List (
3771 New_Occurrence_Of
3772 (RTE_Record_Component (RE_OSD_Num_Prims), Loc)),
3773 Expression =>
3774 Make_Integer_Literal (Loc, Nb_Prim)),
3775
3776 Make_Component_Association (Loc,
3777 Choices => New_List (
3778 New_Occurrence_Of
3779 (RTE_Record_Component (RE_OSD_Table), Loc)),
3780 Expression => Make_Aggregate (Loc,
3781 Component_Associations => OSD_Aggr_List))))));
3782
17e14451 3783 Append_To (Result,
3784 Make_Attribute_Definition_Clause (Loc,
3785 Name => New_Reference_To (OSD, Loc),
3786 Chars => Name_Alignment,
3787 Expression =>
3788 Make_Attribute_Reference (Loc,
3789 Prefix =>
3790 New_Reference_To (RTE (RE_Integer_Address), Loc),
3791 Attribute_Name => Name_Alignment)));
3792
725a69d2 3793 -- In secondary dispatch tables the Typeinfo component contains
3794 -- the address of the Object Specific Data (see a-tags.ads)
3795
3796 Append_To (DT_Aggr_List,
3797 Make_Attribute_Reference (Loc,
3798 Prefix => New_Reference_To (OSD, Loc),
3799 Attribute_Name => Name_Address));
3800 end if;
3801
3802 -- Initialize the table of primitive operations
3803
3804 Prim_Ops_Aggr_List := New_List;
3805
3806 if Empty_DT then
cc60bd16 3807 Append_To (Prim_Ops_Aggr_List, Make_Null (Loc));
725a69d2 3808
3809 elsif Is_Abstract_Type (Typ)
24971415 3810 or else not Building_Static_DT (Typ)
725a69d2 3811 then
3812 for J in 1 .. Nb_Prim loop
cc60bd16 3813 Append_To (Prim_Ops_Aggr_List, Make_Null (Loc));
725a69d2 3814 end loop;
3815
3816 else
3817 declare
3818 Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id;
3819 Pos : Nat;
3820 Thunk_Code : Node_Id;
3821 Thunk_Id : Entity_Id;
3822
3823 begin
3824 Prim_Table := (others => Empty);
3825
3826 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3827 while Present (Prim_Elmt) loop
3828 Prim := Node (Prim_Elmt);
3829
3830 if not Is_Predefined_Dispatching_Operation (Prim)
a652dd51 3831 and then Present (Interface_Alias (Prim))
725a69d2 3832 and then not Is_Abstract_Subprogram (Alias (Prim))
3833 and then not Is_Imported (Alias (Prim))
3834 and then Find_Dispatching_Type
a652dd51 3835 (Interface_Alias (Prim)) = Iface
725a69d2 3836
3837 -- Generate the code of the thunk only if the abstract
3838 -- interface type is not an immediate ancestor of
3839 -- Tagged_Type; otherwise the DT associated with the
3840 -- interface is the primary DT.
3841
a652dd51 3842 and then not Is_Ancestor (Iface, Typ)
725a69d2 3843 then
cdb1c38f 3844 if not Build_Thunks then
725a69d2 3845 Pos :=
a652dd51 3846 UI_To_Int (DT_Position (Interface_Alias (Prim)));
cdb1c38f 3847 Prim_Table (Pos) := Alias (Prim);
3848 else
3849 Expand_Interface_Thunk (Prim, Thunk_Id, Thunk_Code);
725a69d2 3850
cdb1c38f 3851 if Present (Thunk_Id) then
3852 Pos :=
a652dd51 3853 UI_To_Int (DT_Position (Interface_Alias (Prim)));
cdb1c38f 3854
3855 Prim_Table (Pos) := Thunk_Id;
3856 Append_To (Result, Thunk_Code);
3857 end if;
725a69d2 3858 end if;
3859 end if;
3860
3861 Next_Elmt (Prim_Elmt);
3862 end loop;
3863
3864 for J in Prim_Table'Range loop
3865 if Present (Prim_Table (J)) then
3866 New_Node :=
cc60bd16 3867 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 3868 Make_Attribute_Reference (Loc,
3869 Prefix => New_Reference_To (Prim_Table (J), Loc),
3870 Attribute_Name => Name_Unrestricted_Access));
725a69d2 3871 else
cc60bd16 3872 New_Node := Make_Null (Loc);
725a69d2 3873 end if;
3874
3875 Append_To (Prim_Ops_Aggr_List, New_Node);
3876 end loop;
3877 end;
3878 end if;
3879
cc60bd16 3880 New_Node :=
725a69d2 3881 Make_Aggregate (Loc,
cc60bd16 3882 Expressions => Prim_Ops_Aggr_List);
3883
3884 Append_To (DT_Aggr_List, New_Node);
3885
3886 -- Remember aggregates initializing dispatch tables
3887
3888 Append_Elmt (New_Node, DT_Aggr);
725a69d2 3889
f301a57b 3890 -- Note: Secondary dispatch tables cannot be declared constant
3891 -- because the component Offset_To_Top is currently initialized
3892 -- by the IP routine.
3893
725a69d2 3894 Append_To (Result,
3895 Make_Object_Declaration (Loc,
3896 Defining_Identifier => Iface_DT,
3897 Aliased_Present => True,
f301a57b 3898 Constant_Present => False,
3899
725a69d2 3900 Object_Definition =>
3901 Make_Subtype_Indication (Loc,
3902 Subtype_Mark => New_Reference_To
3903 (RTE (RE_Dispatch_Table_Wrapper), Loc),
3904 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
3905 Constraints => DT_Constr_List)),
3906
f301a57b 3907 Expression =>
3908 Make_Aggregate (Loc,
3909 Expressions => DT_Aggr_List)));
725a69d2 3910
17e14451 3911 Append_To (Result,
3912 Make_Attribute_Definition_Clause (Loc,
3913 Name => New_Reference_To (Iface_DT, Loc),
3914 Chars => Name_Alignment,
f301a57b 3915
17e14451 3916 Expression =>
3917 Make_Attribute_Reference (Loc,
f301a57b 3918 Prefix =>
17e14451 3919 New_Reference_To (RTE (RE_Integer_Address), Loc),
3920 Attribute_Name => Name_Alignment)));
3921
f301a57b 3922 if Exporting_Table then
3923 Export_DT (Typ, Iface_DT, Suffix_Index);
3924
725a69d2 3925 -- Generate code to create the pointer to the dispatch table
3926
f301a57b 3927 -- Iface_DT_Ptr : Tag := Tag!(DT.Prims_Ptr'Address);
725a69d2 3928
f301a57b 3929 -- Note: This declaration is not added here if the table is exported
3930 -- because in such case Make_Tags has already added this declaration.
3931
3932 else
3933 Append_To (Result,
3934 Make_Object_Declaration (Loc,
3935 Defining_Identifier => Iface_DT_Ptr,
3936 Constant_Present => True,
3937
3938 Object_Definition =>
3939 New_Reference_To (RTE (RE_Interface_Tag), Loc),
3940
3941 Expression =>
3942 Unchecked_Convert_To (RTE (RE_Interface_Tag),
3943 Make_Attribute_Reference (Loc,
3944 Prefix =>
3945 Make_Selected_Component (Loc,
3946 Prefix => New_Reference_To (Iface_DT, Loc),
3947 Selector_Name =>
3948 New_Occurrence_Of
3949 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
3950 Attribute_Name => Name_Address))));
3951 end if;
725a69d2 3952
acf97c11 3953 Append_To (Result,
3954 Make_Object_Declaration (Loc,
3955 Defining_Identifier => Predef_Prims_Ptr,
3956 Constant_Present => True,
f301a57b 3957
3958 Object_Definition =>
acf97c11 3959 New_Reference_To (RTE (RE_Address), Loc),
f301a57b 3960
3961 Expression =>
acf97c11 3962 Make_Attribute_Reference (Loc,
f301a57b 3963 Prefix =>
acf97c11 3964 Make_Selected_Component (Loc,
f301a57b 3965 Prefix => New_Reference_To (Iface_DT, Loc),
3966 Selector_Name =>
3967 New_Occurrence_Of
3968 (RTE_Record_Component (RE_Predef_Prims), Loc)),
acf97c11 3969 Attribute_Name => Name_Address)));
3970
cc60bd16 3971 -- Remember entities containing dispatch tables
acf97c11 3972
cc60bd16 3973 Append_Elmt (Predef_Prims, DT_Decl);
3974 Append_Elmt (Iface_DT, DT_Decl);
725a69d2 3975 end Make_Secondary_DT;
3976
3977 -- Local variables
3978
2ea346ac 3979 Elab_Code : constant List_Id := New_List;
3980 Result : constant List_Id := New_List;
3981 Tname : constant Name_Id := Chars (Typ);
725a69d2 3982 AI : Elmt_Id;
cdb1c38f 3983 AI_Tag_Elmt : Elmt_Id;
24971415 3984 AI_Tag_Comp : Elmt_Id;
f9162257 3985 DT_Aggr_List : List_Id;
24971415 3986 DT_Constr_List : List_Id;
725a69d2 3987 DT_Ptr : Entity_Id;
725a69d2 3988 ITable : Node_Id;
3989 I_Depth : Nat := 0;
3990 Iface_Table_Node : Node_Id;
3991 Name_ITable : Name_Id;
725a69d2 3992 Nb_Predef_Prims : Nat := 0;
3993 Nb_Prim : Nat := 0;
3994 New_Node : Node_Id;
725a69d2 3995 Num_Ifaces : Nat := 0;
cc60bd16 3996 Parent_Typ : Entity_Id;
725a69d2 3997 Prim : Entity_Id;
3998 Prim_Elmt : Elmt_Id;
3999 Prim_Ops_Aggr_List : List_Id;
725a69d2 4000 Suffix_Index : Int;
4001 Typ_Comps : Elist_Id;
4002 Typ_Ifaces : Elist_Id;
4003 TSD_Aggr_List : List_Id;
4004 TSD_Tags_List : List_Id;
17e14451 4005
4006 -- The following name entries are used by Make_DT to generate a number
4007 -- of entities related to a tagged type. These entities may be generated
4008 -- in a scope other than that of the tagged type declaration, and if
4009 -- the entities for two tagged types with the same name happen to be
4010 -- generated in the same scope, we have to take care to use different
4011 -- names. This is achieved by means of a unique serial number appended
4012 -- to each generated entity name.
4013
4014 Name_DT : constant Name_Id :=
4015 New_External_Name (Tname, 'T', Suffix_Index => -1);
4016 Name_Exname : constant Name_Id :=
4017 New_External_Name (Tname, 'E', Suffix_Index => -1);
e7e688dd 4018 Name_HT_Link : constant Name_Id :=
4019 New_External_Name (Tname, 'H', Suffix_Index => -1);
17e14451 4020 Name_Predef_Prims : constant Name_Id :=
4021 New_External_Name (Tname, 'R', Suffix_Index => -1);
4022 Name_SSD : constant Name_Id :=
4023 New_External_Name (Tname, 'S', Suffix_Index => -1);
4024 Name_TSD : constant Name_Id :=
4025 New_External_Name (Tname, 'B', Suffix_Index => -1);
4026
4027 -- Entities built with above names
4028
4029 DT : constant Entity_Id :=
4030 Make_Defining_Identifier (Loc, Name_DT);
4031 Exname : constant Entity_Id :=
4032 Make_Defining_Identifier (Loc, Name_Exname);
e7e688dd 4033 HT_Link : constant Entity_Id :=
4034 Make_Defining_Identifier (Loc, Name_HT_Link);
17e14451 4035 Predef_Prims : constant Entity_Id :=
4036 Make_Defining_Identifier (Loc, Name_Predef_Prims);
4037 SSD : constant Entity_Id :=
4038 Make_Defining_Identifier (Loc, Name_SSD);
4039 TSD : constant Entity_Id :=
4040 Make_Defining_Identifier (Loc, Name_TSD);
725a69d2 4041
4042 -- Start of processing for Make_DT
4043
4044 begin
17e14451 4045 pragma Assert (Is_Frozen (Typ));
725a69d2 4046
17e14451 4047 -- Handle cases in which there is no need to build the dispatch table
725a69d2 4048
17e14451 4049 if Has_Dispatch_Table (Typ)
4050 or else No (Access_Disp_Table (Typ))
4051 or else Is_CPP_Class (Typ)
4052 then
725a69d2 4053 return Result;
725a69d2 4054
17e14451 4055 elsif No_Run_Time_Mode then
4056 Error_Msg_CRT ("tagged types", Typ);
4057 return Result;
725a69d2 4058
17e14451 4059 elsif not RTE_Available (RE_Tag) then
725a69d2 4060 Append_To (Result,
4061 Make_Object_Declaration (Loc,
17e14451 4062 Defining_Identifier => Node (First_Elmt
4063 (Access_Disp_Table (Typ))),
725a69d2 4064 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
4065 Constant_Present => True,
4066 Expression =>
24971415 4067 Unchecked_Convert_To (RTE (RE_Tag),
725a69d2 4068 New_Reference_To (RTE (RE_Null_Address), Loc))));
4069
4070 Analyze_List (Result, Suppress => All_Checks);
4071 Error_Msg_CRT ("tagged types", Typ);
4072 return Result;
4073 end if;
4074
17e14451 4075 -- Ensure that the value of Max_Predef_Prims defined in a-tags is
cdb1c38f 4076 -- correct. Valid values are 10 under configurable runtime or 16
17e14451 4077 -- with full runtime.
4078
4079 if RTE_Available (RE_Interface_Data) then
cdb1c38f 4080 if Max_Predef_Prims /= 16 then
17e14451 4081 Error_Msg_N ("run-time library configuration error", Typ);
4082 return Result;
4083 end if;
725a69d2 4084 else
17e14451 4085 if Max_Predef_Prims /= 10 then
4086 Error_Msg_N ("run-time library configuration error", Typ);
4087 Error_Msg_CRT ("tagged types", Typ);
4088 return Result;
4089 end if;
725a69d2 4090 end if;
4091
cc60bd16 4092 -- Initialize Parent_Typ handling private types
4093
4094 Parent_Typ := Etype (Typ);
4095
4096 if Present (Full_View (Parent_Typ)) then
4097 Parent_Typ := Full_View (Parent_Typ);
4098 end if;
4099
17e14451 4100 -- Ensure that all the primitives are frozen. This is only required when
4101 -- building static dispatch tables --- the primitives must be frozen to
4102 -- be referenced (otherwise we have problems with the backend). It is
4103 -- not a requirement with nonstatic dispatch tables because in this case
4104 -- we generate now an empty dispatch table; the extra code required to
24971415 4105 -- register the primitives in the slots will be generated later --- when
17e14451 4106 -- each primitive is frozen (see Freeze_Subprogram).
725a69d2 4107
24971415 4108 if Building_Static_DT (Typ)
17e14451 4109 and then not Is_CPP_Class (Typ)
4110 then
4111 declare
4112 Save : constant Boolean := Freezing_Library_Level_Tagged_Type;
555c63a6 4113 Prim : Entity_Id;
17e14451 4114 Prim_Elmt : Elmt_Id;
4115 Frnodes : List_Id;
725a69d2 4116
17e14451 4117 begin
4118 Freezing_Library_Level_Tagged_Type := True;
555c63a6 4119
17e14451 4120 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
4121 while Present (Prim_Elmt) loop
555c63a6 4122 Prim := Node (Prim_Elmt);
4123 Frnodes := Freeze_Entity (Prim, Loc);
725a69d2 4124
17e14451 4125 declare
17e14451 4126 F : Entity_Id;
725a69d2 4127
17e14451 4128 begin
555c63a6 4129 F := First_Formal (Prim);
17e14451 4130 while Present (F) loop
555c63a6 4131 Check_Premature_Freezing (Prim, Etype (F));
17e14451 4132 Next_Formal (F);
4133 end loop;
4134
555c63a6 4135 Check_Premature_Freezing (Prim, Etype (Prim));
17e14451 4136 end;
4137
4138 if Present (Frnodes) then
4139 Append_List_To (Result, Frnodes);
4140 end if;
4141
4142 Next_Elmt (Prim_Elmt);
4143 end loop;
555c63a6 4144
17e14451 4145 Freezing_Library_Level_Tagged_Type := Save;
4146 end;
4147 end if;
725a69d2 4148
17e14451 4149 -- Ada 2005 (AI-251): Build the secondary dispatch tables
4150
a652dd51 4151 if Has_Interfaces (Typ) then
17e14451 4152 Collect_Interface_Components (Typ, Typ_Comps);
4153
f301a57b 4154 -- Each secondary dispatch table is assigned an unique positive
4155 -- suffix index; such value also corresponds with the location of
4156 -- its entity in the Dispatch_Table_Wrappers list (see Make_Tags).
4157
4158 -- Note: This value must be kept sync with the Suffix_Index values
4159 -- generated by Make_Tags
4160
4161 Suffix_Index := 1;
acf97c11 4162 AI_Tag_Elmt :=
4163 Next_Elmt (Next_Elmt (First_Elmt (Access_Disp_Table (Typ))));
17e14451 4164
4165 AI_Tag_Comp := First_Elmt (Typ_Comps);
4166 while Present (AI_Tag_Comp) loop
cdb1c38f 4167
4168 -- Build the secondary table containing pointers to thunks
4169
17e14451 4170 Make_Secondary_DT
cdb1c38f 4171 (Typ => Typ,
4172 Iface => Base_Type (Related_Type (Node (AI_Tag_Comp))),
f301a57b 4173 Suffix_Index => Suffix_Index,
cdb1c38f 4174 Num_Iface_Prims => UI_To_Int
4175 (DT_Entry_Count (Node (AI_Tag_Comp))),
4176 Iface_DT_Ptr => Node (AI_Tag_Elmt),
acf97c11 4177 Predef_Prims_Ptr => Node (Next_Elmt (AI_Tag_Elmt)),
cdb1c38f 4178 Build_Thunks => True,
4179 Result => Result);
cdb1c38f 4180
f301a57b 4181 -- Skip secondary dispatch table and secondary dispatch table of
4182 -- predefined primitives
acf97c11 4183
f301a57b 4184 Next_Elmt (AI_Tag_Elmt);
acf97c11 4185 Next_Elmt (AI_Tag_Elmt);
4186
36b938a3 4187 -- Build the secondary table containing pointers to primitives
cdb1c38f 4188 -- (used to give support to Generic Dispatching Constructors).
4189
4190 Make_Secondary_DT
4191 (Typ => Typ,
4192 Iface => Base_Type (Related_Type (Node (AI_Tag_Comp))),
f301a57b 4193 Suffix_Index => -1,
cdb1c38f 4194 Num_Iface_Prims => UI_To_Int
4195 (DT_Entry_Count (Node (AI_Tag_Comp))),
4196 Iface_DT_Ptr => Node (AI_Tag_Elmt),
acf97c11 4197 Predef_Prims_Ptr => Node (Next_Elmt (AI_Tag_Elmt)),
cdb1c38f 4198 Build_Thunks => False,
4199 Result => Result);
725a69d2 4200
f301a57b 4201 -- Skip secondary dispatch table and secondary dispatch table of
4202 -- predefined primitives
acf97c11 4203
f301a57b 4204 Next_Elmt (AI_Tag_Elmt);
acf97c11 4205 Next_Elmt (AI_Tag_Elmt);
4206
17e14451 4207 Suffix_Index := Suffix_Index + 1;
17e14451 4208 Next_Elmt (AI_Tag_Comp);
4209 end loop;
4210 end if;
725a69d2 4211
24971415 4212 -- Get the _tag entity and the number of primitives of its dispatch
4213 -- table.
725a69d2 4214
24971415 4215 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
4216 Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ)));
725a69d2 4217
2ea346ac 4218 Set_Is_Statically_Allocated (DT, Is_Library_Level_Tagged_Type (Typ));
4219 Set_Is_Statically_Allocated (SSD, Is_Library_Level_Tagged_Type (Typ));
4220 Set_Is_Statically_Allocated (TSD, Is_Library_Level_Tagged_Type (Typ));
4221 Set_Is_Statically_Allocated (Predef_Prims,
4222 Is_Library_Level_Tagged_Type (Typ));
725a69d2 4223
4224 -- In case of locally defined tagged type we declare the object
36b938a3 4225 -- containing the dispatch table by means of a variable. Its
725a69d2 4226 -- initialization is done later by means of an assignment. This is
4227 -- required to generate its External_Tag.
4228
24971415 4229 if not Building_Static_DT (Typ) then
725a69d2 4230
4231 -- Generate:
4232 -- DT : No_Dispatch_Table_Wrapper;
17e14451 4233 -- for DT'Alignment use Address'Alignment;
725a69d2 4234 -- DT_Ptr : Tag := !Tag (DT.NDT_Prims_Ptr'Address);
4235
24971415 4236 if not Has_DT (Typ) then
725a69d2 4237 Append_To (Result,
4238 Make_Object_Declaration (Loc,
4239 Defining_Identifier => DT,
4240 Aliased_Present => True,
4241 Constant_Present => False,
4242 Object_Definition =>
4243 New_Reference_To
4244 (RTE (RE_No_Dispatch_Table_Wrapper), Loc)));
4245
9af28f61 4246 -- Comment needed ???
4247
3dbca0d5 4248 if Generate_SCIL then
4249 Insert_Before (Last (Result),
4250 New_Scil_Node
4251 (Nkind => Dispatch_Table_Object_Init,
4252 Related_Node => Last (Result),
4253 Entity => Typ));
4254 end if;
4255
17e14451 4256 Append_To (Result,
4257 Make_Attribute_Definition_Clause (Loc,
4258 Name => New_Reference_To (DT, Loc),
4259 Chars => Name_Alignment,
4260 Expression =>
4261 Make_Attribute_Reference (Loc,
4262 Prefix =>
4263 New_Reference_To (RTE (RE_Integer_Address), Loc),
4264 Attribute_Name => Name_Alignment)));
4265
725a69d2 4266 Append_To (Result,
4267 Make_Object_Declaration (Loc,
4268 Defining_Identifier => DT_Ptr,
4269 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
4270 Constant_Present => True,
4271 Expression =>
24971415 4272 Unchecked_Convert_To (RTE (RE_Tag),
725a69d2 4273 Make_Attribute_Reference (Loc,
4274 Prefix =>
4275 Make_Selected_Component (Loc,
4276 Prefix => New_Reference_To (DT, Loc),
4277 Selector_Name =>
4278 New_Occurrence_Of
4279 (RTE_Record_Component (RE_NDT_Prims_Ptr), Loc)),
4280 Attribute_Name => Name_Address))));
4281
3dbca0d5 4282 if Generate_SCIL then
4283 Insert_Before (Last (Result),
4284 New_Scil_Node
4285 (Nkind => Dispatch_Table_Tag_Init,
4286 Related_Node => Last (Result),
4287 Entity => Typ));
4288 end if;
4289
725a69d2 4290 -- Generate:
4291 -- DT : Dispatch_Table_Wrapper (Nb_Prim);
4292 -- for DT'Alignment use Address'Alignment;
4293 -- DT_Ptr : Tag := !Tag (DT.Prims_Ptr'Address);
4294
4295 else
4296 -- If the tagged type has no primitives we add a dummy slot
4297 -- whose address will be the tag of this type.
4298
4299 if Nb_Prim = 0 then
4300 DT_Constr_List :=
4301 New_List (Make_Integer_Literal (Loc, 1));
4302 else
4303 DT_Constr_List :=
4304 New_List (Make_Integer_Literal (Loc, Nb_Prim));
4305 end if;
4306
4307 Append_To (Result,
4308 Make_Object_Declaration (Loc,
4309 Defining_Identifier => DT,
4310 Aliased_Present => True,
4311 Constant_Present => False,
4312 Object_Definition =>
4313 Make_Subtype_Indication (Loc,
4314 Subtype_Mark =>
4315 New_Reference_To (RTE (RE_Dispatch_Table_Wrapper), Loc),
4316 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
4317 Constraints => DT_Constr_List))));
4318
9af28f61 4319 -- Comment needed ???
4320
3dbca0d5 4321 if Generate_SCIL then
4322 Insert_Before (Last (Result),
4323 New_Scil_Node
4324 (Nkind => Dispatch_Table_Object_Init,
4325 Related_Node => Last (Result),
4326 Entity => Typ));
4327 end if;
4328
725a69d2 4329 Append_To (Result,
4330 Make_Attribute_Definition_Clause (Loc,
4331 Name => New_Reference_To (DT, Loc),
4332 Chars => Name_Alignment,
4333 Expression =>
4334 Make_Attribute_Reference (Loc,
4335 Prefix =>
4336 New_Reference_To (RTE (RE_Integer_Address), Loc),
4337 Attribute_Name => Name_Alignment)));
4338
4339 Append_To (Result,
4340 Make_Object_Declaration (Loc,
4341 Defining_Identifier => DT_Ptr,
4342 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
4343 Constant_Present => True,
4344 Expression =>
24971415 4345 Unchecked_Convert_To (RTE (RE_Tag),
725a69d2 4346 Make_Attribute_Reference (Loc,
4347 Prefix =>
4348 Make_Selected_Component (Loc,
4349 Prefix => New_Reference_To (DT, Loc),
4350 Selector_Name =>
4351 New_Occurrence_Of
4352 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
4353 Attribute_Name => Name_Address))));
acf97c11 4354
9af28f61 4355 -- Comment needed ???
4356
3dbca0d5 4357 if Generate_SCIL then
4358 Insert_Before (Last (Result),
4359 New_Scil_Node
4360 (Nkind => Dispatch_Table_Tag_Init,
4361 Related_Node => Last (Result),
4362 Entity => Typ));
4363 end if;
4364
acf97c11 4365 Append_To (Result,
4366 Make_Object_Declaration (Loc,
4367 Defining_Identifier =>
4368 Node (Next_Elmt (First_Elmt (Access_Disp_Table (Typ)))),
4369 Constant_Present => True,
4370 Object_Definition => New_Reference_To
4371 (RTE (RE_Address), Loc),
4372 Expression =>
4373 Make_Attribute_Reference (Loc,
4374 Prefix =>
4375 Make_Selected_Component (Loc,
4376 Prefix => New_Reference_To (DT, Loc),
4377 Selector_Name =>
4378 New_Occurrence_Of
4379 (RTE_Record_Component (RE_Predef_Prims), Loc)),
4380 Attribute_Name => Name_Address)));
725a69d2 4381 end if;
4382 end if;
4383
4384 -- Generate: Exname : constant String := full_qualified_name (typ);
343d35dc 4385 -- The type itself may be an anonymous parent type, so use the first
4386 -- subtype to have a user-recognizable name.
d62940bf 4387
343d35dc 4388 Append_To (Result,
4389 Make_Object_Declaration (Loc,
4390 Defining_Identifier => Exname,
4391 Constant_Present => True,
4392 Object_Definition => New_Reference_To (Standard_String, Loc),
4393 Expression =>
4394 Make_String_Literal (Loc,
4395 Full_Qualified_Name (First_Subtype (Typ)))));
d62940bf 4396
24971415 4397 Set_Is_Statically_Allocated (Exname);
4398 Set_Is_True_Constant (Exname);
4399
e7e688dd 4400 -- Declare the object used by Ada.Tags.Register_Tag
4401
4402 if RTE_Available (RE_Register_Tag) then
4403 Append_To (Result,
4404 Make_Object_Declaration (Loc,
4405 Defining_Identifier => HT_Link,
4406 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc)));
4407 end if;
4408
725a69d2 4409 -- Generate code to create the storage for the type specific data object
4410 -- with enough space to store the tags of the ancestors plus the tags
4411 -- of all the implemented interfaces (as described in a-tags.adb).
4412
4413 -- TSD : Type_Specific_Data (I_Depth) :=
4414 -- (Idepth => I_Depth,
4415 -- Access_Level => Type_Access_Level (Typ),
4416 -- Expanded_Name => Cstring_Ptr!(Exname'Address))
4417 -- External_Tag => Cstring_Ptr!(Exname'Address))
e7e688dd 4418 -- HT_Link => HT_Link'Address,
725a69d2 4419 -- Transportable => <<boolean-value>>,
4420 -- RC_Offset => <<integer-value>>,
cc60bd16 4421 -- [ Size_Func => Size_Prim'Access ]
725a69d2 4422 -- [ Interfaces_Table => <<access-value>> ]
24971415 4423 -- [ SSD => SSD_Table'Address ]
725a69d2 4424 -- Tags_Table => (0 => null,
4425 -- 1 => Parent'Tag
4426 -- ...);
4427 -- for TSD'Alignment use Address'Alignment
4428
4429 TSD_Aggr_List := New_List;
4430
4431 -- Idepth: Count ancestors to compute the inheritance depth. For private
4432 -- extensions, always go to the full view in order to compute the real
4433 -- inheritance depth.
4434
4435 declare
4436 Current_Typ : Entity_Id;
4437 Parent_Typ : Entity_Id;
4438
4439 begin
4440 I_Depth := 0;
4441 Current_Typ := Typ;
4442 loop
4443 Parent_Typ := Etype (Current_Typ);
4444
4445 if Is_Private_Type (Parent_Typ) then
4446 Parent_Typ := Full_View (Base_Type (Parent_Typ));
4447 end if;
4448
4449 exit when Parent_Typ = Current_Typ;
4450
4451 I_Depth := I_Depth + 1;
4452 Current_Typ := Parent_Typ;
4453 end loop;
4454 end;
4455
4456 Append_To (TSD_Aggr_List,
17e14451 4457 Make_Integer_Literal (Loc, I_Depth));
725a69d2 4458
4459 -- Access_Level
4460
4461 Append_To (TSD_Aggr_List,
17e14451 4462 Make_Integer_Literal (Loc, Type_Access_Level (Typ)));
725a69d2 4463
4464 -- Expanded_Name
4465
4466 Append_To (TSD_Aggr_List,
17e14451 4467 Unchecked_Convert_To (RTE (RE_Cstring_Ptr),
4468 Make_Attribute_Reference (Loc,
4469 Prefix => New_Reference_To (Exname, Loc),
4470 Attribute_Name => Name_Address)));
725a69d2 4471
4472 -- External_Tag of a local tagged type
4473
17e14451 4474 -- <typ>A : constant String :=
725a69d2 4475 -- "Internal tag at 16#tag-addr#: <full-name-of-typ>";
4476
4477 -- The reason we generate this strange name is that we do not want to
4478 -- enter local tagged types in the global hash table used to compute
4479 -- the Internal_Tag attribute for two reasons:
4480
4481 -- 1. It is hard to avoid a tasking race condition for entering the
4482 -- entry into the hash table.
4483
4484 -- 2. It would cause a storage leak, unless we rig up considerable
4485 -- mechanism to remove the entry from the hash table on exit.
4486
4487 -- So what we do is to generate the above external tag name, where the
4488 -- hex address is the address of the local dispatch table (i.e. exactly
4489 -- the value we want if Internal_Tag is computed from this string).
4490
4491 -- Of course this value will only be valid if the tagged type is still
4492 -- in scope, but it clearly must be erroneous to compute the internal
4493 -- tag of a tagged type that is out of scope!
4494
17e14451 4495 -- We don't do this processing if an explicit external tag has been
4496 -- specified. That's an odd case for which we have already issued a
4497 -- warning, where we will not be able to compute the internal tag.
4498
4499 if not Is_Library_Level_Entity (Typ)
4500 and then not Has_External_Tag_Rep_Clause (Typ)
4501 then
725a69d2 4502 declare
725a69d2 4503 Exname : constant Entity_Id :=
17e14451 4504 Make_Defining_Identifier (Loc,
4505 New_External_Name (Tname, 'A'));
4506
725a69d2 4507 Full_Name : constant String_Id :=
4508 Full_Qualified_Name (First_Subtype (Typ));
4509 Str1_Id : String_Id;
4510 Str2_Id : String_Id;
725a69d2 4511
4512 begin
4513 -- Generate:
17e14451 4514 -- Str1 = "Internal tag at 16#";
725a69d2 4515
4516 Start_String;
4517 Store_String_Chars ("Internal tag at 16#");
4518 Str1_Id := End_String;
4519
4520 -- Generate:
17e14451 4521 -- Str2 = "#: <type-full-name>";
725a69d2 4522
4523 Start_String;
4524 Store_String_Chars ("#: ");
725a69d2 4525 Store_String_Chars (Full_Name);
17e14451 4526 Str2_Id := End_String;
725a69d2 4527
4528 -- Generate:
4529 -- Exname : constant String :=
17e14451 4530 -- Str1 & Address_Image (Tag) & Str2;
725a69d2 4531
4532 if RTE_Available (RE_Address_Image) then
4533 Append_To (Result,
4534 Make_Object_Declaration (Loc,
4535 Defining_Identifier => Exname,
4536 Constant_Present => True,
4537 Object_Definition => New_Reference_To
4538 (Standard_String, Loc),
4539 Expression =>
4540 Make_Op_Concat (Loc,
4541 Left_Opnd =>
4542 Make_String_Literal (Loc, Str1_Id),
4543 Right_Opnd =>
4544 Make_Op_Concat (Loc,
4545 Left_Opnd =>
4546 Make_Function_Call (Loc,
4547 Name =>
4548 New_Reference_To
4549 (RTE (RE_Address_Image), Loc),
4550 Parameter_Associations => New_List (
4551 Unchecked_Convert_To (RTE (RE_Address),
4552 New_Reference_To (DT_Ptr, Loc)))),
4553 Right_Opnd =>
17e14451 4554 Make_String_Literal (Loc, Str2_Id)))));
4555
725a69d2 4556 else
4557 Append_To (Result,
4558 Make_Object_Declaration (Loc,
4559 Defining_Identifier => Exname,
4560 Constant_Present => True,
4561 Object_Definition => New_Reference_To
4562 (Standard_String, Loc),
4563 Expression =>
4564 Make_Op_Concat (Loc,
4565 Left_Opnd =>
4566 Make_String_Literal (Loc, Str1_Id),
4567 Right_Opnd =>
17e14451 4568 Make_String_Literal (Loc, Str2_Id))));
725a69d2 4569 end if;
4570
4571 New_Node :=
4572 Unchecked_Convert_To (RTE (RE_Cstring_Ptr),
4573 Make_Attribute_Reference (Loc,
4574 Prefix => New_Reference_To (Exname, Loc),
4575 Attribute_Name => Name_Address));
4576 end;
4577
4578 -- External tag of a library-level tagged type: Check for a definition
4579 -- of External_Tag. The clause is considered only if it applies to this
4580 -- specific tagged type, as opposed to one of its ancestors.
cc60bd16 4581 -- If the type is an unconstrained type extension, we are building the
4582 -- dispatch table of its anonymous base type, so the external tag, if
34fd8639 4583 -- any was specified, must be retrieved from the first subtype. Go to
4584 -- the full view in case the clause is in the private part.
725a69d2 4585
4586 else
4587 declare
cc60bd16 4588 Def : constant Node_Id := Get_Attribute_Definition_Clause
34fd8639 4589 (Underlying_Type (First_Subtype (Typ)),
cc60bd16 4590 Attribute_External_Tag);
4591
725a69d2 4592 Old_Val : String_Id;
4593 New_Val : String_Id;
4594 E : Entity_Id;
4595
4596 begin
4597 if not Present (Def)
cc60bd16 4598 or else Entity (Name (Def)) /= First_Subtype (Typ)
725a69d2 4599 then
4600 New_Node :=
4601 Unchecked_Convert_To (RTE (RE_Cstring_Ptr),
4602 Make_Attribute_Reference (Loc,
cc60bd16 4603 Prefix => New_Reference_To (Exname, Loc),
725a69d2 4604 Attribute_Name => Name_Address));
4605 else
4606 Old_Val := Strval (Expr_Value_S (Expression (Def)));
4607
17e14451 4608 -- For the rep clause "for <typ>'external_tag use y" generate:
725a69d2 4609
17e14451 4610 -- <typ>A : constant string := y;
4611 --
4612 -- <typ>A'Address is used to set the External_Tag component
4613 -- of the TSD
725a69d2 4614
4615 -- Create a new nul terminated string if it is not already
4616
4617 if String_Length (Old_Val) > 0
4618 and then
4619 Get_String_Char (Old_Val, String_Length (Old_Val)) = 0
4620 then
4621 New_Val := Old_Val;
4622 else
4623 Start_String (Old_Val);
4624 Store_String_Char (Get_Char_Code (ASCII.NUL));
4625 New_Val := End_String;
4626 end if;
4627
4628 E := Make_Defining_Identifier (Loc,
4629 New_External_Name (Chars (Typ), 'A'));
4630
4631 Append_To (Result,
4632 Make_Object_Declaration (Loc,
4633 Defining_Identifier => E,
4634 Constant_Present => True,
4635 Object_Definition =>
4636 New_Reference_To (Standard_String, Loc),
4637 Expression =>
4638 Make_String_Literal (Loc, New_Val)));
4639
4640 New_Node :=
4641 Unchecked_Convert_To (RTE (RE_Cstring_Ptr),
4642 Make_Attribute_Reference (Loc,
4643 Prefix => New_Reference_To (E, Loc),
4644 Attribute_Name => Name_Address));
4645 end if;
4646 end;
4647 end if;
4648
17e14451 4649 Append_To (TSD_Aggr_List, New_Node);
725a69d2 4650
4651 -- HT_Link
4652
e7e688dd 4653 if RTE_Available (RE_Register_Tag) then
4654 Append_To (TSD_Aggr_List,
4655 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
4656 Make_Attribute_Reference (Loc,
4657 Prefix => New_Reference_To (HT_Link, Loc),
4658 Attribute_Name => Name_Address)));
4659 else
4660 Append_To (TSD_Aggr_List,
4661 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
4662 New_Reference_To (RTE (RE_Null_Address), Loc)));
4663 end if;
725a69d2 4664
4665 -- Transportable: Set for types that can be used in remote calls
4666 -- with respect to E.4(18) legality rules.
4667
17e14451 4668 declare
4669 Transportable : Entity_Id;
725a69d2 4670
17e14451 4671 begin
4672 Transportable :=
4673 Boolean_Literals
4674 (Is_Pure (Typ)
4675 or else Is_Shared_Passive (Typ)
4676 or else
4677 ((Is_Remote_Types (Typ)
4678 or else Is_Remote_Call_Interface (Typ))
4679 and then Original_View_In_Visible_Part (Typ))
4680 or else not Comes_From_Source (Typ));
4681
4682 Append_To (TSD_Aggr_List,
4683 New_Occurrence_Of (Transportable, Loc));
4684 end;
725a69d2 4685
4686 -- RC_Offset: These are the valid values and their meaning:
4687
343d35dc 4688 -- >0: For simple types with controlled components is
4689 -- type._record_controller'position
725a69d2 4690
343d35dc 4691 -- 0: For types with no controlled components
725a69d2 4692
343d35dc 4693 -- -1: For complex types with controlled components where the position
4694 -- of the record controller is not statically computable but there
4695 -- are controlled components at this level. The _Controller field
4696 -- is available right after the _parent.
725a69d2 4697
343d35dc 4698 -- -2: There are no controlled components at this level. We need to
4699 -- get the position from the parent.
952af0b9 4700
17e14451 4701 declare
4702 RC_Offset_Node : Node_Id;
343d35dc 4703
17e14451 4704 begin
4705 if not Has_Controlled_Component (Typ) then
4706 RC_Offset_Node := Make_Integer_Literal (Loc, 0);
4707
4708 elsif Etype (Typ) /= Typ
cdb1c38f 4709 and then Has_Discriminants (Parent_Typ)
17e14451 4710 then
4711 if Has_New_Controlled_Component (Typ) then
4712 RC_Offset_Node := Make_Integer_Literal (Loc, -1);
4713 else
4714 RC_Offset_Node := Make_Integer_Literal (Loc, -2);
4715 end if;
343d35dc 4716 else
17e14451 4717 RC_Offset_Node :=
4718 Make_Attribute_Reference (Loc,
4719 Prefix =>
4720 Make_Selected_Component (Loc,
4721 Prefix => New_Reference_To (Typ, Loc),
4722 Selector_Name =>
4723 New_Reference_To (Controller_Component (Typ), Loc)),
4724 Attribute_Name => Name_Position);
4725
4726 -- This is not proper Ada code to use the attribute 'Position
4727 -- on something else than an object but this is supported by
4728 -- the back end (see comment on the Bit_Component attribute in
4729 -- sem_attr). So we avoid semantic checking here.
4730
4731 -- Is this documented in sinfo.ads??? it should be!
4732
4733 Set_Analyzed (RC_Offset_Node);
4734 Set_Etype (Prefix (RC_Offset_Node), RTE (RE_Record_Controller));
4735 Set_Etype (Prefix (Prefix (RC_Offset_Node)), Typ);
4736 Set_Etype (Selector_Name (Prefix (RC_Offset_Node)),
4737 RTE (RE_Record_Controller));
4738 Set_Etype (RC_Offset_Node, RTE (RE_Storage_Offset));
68f95949 4739 end if;
952af0b9 4740
17e14451 4741 Append_To (TSD_Aggr_List, RC_Offset_Node);
4742 end;
725a69d2 4743
cc60bd16 4744 -- Size_Func
4745
4746 if RTE_Record_Component_Available (RE_Size_Func) then
4747 if not Building_Static_DT (Typ)
4748 or else Is_Interface (Typ)
4749 then
4750 Append_To (TSD_Aggr_List,
4751 Unchecked_Convert_To (RTE (RE_Size_Ptr),
4752 New_Reference_To (RTE (RE_Null_Address), Loc)));
4753
4754 else
4755 declare
4756 Prim_Elmt : Elmt_Id;
4757 Prim : Entity_Id;
4758
4759 begin
4760 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
4761 while Present (Prim_Elmt) loop
4762 Prim := Node (Prim_Elmt);
4763
4764 if Chars (Prim) = Name_uSize then
4765 while Present (Alias (Prim)) loop
4766 Prim := Alias (Prim);
4767 end loop;
4768
4769 if Is_Abstract_Subprogram (Prim) then
4770 Append_To (TSD_Aggr_List,
4771 Unchecked_Convert_To (RTE (RE_Size_Ptr),
4772 New_Reference_To (RTE (RE_Null_Address), Loc)));
4773 else
4774 Append_To (TSD_Aggr_List,
4775 Unchecked_Convert_To (RTE (RE_Size_Ptr),
4776 Make_Attribute_Reference (Loc,
4777 Prefix => New_Reference_To (Prim, Loc),
4778 Attribute_Name => Name_Unrestricted_Access)));
4779 end if;
4780
4781 exit;
4782 end if;
4783
4784 Next_Elmt (Prim_Elmt);
4785 end loop;
4786 end;
4787 end if;
4788 end if;
4789
725a69d2 4790 -- Interfaces_Table (required for AI-405)
4791
4792 if RTE_Record_Component_Available (RE_Interfaces_Table) then
4793
4794 -- Count the number of interface types implemented by Typ
4795
a652dd51 4796 Collect_Interfaces (Typ, Typ_Ifaces);
725a69d2 4797
4798 AI := First_Elmt (Typ_Ifaces);
4799 while Present (AI) loop
4800 Num_Ifaces := Num_Ifaces + 1;
4801 Next_Elmt (AI);
4802 end loop;
952af0b9 4803
343d35dc 4804 if Num_Ifaces = 0 then
725a69d2 4805 Iface_Table_Node := Make_Null (Loc);
952af0b9 4806
725a69d2 4807 -- Generate the Interface_Table object
343d35dc 4808
4809 else
725a69d2 4810 declare
17e14451 4811 TSD_Ifaces_List : constant List_Id := New_List;
cdb1c38f 4812 Elmt : Elmt_Id;
4813 Sec_DT_Tag : Node_Id;
725a69d2 4814
4815 begin
4816 AI := First_Elmt (Typ_Ifaces);
4817 while Present (AI) loop
a652dd51 4818 if Is_Ancestor (Node (AI), Typ) then
cdb1c38f 4819 Sec_DT_Tag :=
4820 New_Reference_To (DT_Ptr, Loc);
4821 else
acf97c11 4822 Elmt :=
4823 Next_Elmt
4824 (Next_Elmt (First_Elmt (Access_Disp_Table (Typ))));
cdb1c38f 4825 pragma Assert (Has_Thunks (Node (Elmt)));
4826
4827 while Ekind (Node (Elmt)) = E_Constant
4828 and then not
a652dd51 4829 Is_Ancestor (Node (AI), Related_Type (Node (Elmt)))
cdb1c38f 4830 loop
4831 pragma Assert (Has_Thunks (Node (Elmt)));
4832 Next_Elmt (Elmt);
acf97c11 4833 pragma Assert (Has_Thunks (Node (Elmt)));
4834 Next_Elmt (Elmt);
4835 pragma Assert (not Has_Thunks (Node (Elmt)));
4836 Next_Elmt (Elmt);
cdb1c38f 4837 pragma Assert (not Has_Thunks (Node (Elmt)));
4838 Next_Elmt (Elmt);
4839 end loop;
4840
4841 pragma Assert (Ekind (Node (Elmt)) = E_Constant
acf97c11 4842 and then not
4843 Has_Thunks (Node (Next_Elmt (Next_Elmt (Elmt)))));
cdb1c38f 4844 Sec_DT_Tag :=
acf97c11 4845 New_Reference_To (Node (Next_Elmt (Next_Elmt (Elmt))),
4846 Loc);
cdb1c38f 4847 end if;
4848
17e14451 4849 Append_To (TSD_Ifaces_List,
4850 Make_Aggregate (Loc,
4851 Expressions => New_List (
4852
4853 -- Iface_Tag
4854
24971415 4855 Unchecked_Convert_To (RTE (RE_Tag),
725a69d2 4856 New_Reference_To
4857 (Node (First_Elmt (Access_Disp_Table (Node (AI)))),
17e14451 4858 Loc)),
725a69d2 4859
17e14451 4860 -- Static_Offset_To_Top
725a69d2 4861
17e14451 4862 New_Reference_To (Standard_True, Loc),
725a69d2 4863
17e14451 4864 -- Offset_To_Top_Value
4865
4866 Make_Integer_Literal (Loc, 0),
4867
4868 -- Offset_To_Top_Func
4869
cdb1c38f 4870 Make_Null (Loc),
4871
4872 -- Secondary_DT
4873
4874 Unchecked_Convert_To (RTE (RE_Tag), Sec_DT_Tag)
4875
4876 )));
725a69d2 4877
725a69d2 4878 Next_Elmt (AI);
4879 end loop;
725a69d2 4880
17e14451 4881 Name_ITable := New_External_Name (Tname, 'I');
4882 ITable := Make_Defining_Identifier (Loc, Name_ITable);
2ea346ac 4883 Set_Is_Statically_Allocated (ITable,
4884 Is_Library_Level_Tagged_Type (Typ));
725a69d2 4885
17e14451 4886 -- The table of interfaces is not constant; its slots are
4887 -- filled at run-time by the IP routine using attribute
4888 -- 'Position to know the location of the tag components
4889 -- (and this attribute cannot be safely used before the
4890 -- object is initialized).
725a69d2 4891
17e14451 4892 Append_To (Result,
4893 Make_Object_Declaration (Loc,
4894 Defining_Identifier => ITable,
4895 Aliased_Present => True,
4896 Constant_Present => False,
4897 Object_Definition =>
4898 Make_Subtype_Indication (Loc,
4899 Subtype_Mark =>
4900 New_Reference_To (RTE (RE_Interface_Data), Loc),
4901 Constraint => Make_Index_Or_Discriminant_Constraint
4902 (Loc,
4903 Constraints => New_List (
4904 Make_Integer_Literal (Loc, Num_Ifaces)))),
725a69d2 4905
17e14451 4906 Expression => Make_Aggregate (Loc,
4907 Expressions => New_List (
4908 Make_Integer_Literal (Loc, Num_Ifaces),
4909 Make_Aggregate (Loc,
4910 Expressions => TSD_Ifaces_List)))));
725a69d2 4911
17e14451 4912 Append_To (Result,
4913 Make_Attribute_Definition_Clause (Loc,
4914 Name => New_Reference_To (ITable, Loc),
4915 Chars => Name_Alignment,
4916 Expression =>
4917 Make_Attribute_Reference (Loc,
4918 Prefix =>
4919 New_Reference_To (RTE (RE_Integer_Address), Loc),
4920 Attribute_Name => Name_Alignment)));
725a69d2 4921
17e14451 4922 Iface_Table_Node :=
4923 Make_Attribute_Reference (Loc,
4924 Prefix => New_Reference_To (ITable, Loc),
4925 Attribute_Name => Name_Unchecked_Access);
4926 end;
725a69d2 4927 end if;
4928
17e14451 4929 Append_To (TSD_Aggr_List, Iface_Table_Node);
725a69d2 4930 end if;
4931
4932 -- Generate the Select Specific Data table for synchronized types that
4933 -- implement synchronized interfaces. The size of the table is
4934 -- constrained by the number of non-predefined primitive operations.
4935
4936 if RTE_Record_Component_Available (RE_SSD) then
4937 if Ada_Version >= Ada_05
24971415 4938 and then Has_DT (Typ)
725a69d2 4939 and then Is_Concurrent_Record_Type (Typ)
a652dd51 4940 and then Has_Interfaces (Typ)
725a69d2 4941 and then Nb_Prim > 0
4942 and then not Is_Abstract_Type (Typ)
4943 and then not Is_Controlled (Typ)
4944 and then not Restriction_Active (No_Dispatching_Calls)
f38c8084 4945 and then not Restriction_Active (No_Select_Statements)
725a69d2 4946 then
343d35dc 4947 Append_To (Result,
4948 Make_Object_Declaration (Loc,
725a69d2 4949 Defining_Identifier => SSD,
343d35dc 4950 Aliased_Present => True,
4951 Object_Definition =>
4952 Make_Subtype_Indication (Loc,
725a69d2 4953 Subtype_Mark => New_Reference_To (
4954 RTE (RE_Select_Specific_Data), Loc),
4955 Constraint =>
4956 Make_Index_Or_Discriminant_Constraint (Loc,
4957 Constraints => New_List (
4958 Make_Integer_Literal (Loc, Nb_Prim))))));
4959
17e14451 4960 Append_To (Result,
4961 Make_Attribute_Definition_Clause (Loc,
4962 Name => New_Reference_To (SSD, Loc),
4963 Chars => Name_Alignment,
4964 Expression =>
4965 Make_Attribute_Reference (Loc,
4966 Prefix =>
4967 New_Reference_To (RTE (RE_Integer_Address), Loc),
4968 Attribute_Name => Name_Alignment)));
4969
725a69d2 4970 -- This table is initialized by Make_Select_Specific_Data_Table,
4971 -- which calls Set_Entry_Index and Set_Prim_Op_Kind.
4972
4973 Append_To (TSD_Aggr_List,
17e14451 4974 Make_Attribute_Reference (Loc,
4975 Prefix => New_Reference_To (SSD, Loc),
4976 Attribute_Name => Name_Unchecked_Access));
725a69d2 4977 else
17e14451 4978 Append_To (TSD_Aggr_List, Make_Null (Loc));
343d35dc 4979 end if;
952af0b9 4980 end if;
4981
725a69d2 4982 -- Initialize the table of ancestor tags. In case of interface types
4983 -- this table is not needed.
d62940bf 4984
cc60bd16 4985 TSD_Tags_List := New_List;
952af0b9 4986
cc60bd16 4987 -- If we are not statically allocating the dispatch table then we must
4988 -- fill position 0 with null because we still have not generated the
4989 -- tag of Typ.
343d35dc 4990
cc60bd16 4991 if not Building_Static_DT (Typ)
4992 or else Is_Interface (Typ)
4993 then
4994 Append_To (TSD_Tags_List,
4995 Unchecked_Convert_To (RTE (RE_Tag),
4996 New_Reference_To (RTE (RE_Null_Address), Loc)));
343d35dc 4997
cc60bd16 4998 -- Otherwise we can safely reference the tag
343d35dc 4999
cc60bd16 5000 else
5001 Append_To (TSD_Tags_List,
5002 New_Reference_To (DT_Ptr, Loc));
5003 end if;
343d35dc 5004
cc60bd16 5005 -- Fill the rest of the table with the tags of the ancestors
343d35dc 5006
cc60bd16 5007 declare
5008 Current_Typ : Entity_Id;
5009 Parent_Typ : Entity_Id;
5010 Pos : Nat;
725a69d2 5011
cc60bd16 5012 begin
17e14451 5013 Pos := 1;
5014 Current_Typ := Typ;
725a69d2 5015
17e14451 5016 loop
5017 Parent_Typ := Etype (Current_Typ);
343d35dc 5018
17e14451 5019 if Is_Private_Type (Parent_Typ) then
5020 Parent_Typ := Full_View (Base_Type (Parent_Typ));
5021 end if;
5022
5023 exit when Parent_Typ = Current_Typ;
5024
5025 if Is_CPP_Class (Parent_Typ)
5026 or else Is_Interface (Typ)
5027 then
5028 -- The tags defined in the C++ side will be inherited when
5029 -- the object is constructed (Exp_Ch3.Build_Init_Procedure)
5030
5031 Append_To (TSD_Tags_List,
5032 Unchecked_Convert_To (RTE (RE_Tag),
5033 New_Reference_To (RTE (RE_Null_Address), Loc)));
5034 else
5035 Append_To (TSD_Tags_List,
5036 New_Reference_To
5037 (Node (First_Elmt (Access_Disp_Table (Parent_Typ))),
5038 Loc));
5039 end if;
5040
5041 Pos := Pos + 1;
5042 Current_Typ := Parent_Typ;
5043 end loop;
5044
5045 pragma Assert (Pos = I_Depth + 1);
5046 end;
5047
5048 Append_To (TSD_Aggr_List,
5049 Make_Aggregate (Loc,
5050 Expressions => TSD_Tags_List));
343d35dc 5051
725a69d2 5052 -- Build the TSD object
343d35dc 5053
5054 Append_To (Result,
5055 Make_Object_Declaration (Loc,
5056 Defining_Identifier => TSD,
5057 Aliased_Present => True,
24971415 5058 Constant_Present => Building_Static_DT (Typ),
343d35dc 5059 Object_Definition =>
5060 Make_Subtype_Indication (Loc,
5061 Subtype_Mark => New_Reference_To (
5062 RTE (RE_Type_Specific_Data), Loc),
5063 Constraint =>
5064 Make_Index_Or_Discriminant_Constraint (Loc,
5065 Constraints => New_List (
5066 Make_Integer_Literal (Loc, I_Depth)))),
725a69d2 5067
343d35dc 5068 Expression => Make_Aggregate (Loc,
17e14451 5069 Expressions => TSD_Aggr_List)));
343d35dc 5070
24971415 5071 Set_Is_True_Constant (TSD, Building_Static_DT (Typ));
5072
343d35dc 5073 Append_To (Result,
5074 Make_Attribute_Definition_Clause (Loc,
5075 Name => New_Reference_To (TSD, Loc),
5076 Chars => Name_Alignment,
5077 Expression =>
5078 Make_Attribute_Reference (Loc,
5079 Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc),
5080 Attribute_Name => Name_Alignment)));
5081
24971415 5082 -- Initialize or declare the dispatch table object
343d35dc 5083
24971415 5084 if not Has_DT (Typ) then
725a69d2 5085 DT_Constr_List := New_List;
5086 DT_Aggr_List := New_List;
343d35dc 5087
725a69d2 5088 -- Typeinfo
952af0b9 5089
725a69d2 5090 New_Node :=
5091 Make_Attribute_Reference (Loc,
5092 Prefix => New_Reference_To (TSD, Loc),
5093 Attribute_Name => Name_Address);
5094
5095 Append_To (DT_Constr_List, New_Node);
5096 Append_To (DT_Aggr_List, New_Copy (New_Node));
5097 Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0));
5098
5099 -- In case of locally defined tagged types we have already declared
5100 -- and uninitialized object for the dispatch table, which is now
24971415 5101 -- initialized by means of the following assignment:
5102
5103 -- DT := (TSD'Address, 0);
725a69d2 5104
24971415 5105 if not Building_Static_DT (Typ) then
725a69d2 5106 Append_To (Result,
5107 Make_Assignment_Statement (Loc,
5108 Name => New_Reference_To (DT, Loc),
5109 Expression => Make_Aggregate (Loc,
5110 Expressions => DT_Aggr_List)));
5111
24971415 5112 -- In case of library level tagged types we declare and export now
5113 -- the constant object containing the dummy dispatch table. There
5114 -- is no need to declare the tag here because it has been previously
5115 -- declared by Make_Tags
5116
5117 -- DT : aliased constant No_Dispatch_Table :=
5118 -- (NDT_TSD => TSD'Address;
5119 -- NDT_Prims_Ptr => 0);
5120 -- for DT'Alignment use Address'Alignment;
725a69d2 5121
5122 else
5123 Append_To (Result,
5124 Make_Object_Declaration (Loc,
5125 Defining_Identifier => DT,
5126 Aliased_Present => True,
17e14451 5127 Constant_Present => True,
725a69d2 5128 Object_Definition =>
5129 New_Reference_To (RTE (RE_No_Dispatch_Table_Wrapper), Loc),
5130 Expression => Make_Aggregate (Loc,
5131 Expressions => DT_Aggr_List)));
5132
9af28f61 5133 -- Comment needed ???
5134
3dbca0d5 5135 if Generate_SCIL then
5136 Insert_Before (Last (Result),
5137 New_Scil_Node
5138 (Nkind => Dispatch_Table_Object_Init,
5139 Related_Node => Last (Result),
5140 Entity => Typ));
5141 end if;
5142
17e14451 5143 Append_To (Result,
5144 Make_Attribute_Definition_Clause (Loc,
5145 Name => New_Reference_To (DT, Loc),
5146 Chars => Name_Alignment,
5147 Expression =>
5148 Make_Attribute_Reference (Loc,
5149 Prefix =>
5150 New_Reference_To (RTE (RE_Integer_Address), Loc),
5151 Attribute_Name => Name_Alignment)));
5152
24971415 5153 Export_DT (Typ, DT);
725a69d2 5154 end if;
5155
5156 -- Common case: Typ has a dispatch table
5157
5158 -- Generate:
5159
5160 -- Predef_Prims : Address_Array (1 .. Default_Prim_Ops_Count) :=
5161 -- (predef-prim-op-1'address,
5162 -- predef-prim-op-2'address,
5163 -- ...
5164 -- predef-prim-op-n'address);
5165 -- for Predef_Prims'Alignment use Address'Alignment
5166
5167 -- DT : Dispatch_Table (Nb_Prims) :=
5168 -- (Signature => <sig-value>,
5169 -- Tag_Kind => <tag_kind-value>,
5170 -- Predef_Prims => Predef_Prims'First'Address,
5171 -- Offset_To_Top => 0,
5172 -- TSD => TSD'Address;
5173 -- Prims_Ptr => (prim-op-1'address,
5174 -- prim-op-2'address,
5175 -- ...
5176 -- prim-op-n'address));
17e14451 5177 -- for DT'Alignment use Address'Alignment
725a69d2 5178
5179 else
5180 declare
5181 Pos : Nat;
5182
5183 begin
24971415 5184 if not Building_Static_DT (Typ) then
725a69d2 5185 Nb_Predef_Prims := Max_Predef_Prims;
5186
5187 else
5188 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
5189 while Present (Prim_Elmt) loop
5190 Prim := Node (Prim_Elmt);
5191
5192 if Is_Predefined_Dispatching_Operation (Prim)
5193 and then not Is_Abstract_Subprogram (Prim)
5194 then
5195 Pos := UI_To_Int (DT_Position (Prim));
5196
5197 if Pos > Nb_Predef_Prims then
5198 Nb_Predef_Prims := Pos;
5199 end if;
5200 end if;
5201
5202 Next_Elmt (Prim_Elmt);
5203 end loop;
5204 end if;
5205
5206 declare
5207 Prim_Table : array
5208 (Nat range 1 .. Nb_Predef_Prims) of Entity_Id;
cc60bd16 5209 Decl : Node_Id;
725a69d2 5210 E : Entity_Id;
5211
5212 begin
5213 Prim_Ops_Aggr_List := New_List;
5214
5215 Prim_Table := (others => Empty);
17e14451 5216
cdb1c38f 5217 if Building_Static_DT (Typ) then
5218 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
5219 while Present (Prim_Elmt) loop
5220 Prim := Node (Prim_Elmt);
725a69d2 5221
cdb1c38f 5222 if Is_Predefined_Dispatching_Operation (Prim)
5223 and then not Is_Abstract_Subprogram (Prim)
5224 and then not Present (Prim_Table
5225 (UI_To_Int (DT_Position (Prim))))
5226 then
5227 E := Prim;
5228 while Present (Alias (E)) loop
5229 E := Alias (E);
5230 end loop;
725a69d2 5231
cdb1c38f 5232 pragma Assert (not Is_Abstract_Subprogram (E));
5233 Prim_Table (UI_To_Int (DT_Position (Prim))) := E;
5234 end if;
725a69d2 5235
cdb1c38f 5236 Next_Elmt (Prim_Elmt);
5237 end loop;
5238 end if;
725a69d2 5239
5240 for J in Prim_Table'Range loop
5241 if Present (Prim_Table (J)) then
5242 New_Node :=
cc60bd16 5243 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 5244 Make_Attribute_Reference (Loc,
5245 Prefix => New_Reference_To (Prim_Table (J), Loc),
5246 Attribute_Name => Name_Unrestricted_Access));
725a69d2 5247 else
cc60bd16 5248 New_Node := Make_Null (Loc);
725a69d2 5249 end if;
5250
5251 Append_To (Prim_Ops_Aggr_List, New_Node);
5252 end loop;
343d35dc 5253
cc60bd16 5254 New_Node :=
5255 Make_Aggregate (Loc,
5256 Expressions => Prim_Ops_Aggr_List);
5257
5258 Decl :=
5259 Make_Subtype_Declaration (Loc,
5260 Defining_Identifier =>
5261 Make_Defining_Identifier (Loc,
5262 New_Internal_Name ('S')),
5263 Subtype_Indication =>
5264 New_Reference_To (RTE (RE_Address_Array), Loc));
5265
5266 Append_To (Result, Decl);
5267
68f95949 5268 Append_To (Result,
5269 Make_Object_Declaration (Loc,
725a69d2 5270 Defining_Identifier => Predef_Prims,
68f95949 5271 Aliased_Present => True,
24971415 5272 Constant_Present => Building_Static_DT (Typ),
cc60bd16 5273 Object_Definition => New_Reference_To
5274 (Defining_Identifier (Decl), Loc),
5275 Expression => New_Node));
5276
5277 -- Remember aggregates initializing dispatch tables
5278
5279 Append_Elmt (New_Node, DT_Aggr);
725a69d2 5280
5281 Append_To (Result,
5282 Make_Attribute_Definition_Clause (Loc,
5283 Name => New_Reference_To (Predef_Prims, Loc),
5284 Chars => Name_Alignment,
5285 Expression =>
5286 Make_Attribute_Reference (Loc,
5287 Prefix =>
5288 New_Reference_To (RTE (RE_Integer_Address), Loc),
5289 Attribute_Name => Name_Alignment)));
5290 end;
5291 end;
5292
5293 -- Stage 1: Initialize the discriminant and the record components
5294
5295 DT_Constr_List := New_List;
5296 DT_Aggr_List := New_List;
5297
5298 -- Num_Prims. If the tagged type has no primitives we add a dummy
5299 -- slot whose address will be the tag of this type.
5300
5301 if Nb_Prim = 0 then
5302 New_Node := Make_Integer_Literal (Loc, 1);
5303 else
5304 New_Node := Make_Integer_Literal (Loc, Nb_Prim);
5305 end if;
5306
5307 Append_To (DT_Constr_List, New_Node);
5308 Append_To (DT_Aggr_List, New_Copy (New_Node));
5309
5310 -- Signature
5311
5312 if RTE_Record_Component_Available (RE_Signature) then
5313 Append_To (DT_Aggr_List,
5314 New_Reference_To (RTE (RE_Primary_DT), Loc));
5315 end if;
5316
5317 -- Tag_Kind
5318
5319 if RTE_Record_Component_Available (RE_Tag_Kind) then
5320 Append_To (DT_Aggr_List, Tagged_Kind (Typ));
5321 end if;
5322
5323 -- Predef_Prims
5324
5325 Append_To (DT_Aggr_List,
5326 Make_Attribute_Reference (Loc,
5327 Prefix => New_Reference_To (Predef_Prims, Loc),
5328 Attribute_Name => Name_Address));
5329
5330 -- Offset_To_Top
5331
cc60bd16 5332 Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0));
725a69d2 5333
5334 -- Typeinfo
5335
5336 Append_To (DT_Aggr_List,
5337 Make_Attribute_Reference (Loc,
5338 Prefix => New_Reference_To (TSD, Loc),
5339 Attribute_Name => Name_Address));
5340
5341 -- Stage 2: Initialize the table of primitive operations
5342
5343 Prim_Ops_Aggr_List := New_List;
5344
5345 if Nb_Prim = 0 then
cc60bd16 5346 Append_To (Prim_Ops_Aggr_List, Make_Null (Loc));
725a69d2 5347
24971415 5348 elsif not Building_Static_DT (Typ) then
725a69d2 5349 for J in 1 .. Nb_Prim loop
cc60bd16 5350 Append_To (Prim_Ops_Aggr_List, Make_Null (Loc));
725a69d2 5351 end loop;
5352
5353 else
5354 declare
5355 Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id;
5356 E : Entity_Id;
5357 Prim : Entity_Id;
5358 Prim_Elmt : Elmt_Id;
5359
5360 begin
5361 Prim_Table := (others => Empty);
cdb1c38f 5362
5363 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
725a69d2 5364 while Present (Prim_Elmt) loop
5365 Prim := Node (Prim_Elmt);
5366
9429b6e9 5367 -- Retrieve the ultimate alias of the primitive for proper
5368 -- handling of renamings and eliminated primitives.
5369
5370 E := Ultimate_Alias (Prim);
5371
725a69d2 5372 if Is_Imported (Prim)
a652dd51 5373 or else Present (Interface_Alias (Prim))
725a69d2 5374 or else Is_Predefined_Dispatching_Operation (Prim)
9429b6e9 5375 or else Is_Eliminated (E)
725a69d2 5376 then
5377 null;
5378
5379 else
725a69d2 5380 if not Is_Predefined_Dispatching_Operation (E)
5381 and then not Is_Abstract_Subprogram (E)
a652dd51 5382 and then not Present (Interface_Alias (E))
725a69d2 5383 then
5384 pragma Assert
5385 (UI_To_Int (DT_Position (Prim)) <= Nb_Prim);
5386
5387 Prim_Table (UI_To_Int (DT_Position (Prim))) := E;
725a69d2 5388 end if;
5389 end if;
5390
5391 Next_Elmt (Prim_Elmt);
5392 end loop;
5393
5394 for J in Prim_Table'Range loop
5395 if Present (Prim_Table (J)) then
5396 New_Node :=
cc60bd16 5397 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 5398 Make_Attribute_Reference (Loc,
5399 Prefix => New_Reference_To (Prim_Table (J), Loc),
5400 Attribute_Name => Name_Unrestricted_Access));
725a69d2 5401 else
cc60bd16 5402 New_Node := Make_Null (Loc);
725a69d2 5403 end if;
5404
5405 Append_To (Prim_Ops_Aggr_List, New_Node);
5406 end loop;
5407 end;
5408 end if;
5409
cc60bd16 5410 New_Node :=
725a69d2 5411 Make_Aggregate (Loc,
cc60bd16 5412 Expressions => Prim_Ops_Aggr_List);
5413
5414 Append_To (DT_Aggr_List, New_Node);
5415
5416 -- Remember aggregates initializing dispatch tables
5417
5418 Append_Elmt (New_Node, DT_Aggr);
725a69d2 5419
5420 -- In case of locally defined tagged types we have already declared
5421 -- and uninitialized object for the dispatch table, which is now
5422 -- initialized by means of an assignment.
5423
24971415 5424 if not Building_Static_DT (Typ) then
725a69d2 5425 Append_To (Result,
5426 Make_Assignment_Statement (Loc,
5427 Name => New_Reference_To (DT, Loc),
5428 Expression => Make_Aggregate (Loc,
5429 Expressions => DT_Aggr_List)));
5430
24971415 5431 -- In case of library level tagged types we declare now and export
5432 -- the constant object containing the dispatch table.
725a69d2 5433
5434 else
5435 Append_To (Result,
5436 Make_Object_Declaration (Loc,
5437 Defining_Identifier => DT,
5438 Aliased_Present => True,
17e14451 5439 Constant_Present => True,
725a69d2 5440 Object_Definition =>
5441 Make_Subtype_Indication (Loc,
5442 Subtype_Mark => New_Reference_To
5443 (RTE (RE_Dispatch_Table_Wrapper), Loc),
5444 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
5445 Constraints => DT_Constr_List)),
5446 Expression => Make_Aggregate (Loc,
5447 Expressions => DT_Aggr_List)));
5448
9af28f61 5449 -- Comment needed ???
5450
3dbca0d5 5451 if Generate_SCIL then
5452 Insert_Before (Last (Result),
5453 New_Scil_Node
5454 (Nkind => Dispatch_Table_Object_Init,
5455 Related_Node => Last (Result),
5456 Entity => Typ));
5457 end if;
5458
725a69d2 5459 Append_To (Result,
5460 Make_Attribute_Definition_Clause (Loc,
5461 Name => New_Reference_To (DT, Loc),
5462 Chars => Name_Alignment,
5463 Expression =>
5464 Make_Attribute_Reference (Loc,
5465 Prefix =>
5466 New_Reference_To (RTE (RE_Integer_Address), Loc),
5467 Attribute_Name => Name_Alignment)));
5468
24971415 5469 Export_DT (Typ, DT);
952af0b9 5470 end if;
76a1c25b 5471 end if;
d62940bf 5472
f301a57b 5473 -- Initialize the table of ancestor tags if not building static
5474 -- dispatch table
725a69d2 5475
24971415 5476 if not Building_Static_DT (Typ)
17e14451 5477 and then not Is_Interface (Typ)
725a69d2 5478 and then not Is_CPP_Class (Typ)
5479 then
5480 Append_To (Result,
5481 Make_Assignment_Statement (Loc,
5482 Name =>
5483 Make_Indexed_Component (Loc,
5484 Prefix =>
5485 Make_Selected_Component (Loc,
5486 Prefix =>
5487 New_Reference_To (TSD, Loc),
5488 Selector_Name =>
5489 New_Reference_To
5490 (RTE_Record_Component (RE_Tags_Table), Loc)),
5491 Expressions =>
5492 New_List (Make_Integer_Literal (Loc, 0))),
5493
5494 Expression =>
5495 New_Reference_To
5496 (Node (First_Elmt (Access_Disp_Table (Typ))), Loc)));
5497 end if;
5498
f301a57b 5499 -- Inherit the dispatch tables of the parent. There is no need to
5500 -- inherit anything from the parent when building static dispatch tables
5501 -- because the whole dispatch table (including inherited primitives) has
5502 -- been already built.
acf97c11 5503
24971415 5504 if Building_Static_DT (Typ) then
725a69d2 5505 null;
5506
af647dc7 5507 -- If the ancestor is a CPP_Class type we inherit the dispatch tables
5508 -- in the init proc, and we don't need to fill them in here.
d62940bf 5509
cc60bd16 5510 elsif Is_CPP_Class (Parent_Typ) then
af647dc7 5511 null;
d62940bf 5512
acf97c11 5513 -- Otherwise we fill in the dispatch tables here
d62940bf 5514
af647dc7 5515 else
cc60bd16 5516 if Typ /= Parent_Typ
af647dc7 5517 and then not Is_Interface (Typ)
5518 and then not Restriction_Active (No_Dispatching_Calls)
68f95949 5519 then
343d35dc 5520 -- Inherit the dispatch table
d62940bf 5521
acf97c11 5522 if not Is_Interface (Typ)
cc60bd16 5523 and then not Is_Interface (Parent_Typ)
5524 and then not Is_CPP_Class (Parent_Typ)
acf97c11 5525 then
5526 declare
5527 Nb_Prims : constant Int :=
5528 UI_To_Int (DT_Entry_Count
cc60bd16 5529 (First_Tag_Component (Parent_Typ)));
5530
acf97c11 5531 begin
5532 Append_To (Elab_Code,
5533 Build_Inherit_Predefined_Prims (Loc,
5534 Old_Tag_Node =>
5535 New_Reference_To
5536 (Node
5537 (Next_Elmt
5538 (First_Elmt
cc60bd16 5539 (Access_Disp_Table (Parent_Typ)))), Loc),
acf97c11 5540 New_Tag_Node =>
5541 New_Reference_To
5542 (Node
5543 (Next_Elmt
5544 (First_Elmt
5545 (Access_Disp_Table (Typ)))), Loc)));
5546
5547 if Nb_Prims /= 0 then
725a69d2 5548 Append_To (Elab_Code,
acf97c11 5549 Build_Inherit_Prims (Loc,
5550 Typ => Typ,
5551 Old_Tag_Node =>
5552 New_Reference_To
5553 (Node
5554 (First_Elmt
cc60bd16 5555 (Access_Disp_Table (Parent_Typ))), Loc),
acf97c11 5556 New_Tag_Node => New_Reference_To (DT_Ptr, Loc),
5557 Num_Prims => Nb_Prims));
5558 end if;
5559 end;
af647dc7 5560 end if;
d62940bf 5561
af647dc7 5562 -- Inherit the secondary dispatch tables of the ancestor
d62940bf 5563
cc60bd16 5564 if not Is_CPP_Class (Parent_Typ) then
af647dc7 5565 declare
5566 Sec_DT_Ancestor : Elmt_Id :=
5567 Next_Elmt
acf97c11 5568 (Next_Elmt
af647dc7 5569 (First_Elmt
cc60bd16 5570 (Access_Disp_Table (Parent_Typ))));
af647dc7 5571 Sec_DT_Typ : Elmt_Id :=
5572 Next_Elmt
acf97c11 5573 (Next_Elmt
5574 (First_Elmt
5575 (Access_Disp_Table (Typ))));
af647dc7 5576
5577 procedure Copy_Secondary_DTs (Typ : Entity_Id);
5578 -- Local procedure required to climb through the ancestors
5579 -- and copy the contents of all their secondary dispatch
5580 -- tables.
5581
5582 ------------------------
5583 -- Copy_Secondary_DTs --
5584 ------------------------
5585
5586 procedure Copy_Secondary_DTs (Typ : Entity_Id) is
5587 E : Entity_Id;
5588 Iface : Elmt_Id;
5589
5590 begin
5591 -- Climb to the ancestor (if any) handling private types
5592
5593 if Present (Full_View (Etype (Typ))) then
5594 if Full_View (Etype (Typ)) /= Typ then
5595 Copy_Secondary_DTs (Full_View (Etype (Typ)));
5596 end if;
d62940bf 5597
af647dc7 5598 elsif Etype (Typ) /= Typ then
5599 Copy_Secondary_DTs (Etype (Typ));
5600 end if;
d62940bf 5601
a652dd51 5602 if Present (Interfaces (Typ))
5603 and then not Is_Empty_Elmt_List (Interfaces (Typ))
af647dc7 5604 then
a652dd51 5605 Iface := First_Elmt (Interfaces (Typ));
af647dc7 5606 E := First_Entity (Typ);
5607 while Present (E)
5608 and then Present (Node (Sec_DT_Ancestor))
725a69d2 5609 and then Ekind (Node (Sec_DT_Ancestor)) = E_Constant
af647dc7 5610 loop
5611 if Is_Tag (E) and then Chars (E) /= Name_uTag then
cdb1c38f 5612 declare
5613 Num_Prims : constant Int :=
5614 UI_To_Int (DT_Entry_Count (E));
5615
5616 begin
5617 if not Is_Interface (Etype (Typ)) then
5618
5619 -- Inherit first secondary dispatch table
5620
5621 Append_To (Elab_Code,
5622 Build_Inherit_Predefined_Prims (Loc,
5623 Old_Tag_Node =>
5624 Unchecked_Convert_To (RTE (RE_Tag),
acf97c11 5625 New_Reference_To
5626 (Node
5627 (Next_Elmt (Sec_DT_Ancestor)),
5628 Loc)),
cdb1c38f 5629 New_Tag_Node =>
5630 Unchecked_Convert_To (RTE (RE_Tag),
5631 New_Reference_To
acf97c11 5632 (Node (Next_Elmt (Sec_DT_Typ)),
5633 Loc))));
cdb1c38f 5634
5635 if Num_Prims /= 0 then
5636 Append_To (Elab_Code,
5637 Build_Inherit_Prims (Loc,
5638 Typ => Node (Iface),
5639 Old_Tag_Node =>
5640 Unchecked_Convert_To
5641 (RTE (RE_Tag),
5642 New_Reference_To
5643 (Node (Sec_DT_Ancestor),
5644 Loc)),
5645 New_Tag_Node =>
5646 Unchecked_Convert_To
5647 (RTE (RE_Tag),
5648 New_Reference_To
5649 (Node (Sec_DT_Typ), Loc)),
5650 Num_Prims => Num_Prims));
5651 end if;
5652 end if;
5653
5654 Next_Elmt (Sec_DT_Ancestor);
5655 Next_Elmt (Sec_DT_Typ);
343d35dc 5656
acf97c11 5657 -- Skip the secondary dispatch table of
5658 -- predefined primitives
5659
5660 Next_Elmt (Sec_DT_Ancestor);
5661 Next_Elmt (Sec_DT_Typ);
5662
cdb1c38f 5663 if not Is_Interface (Etype (Typ)) then
5664
5665 -- Inherit second secondary dispatch table
343d35dc 5666
343d35dc 5667 Append_To (Elab_Code,
5668 Build_Inherit_Predefined_Prims (Loc,
5669 Old_Tag_Node =>
5670 Unchecked_Convert_To (RTE (RE_Tag),
5671 New_Reference_To
acf97c11 5672 (Node
5673 (Next_Elmt (Sec_DT_Ancestor)),
5674 Loc)),
343d35dc 5675 New_Tag_Node =>
5676 Unchecked_Convert_To (RTE (RE_Tag),
5677 New_Reference_To
acf97c11 5678 (Node (Next_Elmt (Sec_DT_Typ)),
5679 Loc))));
343d35dc 5680
5681 if Num_Prims /= 0 then
5682 Append_To (Elab_Code,
5683 Build_Inherit_Prims (Loc,
17e14451 5684 Typ => Node (Iface),
343d35dc 5685 Old_Tag_Node =>
5686 Unchecked_Convert_To
5687 (RTE (RE_Tag),
5688 New_Reference_To
5689 (Node (Sec_DT_Ancestor),
5690 Loc)),
5691 New_Tag_Node =>
5692 Unchecked_Convert_To
5693 (RTE (RE_Tag),
5694 New_Reference_To
5695 (Node (Sec_DT_Typ), Loc)),
17e14451 5696 Num_Prims => Num_Prims));
343d35dc 5697 end if;
cdb1c38f 5698 end if;
5699 end;
af647dc7 5700
5701 Next_Elmt (Sec_DT_Ancestor);
5702 Next_Elmt (Sec_DT_Typ);
acf97c11 5703
5704 -- Skip the secondary dispatch table of
5705 -- predefined primitives
5706
5707 Next_Elmt (Sec_DT_Ancestor);
5708 Next_Elmt (Sec_DT_Typ);
5709
af647dc7 5710 Next_Elmt (Iface);
5711 end if;
d62940bf 5712
af647dc7 5713 Next_Entity (E);
5714 end loop;
5715 end if;
5716 end Copy_Secondary_DTs;
d62940bf 5717
af647dc7 5718 begin
725a69d2 5719 if Present (Node (Sec_DT_Ancestor))
5720 and then Ekind (Node (Sec_DT_Ancestor)) = E_Constant
5721 then
af647dc7 5722 -- Handle private types
76a1c25b 5723
af647dc7 5724 if Present (Full_View (Typ)) then
5725 Copy_Secondary_DTs (Full_View (Typ));
5726 else
5727 Copy_Secondary_DTs (Typ);
5728 end if;
76a1c25b 5729 end if;
af647dc7 5730 end;
5731 end if;
76a1c25b 5732 end if;
343d35dc 5733 end if;
d62940bf 5734
343d35dc 5735 -- Generate code to register the Tag in the External_Tag hash table for
5736 -- the pure Ada type only.
d62940bf 5737
343d35dc 5738 -- Register_Tag (Dt_Ptr);
d62940bf 5739
725a69d2 5740 -- Skip this action in the following cases:
5741 -- 1) if Register_Tag is not available.
5742 -- 2) in No_Run_Time mode.
2ea346ac 5743 -- 3) if Typ is not defined at the library level (this is required
725a69d2 5744 -- to avoid adding concurrency control to the hash table used
5745 -- by the run-time to register the tags).
d62940bf 5746
cdb1c38f 5747 if not No_Run_Time_Mode
5748 and then Is_Library_Level_Entity (Typ)
5749 and then RTE_Available (RE_Register_Tag)
5750 then
725a69d2 5751 Append_To (Elab_Code,
cdb1c38f 5752 Make_Procedure_Call_Statement (Loc,
5753 Name => New_Reference_To (RTE (RE_Register_Tag), Loc),
5754 Parameter_Associations =>
5755 New_List (New_Reference_To (DT_Ptr, Loc))));
d62940bf 5756 end if;
5757
2ea346ac 5758 if not Is_Empty_List (Elab_Code) then
5759 Append_List_To (Result, Elab_Code);
5760 end if;
cdb1c38f 5761
f38c8084 5762 -- Populate the two auxiliary tables used for dispatching asynchronous,
5763 -- conditional and timed selects for synchronized types that implement
5764 -- a limited interface. Skip this step in Ravenscar profile or when
5765 -- general dispatching is forbidden.
17e14451 5766
5767 if Ada_Version >= Ada_05
5768 and then Is_Concurrent_Record_Type (Typ)
a652dd51 5769 and then Has_Interfaces (Typ)
f38c8084 5770 and then not Restriction_Active (No_Dispatching_Calls)
5771 and then not Restriction_Active (No_Select_Statements)
17e14451 5772 then
5773 Append_List_To (Result,
5774 Make_Select_Specific_Data_Table (Typ));
5775 end if;
5776
cc60bd16 5777 -- Remember entities containing dispatch tables
acf97c11 5778
cc60bd16 5779 Append_Elmt (Predef_Prims, DT_Decl);
5780 Append_Elmt (DT, DT_Decl);
acf97c11 5781
725a69d2 5782 Analyze_List (Result, Suppress => All_Checks);
17e14451 5783 Set_Has_Dispatch_Table (Typ);
5784
f301a57b 5785 -- Mark entities containing dispatch tables. Required by the backend to
5786 -- handle them properly.
cc60bd16 5787
5788 if not Is_Interface (Typ) then
5789 declare
5790 Elmt : Elmt_Id;
5791
5792 begin
5793 -- Ensure that entities Prim_Ptr and Predef_Prims_Table_Ptr have
5794 -- the decoration required by the backend
5795
5796 Set_Is_Dispatch_Table_Entity (RTE (RE_Prim_Ptr));
5797 Set_Is_Dispatch_Table_Entity (RTE (RE_Predef_Prims_Table_Ptr));
5798
5799 -- Object declarations
5800
5801 Elmt := First_Elmt (DT_Decl);
5802 while Present (Elmt) loop
5803 Set_Is_Dispatch_Table_Entity (Node (Elmt));
5804 pragma Assert (Ekind (Etype (Node (Elmt))) = E_Array_Subtype
5805 or else Ekind (Etype (Node (Elmt))) = E_Record_Subtype);
5806 Set_Is_Dispatch_Table_Entity (Etype (Node (Elmt)));
5807 Next_Elmt (Elmt);
5808 end loop;
5809
5810 -- Aggregates initializing dispatch tables
5811
5812 Elmt := First_Elmt (DT_Aggr);
5813 while Present (Elmt) loop
5814 Set_Is_Dispatch_Table_Entity (Etype (Node (Elmt)));
5815 Next_Elmt (Elmt);
5816 end loop;
5817 end;
5818 end if;
5819
76a1c25b 5820 return Result;
5821 end Make_DT;
d62940bf 5822
76a1c25b 5823 -------------------------------------
5824 -- Make_Select_Specific_Data_Table --
5825 -------------------------------------
d62940bf 5826
76a1c25b 5827 function Make_Select_Specific_Data_Table
5828 (Typ : Entity_Id) return List_Id
5829 is
5830 Assignments : constant List_Id := New_List;
5831 Loc : constant Source_Ptr := Sloc (Typ);
d62940bf 5832
68f95949 5833 Conc_Typ : Entity_Id;
5834 Decls : List_Id;
5835 DT_Ptr : Entity_Id;
5836 Prim : Entity_Id;
5837 Prim_Als : Entity_Id;
5838 Prim_Elmt : Elmt_Id;
5839 Prim_Pos : Uint;
343d35dc 5840 Nb_Prim : Nat := 0;
d62940bf 5841
76a1c25b 5842 type Examined_Array is array (Int range <>) of Boolean;
d62940bf 5843
76a1c25b 5844 function Find_Entry_Index (E : Entity_Id) return Uint;
5845 -- Given an entry, find its index in the visible declarations of the
5846 -- corresponding concurrent type of Typ.
d62940bf 5847
76a1c25b 5848 ----------------------
5849 -- Find_Entry_Index --
5850 ----------------------
d62940bf 5851
76a1c25b 5852 function Find_Entry_Index (E : Entity_Id) return Uint is
5853 Index : Uint := Uint_1;
5854 Subp_Decl : Entity_Id;
d62940bf 5855
76a1c25b 5856 begin
5857 if Present (Decls)
5858 and then not Is_Empty_List (Decls)
5859 then
5860 Subp_Decl := First (Decls);
5861 while Present (Subp_Decl) loop
5862 if Nkind (Subp_Decl) = N_Entry_Declaration then
5863 if Defining_Identifier (Subp_Decl) = E then
5864 return Index;
5865 end if;
d62940bf 5866
76a1c25b 5867 Index := Index + 1;
5868 end if;
d62940bf 5869
76a1c25b 5870 Next (Subp_Decl);
5871 end loop;
5872 end if;
d62940bf 5873
76a1c25b 5874 return Uint_0;
5875 end Find_Entry_Index;
5876
5877 -- Start of processing for Make_Select_Specific_Data_Table
5878
5879 begin
68f95949 5880 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
5881
76a1c25b 5882 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
d62940bf 5883
76a1c25b 5884 if Present (Corresponding_Concurrent_Type (Typ)) then
5885 Conc_Typ := Corresponding_Concurrent_Type (Typ);
5886
17e14451 5887 if Present (Full_View (Conc_Typ)) then
5888 Conc_Typ := Full_View (Conc_Typ);
5889 end if;
5890
76a1c25b 5891 if Ekind (Conc_Typ) = E_Protected_Type then
5892 Decls := Visible_Declarations (Protected_Definition (
5893 Parent (Conc_Typ)));
d62940bf 5894 else
5895 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
76a1c25b 5896 Decls := Visible_Declarations (Task_Definition (
5897 Parent (Conc_Typ)));
5898 end if;
5899 end if;
d62940bf 5900
76a1c25b 5901 -- Count the non-predefined primitive operations
d62940bf 5902
76a1c25b 5903 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
5904 while Present (Prim_Elmt) loop
af647dc7 5905 Prim := Node (Prim_Elmt);
5906
5907 if not (Is_Predefined_Dispatching_Operation (Prim)
5908 or else Is_Predefined_Dispatching_Alias (Prim))
5909 then
76a1c25b 5910 Nb_Prim := Nb_Prim + 1;
5911 end if;
d62940bf 5912
76a1c25b 5913 Next_Elmt (Prim_Elmt);
5914 end loop;
d62940bf 5915
76a1c25b 5916 declare
68f95949 5917 Examined : Examined_Array (1 .. Nb_Prim) := (others => False);
d62940bf 5918
76a1c25b 5919 begin
5920 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
5921 while Present (Prim_Elmt) loop
5922 Prim := Node (Prim_Elmt);
d62940bf 5923
af647dc7 5924 -- Look for primitive overriding an abstract interface subprogram
d62940bf 5925
a652dd51 5926 if Present (Interface_Alias (Prim))
af647dc7 5927 and then not Examined (UI_To_Int (DT_Position (Alias (Prim))))
5928 then
5929 Prim_Pos := DT_Position (Alias (Prim));
5930 pragma Assert (UI_To_Int (Prim_Pos) <= Nb_Prim);
5931 Examined (UI_To_Int (Prim_Pos)) := True;
d62940bf 5932
af647dc7 5933 -- Set the primitive operation kind regardless of subprogram
5934 -- type. Generate:
5935 -- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, <position>, <kind>);
d62940bf 5936
af647dc7 5937 Append_To (Assignments,
725a69d2 5938 Make_Procedure_Call_Statement (Loc,
5939 Name => New_Reference_To (RTE (RE_Set_Prim_Op_Kind), Loc),
5940 Parameter_Associations => New_List (
5941 New_Reference_To (DT_Ptr, Loc),
5942 Make_Integer_Literal (Loc, Prim_Pos),
5943 Prim_Op_Kind (Alias (Prim), Typ))));
68f95949 5944
af647dc7 5945 -- Retrieve the root of the alias chain
68f95949 5946
af647dc7 5947 Prim_Als := Prim;
5948 while Present (Alias (Prim_Als)) loop
5949 Prim_Als := Alias (Prim_Als);
5950 end loop;
68f95949 5951
af647dc7 5952 -- In the case of an entry wrapper, set the entry index
68f95949 5953
af647dc7 5954 if Ekind (Prim) = E_Procedure
5955 and then Is_Primitive_Wrapper (Prim_Als)
5956 and then Ekind (Wrapped_Entity (Prim_Als)) = E_Entry
5957 then
5958 -- Generate:
5959 -- Ada.Tags.Set_Entry_Index
5960 -- (DT_Ptr, <position>, <index>);
68f95949 5961
af647dc7 5962 Append_To (Assignments,
725a69d2 5963 Make_Procedure_Call_Statement (Loc,
5964 Name =>
5965 New_Reference_To (RTE (RE_Set_Entry_Index), Loc),
5966 Parameter_Associations => New_List (
5967 New_Reference_To (DT_Ptr, Loc),
5968 Make_Integer_Literal (Loc, Prim_Pos),
5969 Make_Integer_Literal (Loc,
5970 Find_Entry_Index (Wrapped_Entity (Prim_Als))))));
76a1c25b 5971 end if;
5972 end if;
5973
76a1c25b 5974 Next_Elmt (Prim_Elmt);
5975 end loop;
5976 end;
5977
5978 return Assignments;
5979 end Make_Select_Specific_Data_Table;
d62940bf 5980
17e14451 5981 ---------------
5982 -- Make_Tags --
5983 ---------------
5984
5985 function Make_Tags (Typ : Entity_Id) return List_Id is
f301a57b 5986 Loc : constant Source_Ptr := Sloc (Typ);
5987 Result : constant List_Id := New_List;
5988
5989 procedure Import_DT
5990 (Tag_Typ : Entity_Id;
5991 DT : Entity_Id;
5992 Is_Secondary_DT : Boolean);
5993 -- Import the dispatch table DT of tagged type Tag_Typ. Required to
5994 -- generate forward references and statically allocate the table. For
5995 -- primary dispatch tables that require no dispatch table generate:
5996 -- DT : static aliased constant Non_Dispatch_Table_Wrapper;
5997 -- $pragma import (ada, DT);
5998 -- Otherwise generate:
5999 -- DT : static aliased constant Dispatch_Table_Wrapper (Nb_Prim);
6000 -- $pragma import (ada, DT);
7854e190 6001
f301a57b 6002 ---------------
6003 -- Import_DT --
6004 ---------------
24971415 6005
f301a57b 6006 procedure Import_DT
6007 (Tag_Typ : Entity_Id;
6008 DT : Entity_Id;
6009 Is_Secondary_DT : Boolean)
6010 is
6011 DT_Constr_List : List_Id;
6012 Nb_Prim : Nat;
24971415 6013
f301a57b 6014 begin
6015 Set_Is_Imported (DT);
6016 Set_Ekind (DT, E_Constant);
6017 Set_Related_Type (DT, Typ);
24971415 6018
24971415 6019 -- The scope must be set now to call Get_External_Name
6020
6021 Set_Scope (DT, Current_Scope);
6022
6023 Get_External_Name (DT, True);
6024 Set_Interface_Name (DT,
17e14451 6025 Make_String_Literal (Loc,
6026 Strval => String_From_Name_Buffer));
6027
24971415 6028 -- Ensure proper Sprint output of this implicit importation
17e14451 6029
24971415 6030 Set_Is_Internal (DT);
17e14451 6031
24971415 6032 -- Save this entity to allow Make_DT to generate its exportation
6033
f301a57b 6034 Append_Elmt (DT, Dispatch_Table_Wrappers (Typ));
24971415 6035
f301a57b 6036 -- No dispatch table required
acf97c11 6037
f301a57b 6038 if not Is_Secondary_DT
6039 and then not Has_DT (Tag_Typ)
6040 then
6041 Append_To (Result,
6042 Make_Object_Declaration (Loc,
6043 Defining_Identifier => DT,
6044 Aliased_Present => True,
6045 Constant_Present => True,
6046 Object_Definition =>
6047 New_Reference_To (RTE (RE_No_Dispatch_Table_Wrapper), Loc)));
6048
6049 else
24971415 6050 -- Calculate the number of primitives of the dispatch table and
6051 -- the size of the Type_Specific_Data record.
6052
f301a57b 6053 Nb_Prim :=
6054 UI_To_Int (DT_Entry_Count (First_Tag_Component (Tag_Typ)));
24971415 6055
6056 -- If the tagged type has no primitives we add a dummy slot
6057 -- whose address will be the tag of this type.
6058
6059 if Nb_Prim = 0 then
6060 DT_Constr_List :=
6061 New_List (Make_Integer_Literal (Loc, 1));
6062 else
6063 DT_Constr_List :=
6064 New_List (Make_Integer_Literal (Loc, Nb_Prim));
6065 end if;
6066
6067 Append_To (Result,
6068 Make_Object_Declaration (Loc,
6069 Defining_Identifier => DT,
6070 Aliased_Present => True,
6071 Constant_Present => True,
6072 Object_Definition =>
6073 Make_Subtype_Indication (Loc,
6074 Subtype_Mark =>
6075 New_Reference_To (RTE (RE_Dispatch_Table_Wrapper), Loc),
6076 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
6077 Constraints => DT_Constr_List))));
f301a57b 6078 end if;
6079 end Import_DT;
6080
6081 -- Local variables
6082
6083 Tname : constant Name_Id := Chars (Typ);
6084 AI_Tag_Comp : Elmt_Id;
6085 DT : Node_Id;
6086 DT_Ptr : Node_Id;
6087 Predef_Prims_Ptr : Node_Id;
6088 Iface_DT : Node_Id;
6089 Iface_DT_Ptr : Node_Id;
6090 Suffix_Index : Int;
6091 Typ_Name : Name_Id;
6092 Typ_Comps : Elist_Id;
6093
6094 -- Start of processing for Make_Tags
6095
6096 begin
6097 -- 1) Generate the primary and secondary tag entities
24971415 6098
f301a57b 6099 -- Collect the components associated with secondary dispatch tables
6100
6101 if Has_Interfaces (Typ) then
6102 Collect_Interface_Components (Typ, Typ_Comps);
6103 end if;
6104
6105 -- 1) Generate the primary tag entities
6106
6107 -- Primary dispatch table containing user-defined primitives
6108
6109 DT_Ptr := Make_Defining_Identifier (Loc,
6110 New_External_Name (Tname, 'P'));
6111 Set_Etype (DT_Ptr, RTE (RE_Tag));
6112
6113 -- Primary dispatch table containing predefined primitives
6114
6115 Predef_Prims_Ptr :=
6116 Make_Defining_Identifier (Loc,
6117 Chars => New_External_Name (Tname, 'Y'));
6118 Set_Etype (Predef_Prims_Ptr, RTE (RE_Address));
6119
6120 -- Import the forward declaration of the Dispatch Table wrapper record
6121 -- (Make_DT will take care of its exportation)
6122
6123 if Building_Static_DT (Typ) then
6124 Set_Dispatch_Table_Wrappers (Typ, New_Elmt_List);
6125
6126 DT :=
6127 Make_Defining_Identifier (Loc,
6128 Chars => New_External_Name (Tname, 'T'));
6129
6130 Import_DT (Typ, DT, Is_Secondary_DT => False);
6131
6132 if Has_DT (Typ) then
24971415 6133 Append_To (Result,
6134 Make_Object_Declaration (Loc,
6135 Defining_Identifier => DT_Ptr,
6136 Constant_Present => True,
6137 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
6138 Expression =>
6139 Unchecked_Convert_To (RTE (RE_Tag),
6140 Make_Attribute_Reference (Loc,
6141 Prefix =>
6142 Make_Selected_Component (Loc,
6143 Prefix => New_Reference_To (DT, Loc),
6144 Selector_Name =>
6145 New_Occurrence_Of
6146 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
6147 Attribute_Name => Name_Address))));
6148
9af28f61 6149 -- Comment needed ???
6150
3dbca0d5 6151 if Generate_SCIL then
6152 Insert_Before (Last (Result),
6153 New_Scil_Node
6154 (Nkind => Dispatch_Table_Tag_Init,
6155 Related_Node => Last (Result),
6156 Entity => Typ));
6157 end if;
6158
acf97c11 6159 Append_To (Result,
6160 Make_Object_Declaration (Loc,
6161 Defining_Identifier => Predef_Prims_Ptr,
6162 Constant_Present => True,
6163 Object_Definition => New_Reference_To
6164 (RTE (RE_Address), Loc),
6165 Expression =>
6166 Make_Attribute_Reference (Loc,
6167 Prefix =>
6168 Make_Selected_Component (Loc,
6169 Prefix => New_Reference_To (DT, Loc),
6170 Selector_Name =>
6171 New_Occurrence_Of
6172 (RTE_Record_Component (RE_Predef_Prims), Loc)),
6173 Attribute_Name => Name_Address)));
6174
24971415 6175 -- No dispatch table required
6176
6177 else
24971415 6178 Append_To (Result,
6179 Make_Object_Declaration (Loc,
6180 Defining_Identifier => DT_Ptr,
6181 Constant_Present => True,
6182 Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
6183 Expression =>
6184 Unchecked_Convert_To (RTE (RE_Tag),
6185 Make_Attribute_Reference (Loc,
6186 Prefix =>
6187 Make_Selected_Component (Loc,
6188 Prefix => New_Reference_To (DT, Loc),
6189 Selector_Name =>
6190 New_Occurrence_Of
6191 (RTE_Record_Component (RE_NDT_Prims_Ptr), Loc)),
6192 Attribute_Name => Name_Address))));
3dbca0d5 6193
9af28f61 6194 -- Comment needed ???
6195
3dbca0d5 6196 if Generate_SCIL then
6197 Insert_Before (Last (Result),
6198 New_Scil_Node
6199 (Nkind => Dispatch_Table_Tag_Init,
6200 Related_Node => Last (Result),
6201 Entity => Typ));
6202 end if;
24971415 6203 end if;
6204
6205 Set_Is_True_Constant (DT_Ptr);
e7e688dd 6206 Set_Is_Statically_Allocated (DT_Ptr);
17e14451 6207 end if;
6208
6209 pragma Assert (No (Access_Disp_Table (Typ)));
6210 Set_Access_Disp_Table (Typ, New_Elmt_List);
6211 Append_Elmt (DT_Ptr, Access_Disp_Table (Typ));
acf97c11 6212 Append_Elmt (Predef_Prims_Ptr, Access_Disp_Table (Typ));
17e14451 6213
6214 -- 2) Generate the secondary tag entities
6215
a652dd51 6216 if Has_Interfaces (Typ) then
f301a57b 6217
6218 -- Note: The following value of Suffix_Index must be in sync with
6219 -- the Suffix_Index values of secondary dispatch tables generated
6220 -- by Make_DT.
6221
6222 Suffix_Index := 1;
17e14451 6223
6224 -- For each interface type we build an unique external name
6225 -- associated with its corresponding secondary dispatch table.
6226 -- This external name will be used to declare an object that
6227 -- references this secondary dispatch table, value that will be
6228 -- used for the elaboration of Typ's objects and also for the
6229 -- elaboration of objects of derivations of Typ that do not
6230 -- override the primitive operation of this interface type.
6231
6232 AI_Tag_Comp := First_Elmt (Typ_Comps);
6233 while Present (AI_Tag_Comp) loop
6234 Get_Secondary_DT_External_Name
cdb1c38f 6235 (Typ, Related_Type (Node (AI_Tag_Comp)), Suffix_Index);
cdb1c38f 6236 Typ_Name := Name_Find;
17e14451 6237
f301a57b 6238 if Building_Static_DT (Typ) then
6239 Iface_DT :=
6240 Make_Defining_Identifier (Loc,
6241 Chars => New_External_Name
6242 (Typ_Name, 'T', Suffix_Index => -1));
6243 Import_DT
6244 (Tag_Typ => Related_Type (Node (AI_Tag_Comp)),
6245 DT => Iface_DT,
6246 Is_Secondary_DT => True);
6247 end if;
6248
acf97c11 6249 -- Secondary dispatch table referencing thunks to user-defined
6250 -- primitives covered by this interface.
6251
17e14451 6252 Iface_DT_Ptr :=
6253 Make_Defining_Identifier (Loc,
6254 Chars => New_External_Name (Typ_Name, 'P'));
6255 Set_Etype (Iface_DT_Ptr, RTE (RE_Interface_Tag));
6256 Set_Ekind (Iface_DT_Ptr, E_Constant);
cdb1c38f 6257 Set_Is_Tag (Iface_DT_Ptr);
6258 Set_Has_Thunks (Iface_DT_Ptr);
2ea346ac 6259 Set_Is_Statically_Allocated (Iface_DT_Ptr,
6260 Is_Library_Level_Tagged_Type (Typ));
17e14451 6261 Set_Is_True_Constant (Iface_DT_Ptr);
cdb1c38f 6262 Set_Related_Type
6263 (Iface_DT_Ptr, Related_Type (Node (AI_Tag_Comp)));
6264 Append_Elmt (Iface_DT_Ptr, Access_Disp_Table (Typ));
6265
f301a57b 6266 if Building_Static_DT (Typ) then
6267 Append_To (Result,
6268 Make_Object_Declaration (Loc,
6269 Defining_Identifier => Iface_DT_Ptr,
6270 Constant_Present => True,
6271 Object_Definition => New_Reference_To
6272 (RTE (RE_Interface_Tag), Loc),
6273 Expression =>
6274 Unchecked_Convert_To (RTE (RE_Interface_Tag),
6275 Make_Attribute_Reference (Loc,
6276 Prefix =>
6277 Make_Selected_Component (Loc,
6278 Prefix => New_Reference_To (Iface_DT, Loc),
6279 Selector_Name =>
6280 New_Occurrence_Of
6281 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
6282 Attribute_Name => Name_Address))));
6283 end if;
6284
acf97c11 6285 -- Secondary dispatch table referencing thunks to predefined
6286 -- primitives.
6287
6288 Iface_DT_Ptr :=
6289 Make_Defining_Identifier (Loc,
6290 Chars => New_External_Name (Typ_Name, 'Y'));
6291 Set_Etype (Iface_DT_Ptr, RTE (RE_Address));
6292 Set_Ekind (Iface_DT_Ptr, E_Constant);
6293 Set_Is_Tag (Iface_DT_Ptr);
6294 Set_Has_Thunks (Iface_DT_Ptr);
2ea346ac 6295 Set_Is_Statically_Allocated (Iface_DT_Ptr,
6296 Is_Library_Level_Tagged_Type (Typ));
acf97c11 6297 Set_Is_True_Constant (Iface_DT_Ptr);
6298 Set_Related_Type
6299 (Iface_DT_Ptr, Related_Type (Node (AI_Tag_Comp)));
6300 Append_Elmt (Iface_DT_Ptr, Access_Disp_Table (Typ));
6301
6302 -- Secondary dispatch table referencing user-defined primitives
6303 -- covered by this interface.
6304
cdb1c38f 6305 Iface_DT_Ptr :=
6306 Make_Defining_Identifier (Loc,
6307 Chars => New_External_Name (Typ_Name, 'D'));
6308 Set_Etype (Iface_DT_Ptr, RTE (RE_Interface_Tag));
6309 Set_Ekind (Iface_DT_Ptr, E_Constant);
6310 Set_Is_Tag (Iface_DT_Ptr);
2ea346ac 6311 Set_Is_Statically_Allocated (Iface_DT_Ptr,
6312 Is_Library_Level_Tagged_Type (Typ));
cdb1c38f 6313 Set_Is_True_Constant (Iface_DT_Ptr);
6314 Set_Related_Type
6315 (Iface_DT_Ptr, Related_Type (Node (AI_Tag_Comp)));
17e14451 6316 Append_Elmt (Iface_DT_Ptr, Access_Disp_Table (Typ));
6317
acf97c11 6318 -- Secondary dispatch table referencing predefined primitives
6319
6320 Iface_DT_Ptr :=
6321 Make_Defining_Identifier (Loc,
6322 Chars => New_External_Name (Typ_Name, 'Z'));
6323 Set_Etype (Iface_DT_Ptr, RTE (RE_Address));
6324 Set_Ekind (Iface_DT_Ptr, E_Constant);
6325 Set_Is_Tag (Iface_DT_Ptr);
2ea346ac 6326 Set_Is_Statically_Allocated (Iface_DT_Ptr,
6327 Is_Library_Level_Tagged_Type (Typ));
acf97c11 6328 Set_Is_True_Constant (Iface_DT_Ptr);
6329 Set_Related_Type
6330 (Iface_DT_Ptr, Related_Type (Node (AI_Tag_Comp)));
6331 Append_Elmt (Iface_DT_Ptr, Access_Disp_Table (Typ));
6332
17e14451 6333 Next_Elmt (AI_Tag_Comp);
6334 end loop;
6335 end if;
6336
dffd0a90 6337 -- 3) At the end of Access_Disp_Table, if the type has user-defined
6338 -- primitives, we add the entity of an access type declaration that
6339 -- is used by Build_Get_Prim_Op_Address to expand dispatching calls
6340 -- through the primary dispatch table.
6341
6342 if UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))) = 0 then
6343 Analyze_List (Result);
17e14451 6344
6345 -- Generate:
cc60bd16 6346 -- type Typ_DT is array (1 .. Nb_Prims) of Prim_Ptr;
17e14451 6347 -- type Typ_DT_Acc is access Typ_DT;
6348
dffd0a90 6349 else
6350 declare
6351 Name_DT_Prims : constant Name_Id :=
6352 New_External_Name (Tname, 'G');
6353 Name_DT_Prims_Acc : constant Name_Id :=
6354 New_External_Name (Tname, 'H');
6355 DT_Prims : constant Entity_Id :=
6356 Make_Defining_Identifier (Loc,
6357 Name_DT_Prims);
6358 DT_Prims_Acc : constant Entity_Id :=
6359 Make_Defining_Identifier (Loc,
6360 Name_DT_Prims_Acc);
6361 begin
6362 Append_To (Result,
6363 Make_Full_Type_Declaration (Loc,
6364 Defining_Identifier => DT_Prims,
6365 Type_Definition =>
6366 Make_Constrained_Array_Definition (Loc,
6367 Discrete_Subtype_Definitions => New_List (
6368 Make_Range (Loc,
6369 Low_Bound => Make_Integer_Literal (Loc, 1),
6370 High_Bound => Make_Integer_Literal (Loc,
6371 DT_Entry_Count
6372 (First_Tag_Component (Typ))))),
6373 Component_Definition =>
6374 Make_Component_Definition (Loc,
6375 Subtype_Indication =>
6376 New_Reference_To (RTE (RE_Prim_Ptr), Loc)))));
17e14451 6377
dffd0a90 6378 Append_To (Result,
6379 Make_Full_Type_Declaration (Loc,
6380 Defining_Identifier => DT_Prims_Acc,
6381 Type_Definition =>
6382 Make_Access_To_Object_Definition (Loc,
6383 Subtype_Indication =>
6384 New_Occurrence_Of (DT_Prims, Loc))));
17e14451 6385
dffd0a90 6386 Append_Elmt (DT_Prims_Acc, Access_Disp_Table (Typ));
17e14451 6387
dffd0a90 6388 -- Analyze the resulting list and suppress the generation of the
6389 -- Init_Proc associated with the above array declaration because
6390 -- this type is never used in object declarations. It is only used
6391 -- to simplify the expansion associated with dispatching calls.
17e14451 6392
dffd0a90 6393 Analyze_List (Result);
6394 Set_Suppress_Init_Proc (Base_Type (DT_Prims));
cc60bd16 6395
dffd0a90 6396 -- Mark entity of dispatch table. Required by the back end to
6397 -- handle them properly.
cc60bd16 6398
dffd0a90 6399 Set_Is_Dispatch_Table_Entity (DT_Prims);
6400 end;
6401 end if;
17e14451 6402
cdb1c38f 6403 Set_Ekind (DT_Ptr, E_Constant);
6404 Set_Is_Tag (DT_Ptr);
6405 Set_Related_Type (DT_Ptr, Typ);
6406
17e14451 6407 return Result;
6408 end Make_Tags;
6409
cd534f03 6410 ---------------
6411 -- New_Value --
6412 ---------------
6413
6414 function New_Value (From : Node_Id) return Node_Id is
6415 Res : constant Node_Id := Duplicate_Subexpr (From);
6416 begin
6417 if Is_Access_Type (Etype (From)) then
9af28f61 6418 return
6419 Make_Explicit_Dereference (Sloc (From),
6420 Prefix => Res);
cd534f03 6421 else
6422 return Res;
6423 end if;
6424 end New_Value;
6425
3dbca0d5 6426 -------------------
6427 -- New_Scil_Node --
6428 -------------------
6429
6430 function New_Scil_Node
6431 (Nkind : Scil_Node_Kind;
6432 Related_Node : Node_Id;
6433 Entity : Entity_Id := Empty;
6434 Target_Prim : Entity_Id := Empty) return Node_Id
6435 is
9af28f61 6436 New_N : constant Node_Id :=
6437 New_Node (N_Null_Statement, Sloc (Related_Node));
3dbca0d5 6438 begin
3dbca0d5 6439 Set_Is_Scil_Node (New_N);
6440 Set_Scil_Nkind (New_N, UI_From_Int (Scil_Node_Kind'Pos (Nkind)));
6441 Set_Scil_Related_Node (New_N, Related_Node);
6442 Set_Entity (New_N, Entity);
6443 Set_Scil_Target_Prim (New_N, Target_Prim);
3dbca0d5 6444 return New_N;
6445 end New_Scil_Node;
6446
ee6ba406 6447 -----------------------------------
6448 -- Original_View_In_Visible_Part --
6449 -----------------------------------
6450
6451 function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean is
6452 Scop : constant Entity_Id := Scope (Typ);
6453
6454 begin
6455 -- The scope must be a package
6456
65149aa0 6457 if not Is_Package_Or_Generic_Package (Scop) then
ee6ba406 6458 return False;
6459 end if;
6460
6461 -- A type with a private declaration has a private view declared in
6462 -- the visible part.
6463
6464 if Has_Private_Declaration (Typ) then
6465 return True;
6466 end if;
6467
6468 return List_Containing (Parent (Typ)) =
6469 Visible_Declarations (Specification (Unit_Declaration_Node (Scop)));
6470 end Original_View_In_Visible_Part;
6471
d62940bf 6472 ------------------
6473 -- Prim_Op_Kind --
6474 ------------------
6475
6476 function Prim_Op_Kind
6477 (Prim : Entity_Id;
6478 Typ : Entity_Id) return Node_Id
6479 is
6480 Full_Typ : Entity_Id := Typ;
6481 Loc : constant Source_Ptr := Sloc (Prim);
68f95949 6482 Prim_Op : Entity_Id;
d62940bf 6483
6484 begin
6485 -- Retrieve the original primitive operation
6486
68f95949 6487 Prim_Op := Prim;
d62940bf 6488 while Present (Alias (Prim_Op)) loop
6489 Prim_Op := Alias (Prim_Op);
6490 end loop;
6491
6492 if Ekind (Typ) = E_Record_Type
6493 and then Present (Corresponding_Concurrent_Type (Typ))
6494 then
6495 Full_Typ := Corresponding_Concurrent_Type (Typ);
6496 end if;
6497
d77e048b 6498 -- When a private tagged type is completed by a concurrent type,
6499 -- retrieve the full view.
6500
6501 if Is_Private_Type (Full_Typ) then
6502 Full_Typ := Full_View (Full_Typ);
6503 end if;
6504
d62940bf 6505 if Ekind (Prim_Op) = E_Function then
6506
6507 -- Protected function
6508
6509 if Ekind (Full_Typ) = E_Protected_Type then
6510 return New_Reference_To (RTE (RE_POK_Protected_Function), Loc);
6511
76a1c25b 6512 -- Task function
6513
6514 elsif Ekind (Full_Typ) = E_Task_Type then
6515 return New_Reference_To (RTE (RE_POK_Task_Function), Loc);
6516
d62940bf 6517 -- Regular function
6518
6519 else
6520 return New_Reference_To (RTE (RE_POK_Function), Loc);
6521 end if;
6522
6523 else
6524 pragma Assert (Ekind (Prim_Op) = E_Procedure);
6525
6526 if Ekind (Full_Typ) = E_Protected_Type then
6527
6528 -- Protected entry
6529
6530 if Is_Primitive_Wrapper (Prim_Op)
6531 and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry
6532 then
6533 return New_Reference_To (RTE (RE_POK_Protected_Entry), Loc);
6534
6535 -- Protected procedure
6536
6537 else
6538 return New_Reference_To (RTE (RE_POK_Protected_Procedure), Loc);
6539 end if;
6540
6541 elsif Ekind (Full_Typ) = E_Task_Type then
6542
6543 -- Task entry
6544
6545 if Is_Primitive_Wrapper (Prim_Op)
6546 and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry
6547 then
6548 return New_Reference_To (RTE (RE_POK_Task_Entry), Loc);
6549
6550 -- Task "procedure". These are the internally Expander-generated
6551 -- procedures (task body for instance).
6552
6553 else
6554 return New_Reference_To (RTE (RE_POK_Task_Procedure), Loc);
6555 end if;
6556
6557 -- Regular procedure
6558
6559 else
6560 return New_Reference_To (RTE (RE_POK_Procedure), Loc);
6561 end if;
6562 end if;
6563 end Prim_Op_Kind;
6564
725a69d2 6565 ------------------------
6566 -- Register_Primitive --
6567 ------------------------
6568
49260fa5 6569 function Register_Primitive
725a69d2 6570 (Loc : Source_Ptr;
49260fa5 6571 Prim : Entity_Id) return List_Id
725a69d2 6572 is
cdb1c38f 6573 DT_Ptr : Entity_Id;
6574 Iface_Prim : Entity_Id;
6575 Iface_Typ : Entity_Id;
6576 Iface_DT_Ptr : Entity_Id;
6577 Iface_DT_Elmt : Elmt_Id;
49260fa5 6578 L : constant List_Id := New_List;
cdb1c38f 6579 Pos : Uint;
6580 Tag : Entity_Id;
cc60bd16 6581 Tag_Typ : Entity_Id;
cdb1c38f 6582 Thunk_Id : Entity_Id;
6583 Thunk_Code : Node_Id;
725a69d2 6584
6585 begin
6586 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
6587
6588 if not RTE_Available (RE_Tag) then
49260fa5 6589 return L;
725a69d2 6590 end if;
6591
a652dd51 6592 if not Present (Interface_Alias (Prim)) then
cc60bd16 6593 Tag_Typ := Scope (DTC_Entity (Prim));
acf97c11 6594 Pos := DT_Position (Prim);
cc60bd16 6595 Tag := First_Tag_Component (Tag_Typ);
725a69d2 6596
6597 if Is_Predefined_Dispatching_Operation (Prim)
6598 or else Is_Predefined_Dispatching_Alias (Prim)
6599 then
cc60bd16 6600 DT_Ptr :=
6601 Node (Next_Elmt (First_Elmt (Access_Disp_Table (Tag_Typ))));
6602
49260fa5 6603 Append_To (L,
725a69d2 6604 Build_Set_Predefined_Prim_Op_Address (Loc,
6605 Tag_Node => New_Reference_To (DT_Ptr, Loc),
6606 Position => Pos,
acf97c11 6607 Address_Node =>
cc60bd16 6608 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6609 Make_Attribute_Reference (Loc,
6610 Prefix => New_Reference_To (Prim, Loc),
6611 Attribute_Name => Name_Unrestricted_Access))));
725a69d2 6612
9e7de1e1 6613 -- Register copy of the pointer to the 'size primitive in the TSD
cc60bd16 6614
6615 if Chars (Prim) = Name_uSize
6616 and then RTE_Record_Component_Available (RE_Size_Func)
6617 then
6618 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Tag_Typ)));
49260fa5 6619 Append_To (L,
cc60bd16 6620 Build_Set_Size_Function (Loc,
6621 Tag_Node => New_Reference_To (DT_Ptr, Loc),
6622 Size_Func => Prim));
6623 end if;
6624
725a69d2 6625 else
6626 pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag));
6627
cc60bd16 6628 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Tag_Typ)));
49260fa5 6629 Append_To (L,
725a69d2 6630 Build_Set_Prim_Op_Address (Loc,
cc60bd16 6631 Typ => Tag_Typ,
725a69d2 6632 Tag_Node => New_Reference_To (DT_Ptr, Loc),
6633 Position => Pos,
acf97c11 6634 Address_Node =>
cc60bd16 6635 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6636 Make_Attribute_Reference (Loc,
6637 Prefix => New_Reference_To (Prim, Loc),
6638 Attribute_Name => Name_Unrestricted_Access))));
725a69d2 6639 end if;
6640
6641 -- Ada 2005 (AI-251): Primitive associated with an interface type
6642 -- Generate the code of the thunk only if the interface type is not an
6643 -- immediate ancestor of Typ; otherwise the dispatch table associated
6644 -- with the interface is the primary dispatch table and we have nothing
6645 -- else to do here.
6646
6647 else
cc60bd16 6648 Tag_Typ := Find_Dispatching_Type (Alias (Prim));
a652dd51 6649 Iface_Typ := Find_Dispatching_Type (Interface_Alias (Prim));
725a69d2 6650
6651 pragma Assert (Is_Interface (Iface_Typ));
6652
17e14451 6653 Expand_Interface_Thunk (Prim, Thunk_Id, Thunk_Code);
725a69d2 6654
a652dd51 6655 if not Is_Ancestor (Iface_Typ, Tag_Typ)
725a69d2 6656 and then Present (Thunk_Code)
6657 then
725a69d2 6658 -- Generate the code necessary to fill the appropriate entry of
6659 -- the secondary dispatch table of Prim's controlling type with
6660 -- Thunk_Id's address.
6661
cc60bd16 6662 Iface_DT_Elmt := Find_Interface_ADT (Tag_Typ, Iface_Typ);
cdb1c38f 6663 Iface_DT_Ptr := Node (Iface_DT_Elmt);
6664 pragma Assert (Has_Thunks (Iface_DT_Ptr));
6665
a652dd51 6666 Iface_Prim := Interface_Alias (Prim);
acf97c11 6667 Pos := DT_Position (Iface_Prim);
6668 Tag := First_Tag_Component (Iface_Typ);
49260fa5 6669
6670 Prepend_To (L, Thunk_Code);
725a69d2 6671
6672 if Is_Predefined_Dispatching_Operation (Prim)
6673 or else Is_Predefined_Dispatching_Alias (Prim)
6674 then
cdb1c38f 6675 Append_To (L,
725a69d2 6676 Build_Set_Predefined_Prim_Op_Address (Loc,
acf97c11 6677 Tag_Node =>
6678 New_Reference_To (Node (Next_Elmt (Iface_DT_Elmt)), Loc),
725a69d2 6679 Position => Pos,
6680 Address_Node =>
cc60bd16 6681 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6682 Make_Attribute_Reference (Loc,
6683 Prefix => New_Reference_To (Thunk_Id, Loc),
6684 Attribute_Name => Name_Unrestricted_Access))));
cdb1c38f 6685
acf97c11 6686 Next_Elmt (Iface_DT_Elmt);
cdb1c38f 6687 Next_Elmt (Iface_DT_Elmt);
6688 Iface_DT_Ptr := Node (Iface_DT_Elmt);
6689 pragma Assert (not Has_Thunks (Iface_DT_Ptr));
6690
6691 Append_To (L,
6692 Build_Set_Predefined_Prim_Op_Address (Loc,
acf97c11 6693 Tag_Node =>
6694 New_Reference_To (Node (Next_Elmt (Iface_DT_Elmt)), Loc),
cdb1c38f 6695 Position => Pos,
6696 Address_Node =>
cc60bd16 6697 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6698 Make_Attribute_Reference (Loc,
6699 Prefix => New_Reference_To (Alias (Prim), Loc),
6700 Attribute_Name => Name_Unrestricted_Access))));
cdb1c38f 6701
725a69d2 6702 else
6703 pragma Assert (Pos /= Uint_0
6704 and then Pos <= DT_Entry_Count (Tag));
6705
cdb1c38f 6706 Append_To (L,
6707 Build_Set_Prim_Op_Address (Loc,
6708 Typ => Iface_Typ,
6709 Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc),
6710 Position => Pos,
acf97c11 6711 Address_Node =>
cc60bd16 6712 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6713 Make_Attribute_Reference (Loc,
6714 Prefix => New_Reference_To (Thunk_Id, Loc),
6715 Attribute_Name => Name_Unrestricted_Access))));
cdb1c38f 6716
acf97c11 6717 Next_Elmt (Iface_DT_Elmt);
cdb1c38f 6718 Next_Elmt (Iface_DT_Elmt);
6719 Iface_DT_Ptr := Node (Iface_DT_Elmt);
6720 pragma Assert (not Has_Thunks (Iface_DT_Ptr));
6721
6722 Append_To (L,
725a69d2 6723 Build_Set_Prim_Op_Address (Loc,
6724 Typ => Iface_Typ,
6725 Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc),
6726 Position => Pos,
acf97c11 6727 Address_Node =>
cc60bd16 6728 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
acf97c11 6729 Make_Attribute_Reference (Loc,
6730 Prefix => New_Reference_To (Alias (Prim), Loc),
6731 Attribute_Name => Name_Unrestricted_Access))));
cdb1c38f 6732
725a69d2 6733 end if;
6734 end if;
6735 end if;
49260fa5 6736
6737 return L;
725a69d2 6738 end Register_Primitive;
6739
ee6ba406 6740 -------------------------
6741 -- Set_All_DT_Position --
6742 -------------------------
6743
6744 procedure Set_All_DT_Position (Typ : Entity_Id) is
ee6ba406 6745
aad6babd 6746 procedure Validate_Position (Prim : Entity_Id);
36b938a3 6747 -- Check that the position assigned to Prim is completely safe
aad6babd 6748 -- (it has not been assigned to a previously defined primitive
6749 -- operation of Typ)
6750
6751 -----------------------
6752 -- Validate_Position --
6753 -----------------------
6754
6755 procedure Validate_Position (Prim : Entity_Id) is
af647dc7 6756 Op_Elmt : Elmt_Id;
6757 Op : Entity_Id;
d62940bf 6758
aad6babd 6759 begin
af647dc7 6760 -- Aliased primitives are safe
6761
6762 if Present (Alias (Prim)) then
6763 return;
6764 end if;
6765
6766 Op_Elmt := First_Elmt (Primitive_Operations (Typ));
6767 while Present (Op_Elmt) loop
6768 Op := Node (Op_Elmt);
6769
6770 -- No need to check against itself
6771
6772 if Op = Prim then
6773 null;
6774
aad6babd 6775 -- Primitive operations covering abstract interfaces are
6776 -- allocated later
6777
a652dd51 6778 elsif Present (Interface_Alias (Op)) then
aad6babd 6779 null;
6780
68f95949 6781 -- Predefined dispatching operations are completely safe. They
6782 -- are allocated at fixed positions in a separate table.
aad6babd 6783
af647dc7 6784 elsif Is_Predefined_Dispatching_Operation (Op)
6785 or else Is_Predefined_Dispatching_Alias (Op)
6786 then
aad6babd 6787 null;
ee6ba406 6788
aad6babd 6789 -- Aliased subprograms are safe
6790
af647dc7 6791 elsif Present (Alias (Op)) then
aad6babd 6792 null;
6793
af647dc7 6794 elsif DT_Position (Op) = DT_Position (Prim)
6795 and then not Is_Predefined_Dispatching_Operation (Op)
6796 and then not Is_Predefined_Dispatching_Operation (Prim)
6797 and then not Is_Predefined_Dispatching_Alias (Op)
6798 and then not Is_Predefined_Dispatching_Alias (Prim)
6799 then
d62940bf 6800
6801 -- Handle aliased subprograms
6802
6803 declare
6804 Op_1 : Entity_Id;
6805 Op_2 : Entity_Id;
6806
6807 begin
af647dc7 6808 Op_1 := Op;
d62940bf 6809 loop
6810 if Present (Overridden_Operation (Op_1)) then
6811 Op_1 := Overridden_Operation (Op_1);
6812 elsif Present (Alias (Op_1)) then
6813 Op_1 := Alias (Op_1);
6814 else
6815 exit;
6816 end if;
6817 end loop;
6818
6819 Op_2 := Prim;
6820 loop
6821 if Present (Overridden_Operation (Op_2)) then
6822 Op_2 := Overridden_Operation (Op_2);
6823 elsif Present (Alias (Op_2)) then
6824 Op_2 := Alias (Op_2);
6825 else
6826 exit;
6827 end if;
6828 end loop;
6829
6830 if Op_1 /= Op_2 then
6831 raise Program_Error;
6832 end if;
6833 end;
aad6babd 6834 end if;
6835
af647dc7 6836 Next_Elmt (Op_Elmt);
aad6babd 6837 end loop;
6838 end Validate_Position;
6839
af647dc7 6840 -- Local variables
6841
6842 Parent_Typ : constant Entity_Id := Etype (Typ);
af647dc7 6843 First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ));
6844 The_Tag : constant Entity_Id := First_Tag_Component (Typ);
6845
6846 Adjusted : Boolean := False;
6847 Finalized : Boolean := False;
6848
343d35dc 6849 Count_Prim : Nat;
6850 DT_Length : Nat;
6851 Nb_Prim : Nat;
af647dc7 6852 Prim : Entity_Id;
6853 Prim_Elmt : Elmt_Id;
6854
aad6babd 6855 -- Start of processing for Set_All_DT_Position
6856
6857 begin
a652dd51 6858 pragma Assert (Present (First_Tag_Component (Typ)));
6859
343d35dc 6860 -- Set the DT_Position for each primitive operation. Perform some
36b938a3 6861 -- sanity checks to avoid to build completely inconsistent dispatch
343d35dc 6862 -- tables.
ee6ba406 6863
343d35dc 6864 -- First stage: Set the DTC entity of all the primitive operations
6865 -- This is required to properly read the DT_Position attribute in
6866 -- the latter stages.
ee6ba406 6867
343d35dc 6868 Prim_Elmt := First_Prim;
6869 Count_Prim := 0;
6870 while Present (Prim_Elmt) loop
6871 Prim := Node (Prim_Elmt);
ee6ba406 6872
343d35dc 6873 -- Predefined primitives have a separate dispatch table
ee6ba406 6874
343d35dc 6875 if not (Is_Predefined_Dispatching_Operation (Prim)
6876 or else Is_Predefined_Dispatching_Alias (Prim))
6877 then
6878 Count_Prim := Count_Prim + 1;
6879 end if;
ee6ba406 6880
725a69d2 6881 Set_DTC_Entity_Value (Typ, Prim);
ee6ba406 6882
343d35dc 6883 -- Clear any previous value of the DT_Position attribute. In this
6884 -- way we ensure that the final position of all the primitives is
36b938a3 6885 -- established by the following stages of this algorithm.
ee6ba406 6886
343d35dc 6887 Set_DT_Position (Prim, No_Uint);
ee6ba406 6888
343d35dc 6889 Next_Elmt (Prim_Elmt);
6890 end loop;
ee6ba406 6891
343d35dc 6892 declare
acf97c11 6893 Fixed_Prim : array (Int range 0 .. Count_Prim) of Boolean :=
6894 (others => False);
6895
343d35dc 6896 E : Entity_Id;
ee6ba406 6897
725a69d2 6898 procedure Handle_Inherited_Private_Subprograms (Typ : Entity_Id);
6899 -- Called if Typ is declared in a nested package or a public child
6900 -- package to handle inherited primitives that were inherited by Typ
6901 -- in the visible part, but whose declaration was deferred because
6902 -- the parent operation was private and not visible at that point.
6903
343d35dc 6904 procedure Set_Fixed_Prim (Pos : Nat);
6905 -- Sets to true an element of the Fixed_Prim table to indicate
6906 -- that this entry of the dispatch table of Typ is occupied.
ee6ba406 6907
725a69d2 6908 ------------------------------------------
6909 -- Handle_Inherited_Private_Subprograms --
6910 ------------------------------------------
6911
6912 procedure Handle_Inherited_Private_Subprograms (Typ : Entity_Id) is
6913 Op_List : Elist_Id;
6914 Op_Elmt : Elmt_Id;
6915 Op_Elmt_2 : Elmt_Id;
6916 Prim_Op : Entity_Id;
6917 Parent_Subp : Entity_Id;
6918
6919 begin
6920 Op_List := Primitive_Operations (Typ);
6921
6922 Op_Elmt := First_Elmt (Op_List);
6923 while Present (Op_Elmt) loop
6924 Prim_Op := Node (Op_Elmt);
6925
6926 -- Search primitives that are implicit operations with an
6927 -- internal name whose parent operation has a normal name.
6928
6929 if Present (Alias (Prim_Op))
6930 and then Find_Dispatching_Type (Alias (Prim_Op)) /= Typ
6931 and then not Comes_From_Source (Prim_Op)
6932 and then Is_Internal_Name (Chars (Prim_Op))
6933 and then not Is_Internal_Name (Chars (Alias (Prim_Op)))
6934 then
6935 Parent_Subp := Alias (Prim_Op);
6936
6937 -- Check if the type has an explicit overriding for this
6938 -- primitive.
6939
6940 Op_Elmt_2 := Next_Elmt (Op_Elmt);
6941 while Present (Op_Elmt_2) loop
6942 if Chars (Node (Op_Elmt_2)) = Chars (Parent_Subp)
6943 and then Type_Conformant (Prim_Op, Node (Op_Elmt_2))
6944 then
6945 Set_DT_Position (Prim_Op, DT_Position (Parent_Subp));
6946 Set_DT_Position (Node (Op_Elmt_2),
6947 DT_Position (Parent_Subp));
6948 Set_Fixed_Prim (UI_To_Int (DT_Position (Prim_Op)));
6949
6950 goto Next_Primitive;
6951 end if;
6952
6953 Next_Elmt (Op_Elmt_2);
6954 end loop;
6955 end if;
6956
6957 <<Next_Primitive>>
6958 Next_Elmt (Op_Elmt);
6959 end loop;
6960 end Handle_Inherited_Private_Subprograms;
6961
343d35dc 6962 --------------------
6963 -- Set_Fixed_Prim --
6964 --------------------
ee6ba406 6965
343d35dc 6966 procedure Set_Fixed_Prim (Pos : Nat) is
ee6ba406 6967 begin
9e7de1e1 6968 pragma Assert (Pos <= Count_Prim);
343d35dc 6969 Fixed_Prim (Pos) := True;
6970 exception
6971 when Constraint_Error =>
6972 raise Program_Error;
6973 end Set_Fixed_Prim;
ee6ba406 6974
343d35dc 6975 begin
725a69d2 6976 -- In case of nested packages and public child package it may be
6977 -- necessary a special management on inherited subprograms so that
6978 -- the dispatch table is properly filled.
6979
6980 if Ekind (Scope (Scope (Typ))) = E_Package
6981 and then Scope (Scope (Typ)) /= Standard_Standard
6982 and then ((Is_Derived_Type (Typ) and then not Is_Private_Type (Typ))
6983 or else
6984 (Nkind (Parent (Typ)) = N_Private_Extension_Declaration
6985 and then Is_Generic_Type (Typ)))
6986 and then In_Open_Scopes (Scope (Etype (Typ)))
6987 and then Typ = Base_Type (Typ)
6988 then
6989 Handle_Inherited_Private_Subprograms (Typ);
6990 end if;
6991
343d35dc 6992 -- Second stage: Register fixed entries
ee6ba406 6993
343d35dc 6994 Nb_Prim := 0;
6995 Prim_Elmt := First_Prim;
6996 while Present (Prim_Elmt) loop
6997 Prim := Node (Prim_Elmt);
ee6ba406 6998
343d35dc 6999 -- Predefined primitives have a separate table and all its
7000 -- entries are at predefined fixed positions.
ee6ba406 7001
343d35dc 7002 if Is_Predefined_Dispatching_Operation (Prim) then
7003 Set_DT_Position (Prim, Default_Prim_Op_Position (Prim));
ee6ba406 7004
343d35dc 7005 elsif Is_Predefined_Dispatching_Alias (Prim) then
7006 E := Alias (Prim);
7007 while Present (Alias (E)) loop
7008 E := Alias (E);
7009 end loop;
d62940bf 7010
343d35dc 7011 Set_DT_Position (Prim, Default_Prim_Op_Position (E));
d62940bf 7012
343d35dc 7013 -- Overriding primitives of ancestor abstract interfaces
ee6ba406 7014
a652dd51 7015 elsif Present (Interface_Alias (Prim))
7016 and then Is_Ancestor
7017 (Find_Dispatching_Type (Interface_Alias (Prim)), Typ)
343d35dc 7018 then
7019 pragma Assert (DT_Position (Prim) = No_Uint
a652dd51 7020 and then Present (DTC_Entity (Interface_Alias (Prim))));
ee6ba406 7021
a652dd51 7022 E := Interface_Alias (Prim);
343d35dc 7023 Set_DT_Position (Prim, DT_Position (E));
aad6babd 7024
343d35dc 7025 pragma Assert
7026 (DT_Position (Alias (Prim)) = No_Uint
7027 or else DT_Position (Alias (Prim)) = DT_Position (E));
7028 Set_DT_Position (Alias (Prim), DT_Position (E));
7029 Set_Fixed_Prim (UI_To_Int (DT_Position (Prim)));
af647dc7 7030
343d35dc 7031 -- Overriding primitives must use the same entry as the
36b938a3 7032 -- overridden primitive.
af647dc7 7033
a652dd51 7034 elsif not Present (Interface_Alias (Prim))
343d35dc 7035 and then Present (Alias (Prim))
17e14451 7036 and then Chars (Prim) = Chars (Alias (Prim))
343d35dc 7037 and then Find_Dispatching_Type (Alias (Prim)) /= Typ
a652dd51 7038 and then Is_Ancestor
343d35dc 7039 (Find_Dispatching_Type (Alias (Prim)), Typ)
7040 and then Present (DTC_Entity (Alias (Prim)))
af647dc7 7041 then
343d35dc 7042 E := Alias (Prim);
7043 Set_DT_Position (Prim, DT_Position (E));
aad6babd 7044
343d35dc 7045 if not Is_Predefined_Dispatching_Alias (E) then
7046 Set_Fixed_Prim (UI_To_Int (DT_Position (E)));
7047 end if;
9dfe12ae 7048 end if;
ee6ba406 7049
aad6babd 7050 Next_Elmt (Prim_Elmt);
7051 end loop;
7052
343d35dc 7053 -- Third stage: Fix the position of all the new primitives
7054 -- Entries associated with primitives covering interfaces
7055 -- are handled in a latter round.
aad6babd 7056
343d35dc 7057 Prim_Elmt := First_Prim;
7058 while Present (Prim_Elmt) loop
7059 Prim := Node (Prim_Elmt);
aad6babd 7060
343d35dc 7061 -- Skip primitives previously set entries
aad6babd 7062
343d35dc 7063 if DT_Position (Prim) /= No_Uint then
7064 null;
aad6babd 7065
343d35dc 7066 -- Primitives covering interface primitives are handled later
aad6babd 7067
a652dd51 7068 elsif Present (Interface_Alias (Prim)) then
343d35dc 7069 null;
aad6babd 7070
343d35dc 7071 else
7072 -- Take the next available position in the DT
aad6babd 7073
343d35dc 7074 loop
7075 Nb_Prim := Nb_Prim + 1;
7076 pragma Assert (Nb_Prim <= Count_Prim);
7077 exit when not Fixed_Prim (Nb_Prim);
7078 end loop;
aad6babd 7079
343d35dc 7080 Set_DT_Position (Prim, UI_From_Int (Nb_Prim));
7081 Set_Fixed_Prim (Nb_Prim);
7082 end if;
aad6babd 7083
343d35dc 7084 Next_Elmt (Prim_Elmt);
7085 end loop;
7086 end;
aad6babd 7087
343d35dc 7088 -- Fourth stage: Complete the decoration of primitives covering
7089 -- interfaces (that is, propagate the DT_Position attribute
7090 -- from the aliased primitive)
aad6babd 7091
343d35dc 7092 Prim_Elmt := First_Prim;
7093 while Present (Prim_Elmt) loop
7094 Prim := Node (Prim_Elmt);
aad6babd 7095
343d35dc 7096 if DT_Position (Prim) = No_Uint
a652dd51 7097 and then Present (Interface_Alias (Prim))
343d35dc 7098 then
7099 pragma Assert (Present (Alias (Prim))
7100 and then Find_Dispatching_Type (Alias (Prim)) = Typ);
aad6babd 7101
343d35dc 7102 -- Check if this entry will be placed in the primary DT
aad6babd 7103
a652dd51 7104 if Is_Ancestor
7105 (Find_Dispatching_Type (Interface_Alias (Prim)), Typ)
ee6ba406 7106 then
343d35dc 7107 pragma Assert (DT_Position (Alias (Prim)) /= No_Uint);
7108 Set_DT_Position (Prim, DT_Position (Alias (Prim)));
aad6babd 7109
343d35dc 7110 -- Otherwise it will be placed in the secondary DT
aad6babd 7111
343d35dc 7112 else
7113 pragma Assert
a652dd51 7114 (DT_Position (Interface_Alias (Prim)) /= No_Uint);
343d35dc 7115 Set_DT_Position (Prim,
a652dd51 7116 DT_Position (Interface_Alias (Prim)));
aad6babd 7117 end if;
343d35dc 7118 end if;
aad6babd 7119
343d35dc 7120 Next_Elmt (Prim_Elmt);
7121 end loop;
d62940bf 7122
343d35dc 7123 -- Generate listing showing the contents of the dispatch tables.
7124 -- This action is done before some further static checks because
7125 -- in case of critical errors caused by a wrong dispatch table
7126 -- we need to see the contents of such table.
d62940bf 7127
343d35dc 7128 if Debug_Flag_ZZ then
7129 Write_DT (Typ);
7130 end if;
aad6babd 7131
343d35dc 7132 -- Final stage: Ensure that the table is correct plus some further
7133 -- verifications concerning the primitives.
aad6babd 7134
343d35dc 7135 Prim_Elmt := First_Prim;
7136 DT_Length := 0;
7137 while Present (Prim_Elmt) loop
7138 Prim := Node (Prim_Elmt);
aad6babd 7139
343d35dc 7140 -- At this point all the primitives MUST have a position
acf97c11 7141 -- in the dispatch table.
aad6babd 7142
343d35dc 7143 if DT_Position (Prim) = No_Uint then
7144 raise Program_Error;
7145 end if;
aad6babd 7146
343d35dc 7147 -- Calculate real size of the dispatch table
aad6babd 7148
343d35dc 7149 if not (Is_Predefined_Dispatching_Operation (Prim)
7150 or else Is_Predefined_Dispatching_Alias (Prim))
7151 and then UI_To_Int (DT_Position (Prim)) > DT_Length
7152 then
7153 DT_Length := UI_To_Int (DT_Position (Prim));
7154 end if;
aad6babd 7155
36b938a3 7156 -- Ensure that the assigned position to non-predefined
343d35dc 7157 -- dispatching operations in the dispatch table is correct.
aad6babd 7158
343d35dc 7159 if not (Is_Predefined_Dispatching_Operation (Prim)
7160 or else Is_Predefined_Dispatching_Alias (Prim))
7161 then
7162 Validate_Position (Prim);
7163 end if;
ee6ba406 7164
343d35dc 7165 if Chars (Prim) = Name_Finalize then
7166 Finalized := True;
7167 end if;
ee6ba406 7168
343d35dc 7169 if Chars (Prim) = Name_Adjust then
7170 Adjusted := True;
7171 end if;
af647dc7 7172
343d35dc 7173 -- An abstract operation cannot be declared in the private part
7174 -- for a visible abstract type, because it could never be over-
7175 -- ridden. For explicit declarations this is checked at the
7176 -- point of declaration, but for inherited operations it must
7177 -- be done when building the dispatch table.
7178
a652dd51 7179 -- Ada 2005 (AI-251): Primitives associated with interfaces are
7180 -- excluded from this check because interfaces must be visible in
7181 -- the public and private part (RM 7.3 (7.3/2))
343d35dc 7182
7183 if Is_Abstract_Type (Typ)
7184 and then Is_Abstract_Subprogram (Prim)
7185 and then Present (Alias (Prim))
a652dd51 7186 and then not Is_Interface
7187 (Find_Dispatching_Type (Ultimate_Alias (Prim)))
7188 and then not Present (Interface_Alias (Prim))
343d35dc 7189 and then Is_Derived_Type (Typ)
7190 and then In_Private_Part (Current_Scope)
7191 and then
7192 List_Containing (Parent (Prim)) =
7193 Private_Declarations
7194 (Specification (Unit_Declaration_Node (Current_Scope)))
7195 and then Original_View_In_Visible_Part (Typ)
7196 then
7197 -- We exclude Input and Output stream operations because
7198 -- Limited_Controlled inherits useless Input and Output
7199 -- stream operations from Root_Controlled, which can
7200 -- never be overridden.
ee6ba406 7201
343d35dc 7202 if not Is_TSS (Prim, TSS_Stream_Input)
7203 and then
7204 not Is_TSS (Prim, TSS_Stream_Output)
ee6ba406 7205 then
343d35dc 7206 Error_Msg_NE
7207 ("abstract inherited private operation&" &
17e14451 7208 " must be overridden (RM 3.9.3(10))",
343d35dc 7209 Parent (Typ), Prim);
ee6ba406 7210 end if;
343d35dc 7211 end if;
aad6babd 7212
343d35dc 7213 Next_Elmt (Prim_Elmt);
7214 end loop;
ee6ba406 7215
343d35dc 7216 -- Additional check
aad6babd 7217
343d35dc 7218 if Is_Controlled (Typ) then
7219 if not Finalized then
7220 Error_Msg_N
7221 ("controlled type has no explicit Finalize method?", Typ);
ee6ba406 7222
343d35dc 7223 elsif not Adjusted then
7224 Error_Msg_N
7225 ("controlled type has no explicit Adjust method?", Typ);
ee6ba406 7226 end if;
343d35dc 7227 end if;
ee6ba406 7228
343d35dc 7229 -- Set the final size of the Dispatch Table
aad6babd 7230
343d35dc 7231 Set_DT_Entry_Count (The_Tag, UI_From_Int (DT_Length));
ee6ba406 7232
725a69d2 7233 -- The derived type must have at least as many components as its parent
acf97c11 7234 -- (for root types Etype points to itself and the test cannot fail).
aad6babd 7235
725a69d2 7236 if DT_Entry_Count (The_Tag) <
7237 DT_Entry_Count (First_Tag_Component (Parent_Typ))
7238 then
7239 raise Program_Error;
aad6babd 7240 end if;
ee6ba406 7241 end Set_All_DT_Position;
7242
294b942d 7243 --------------------------
7244 -- Set_CPP_Constructors --
7245 --------------------------
ee6ba406 7246
294b942d 7247 procedure Set_CPP_Constructors (Typ : Entity_Id) is
ee6ba406 7248 Loc : Source_Ptr;
7249 Init : Entity_Id;
ee6ba406 7250 E : Entity_Id;
294b942d 7251 Found : Boolean := False;
7252 P : Node_Id;
7253 Parms : List_Id;
ee6ba406 7254
7255 begin
294b942d 7256 -- Look for the constructor entities
ee6ba406 7257
7258 E := Next_Entity (Typ);
294b942d 7259 while Present (E) loop
7260 if Ekind (E) = E_Function
7261 and then Is_Constructor (E)
7262 then
7263 -- Create the init procedure
7264
7265 Found := True;
7266 Loc := Sloc (E);
7267 Init := Make_Defining_Identifier (Loc, Make_Init_Proc_Name (Typ));
7268 Parms :=
7269 New_List (
7270 Make_Parameter_Specification (Loc,
7271 Defining_Identifier =>
7272 Make_Defining_Identifier (Loc, Name_X),
7273 Parameter_Type =>
7274 New_Reference_To (Typ, Loc)));
7275
7276 if Present (Parameter_Specifications (Parent (E))) then
7277 P := First (Parameter_Specifications (Parent (E)));
7278 while Present (P) loop
7279 Append_To (Parms,
7280 Make_Parameter_Specification (Loc,
7281 Defining_Identifier =>
7282 Make_Defining_Identifier (Loc,
7283 Chars (Defining_Identifier (P))),
7284 Parameter_Type => New_Copy_Tree (Parameter_Type (P))));
7285 Next (P);
7286 end loop;
7287 end if;
7288
7289 Discard_Node (
7290 Make_Subprogram_Declaration (Loc,
7291 Make_Procedure_Specification (Loc,
7292 Defining_Unit_Name => Init,
7293 Parameter_Specifications => Parms)));
7294
7295 Set_Init_Proc (Typ, Init);
7296 Set_Is_Imported (Init);
7297 Set_Interface_Name (Init, Interface_Name (E));
7298 Set_Convention (Init, Convention_C);
7299 Set_Is_Public (Init);
7300 Set_Has_Completion (Init);
7301 end if;
7302
ee6ba406 7303 Next_Entity (E);
7304 end loop;
7305
9dfe12ae 7306 -- If there are no constructors, mark the type as abstract since we
ee6ba406 7307 -- won't be able to declare objects of that type.
7308
294b942d 7309 if not Found then
343d35dc 7310 Set_Is_Abstract_Type (Typ);
ee6ba406 7311 end if;
294b942d 7312 end Set_CPP_Constructors;
ee6ba406 7313
725a69d2 7314 --------------------------
7315 -- Set_DTC_Entity_Value --
7316 --------------------------
7317
7318 procedure Set_DTC_Entity_Value
7319 (Tagged_Type : Entity_Id;
7320 Prim : Entity_Id)
7321 is
7322 begin
a652dd51 7323 if Present (Interface_Alias (Prim))
725a69d2 7324 and then Is_Interface
a652dd51 7325 (Find_Dispatching_Type (Interface_Alias (Prim)))
725a69d2 7326 then
7327 Set_DTC_Entity (Prim,
7328 Find_Interface_Tag
7329 (T => Tagged_Type,
a652dd51 7330 Iface => Find_Dispatching_Type (Interface_Alias (Prim))));
725a69d2 7331 else
7332 Set_DTC_Entity (Prim,
7333 First_Tag_Component (Tagged_Type));
7334 end if;
7335 end Set_DTC_Entity_Value;
7336
952af0b9 7337 -----------------
7338 -- Tagged_Kind --
7339 -----------------
7340
7341 function Tagged_Kind (T : Entity_Id) return Node_Id is
7342 Conc_Typ : Entity_Id;
7343 Loc : constant Source_Ptr := Sloc (T);
7344
7345 begin
68f95949 7346 pragma Assert
7347 (Is_Tagged_Type (T) and then RTE_Available (RE_Tagged_Kind));
952af0b9 7348
7349 -- Abstract kinds
7350
343d35dc 7351 if Is_Abstract_Type (T) then
952af0b9 7352 if Is_Limited_Record (T) then
7353 return New_Reference_To (RTE (RE_TK_Abstract_Limited_Tagged), Loc);
7354 else
7355 return New_Reference_To (RTE (RE_TK_Abstract_Tagged), Loc);
7356 end if;
7357
7358 -- Concurrent kinds
7359
7360 elsif Is_Concurrent_Record_Type (T) then
7361 Conc_Typ := Corresponding_Concurrent_Type (T);
7362
17e14451 7363 if Present (Full_View (Conc_Typ)) then
7364 Conc_Typ := Full_View (Conc_Typ);
7365 end if;
7366
952af0b9 7367 if Ekind (Conc_Typ) = E_Protected_Type then
7368 return New_Reference_To (RTE (RE_TK_Protected), Loc);
7369 else
7370 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
7371 return New_Reference_To (RTE (RE_TK_Task), Loc);
7372 end if;
7373
7374 -- Regular tagged kinds
7375
7376 else
7377 if Is_Limited_Record (T) then
7378 return New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc);
7379 else
7380 return New_Reference_To (RTE (RE_TK_Tagged), Loc);
7381 end if;
7382 end if;
7383 end Tagged_Kind;
7384
aad6babd 7385 --------------
7386 -- Write_DT --
7387 --------------
7388
7389 procedure Write_DT (Typ : Entity_Id) is
7390 Elmt : Elmt_Id;
7391 Prim : Node_Id;
7392
7393 begin
7394 -- Protect this procedure against wrong usage. Required because it will
7395 -- be used directly from GDB
7396
17e14451 7397 if not (Typ <= Last_Node_Id)
aad6babd 7398 or else not Is_Tagged_Type (Typ)
7399 then
d62940bf 7400 Write_Str ("wrong usage: Write_DT must be used with tagged types");
aad6babd 7401 Write_Eol;
7402 return;
7403 end if;
7404
7405 Write_Int (Int (Typ));
7406 Write_Str (": ");
7407 Write_Name (Chars (Typ));
7408
7409 if Is_Interface (Typ) then
7410 Write_Str (" is interface");
7411 end if;
7412
7413 Write_Eol;
7414
7415 Elmt := First_Elmt (Primitive_Operations (Typ));
7416 while Present (Elmt) loop
7417 Prim := Node (Elmt);
7418 Write_Str (" - ");
7419
7420 -- Indicate if this primitive will be allocated in the primary
7421 -- dispatch table or in a secondary dispatch table associated
7422 -- with an abstract interface type
7423
7424 if Present (DTC_Entity (Prim)) then
7425 if Etype (DTC_Entity (Prim)) = RTE (RE_Tag) then
7426 Write_Str ("[P] ");
7427 else
7428 Write_Str ("[s] ");
7429 end if;
7430 end if;
7431
7432 -- Output the node of this primitive operation and its name
7433
7434 Write_Int (Int (Prim));
7435 Write_Str (": ");
68f95949 7436
7437 if Is_Predefined_Dispatching_Operation (Prim) then
7438 Write_Str ("(predefined) ");
7439 end if;
7440
aad6babd 7441 Write_Name (Chars (Prim));
7442
7443 -- Indicate if this primitive has an aliased primitive
7444
7445 if Present (Alias (Prim)) then
7446 Write_Str (" (alias = ");
7447 Write_Int (Int (Alias (Prim)));
7448
7449 -- If the DTC_Entity attribute is already set we can also output
7450 -- the name of the interface covered by this primitive (if any)
7451
7452 if Present (DTC_Entity (Alias (Prim)))
7453 and then Is_Interface (Scope (DTC_Entity (Alias (Prim))))
7454 then
7455 Write_Str (" from interface ");
7456 Write_Name (Chars (Scope (DTC_Entity (Alias (Prim)))));
7457 end if;
7458
a652dd51 7459 if Present (Interface_Alias (Prim)) then
aad6babd 7460 Write_Str (", AI_Alias of ");
a652dd51 7461 Write_Name
7462 (Chars (Find_Dispatching_Type (Interface_Alias (Prim))));
aad6babd 7463 Write_Char (':');
a652dd51 7464 Write_Int (Int (Interface_Alias (Prim)));
aad6babd 7465 end if;
7466
7467 Write_Str (")");
7468 end if;
7469
7470 -- Display the final position of this primitive in its associated
7471 -- (primary or secondary) dispatch table
7472
7473 if Present (DTC_Entity (Prim))
7474 and then DT_Position (Prim) /= No_Uint
7475 then
7476 Write_Str (" at #");
7477 Write_Int (UI_To_Int (DT_Position (Prim)));
7478 end if;
7479
343d35dc 7480 if Is_Abstract_Subprogram (Prim) then
aad6babd 7481 Write_Str (" is abstract;");
af647dc7 7482
7483 -- Check if this is a null primitive
7484
7485 elsif Comes_From_Source (Prim)
7486 and then Ekind (Prim) = E_Procedure
7487 and then Null_Present (Parent (Prim))
7488 then
7489 Write_Str (" is null;");
aad6babd 7490 end if;
7491
555c63a6 7492 if Is_Eliminated (Ultimate_Alias (Prim)) then
7493 Write_Str (" (eliminated)");
7494 end if;
7495
aad6babd 7496 Write_Eol;
7497
7498 Next_Elmt (Elmt);
7499 end loop;
7500 end Write_DT;
7501
ee6ba406 7502end Exp_Disp;