Dead
[official-gcc.git] / gomp-20050608-branch / gcc / ada / exp_disp.adb
bloba29714e976c6b906d52a021a6e426e0cf43c0cf7
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ D I S P --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Checks; use Checks;
29 with Debug; use Debug;
30 with Einfo; use Einfo;
31 with Elists; use Elists;
32 with Errout; use Errout;
33 with Exp_Ch7; use Exp_Ch7;
34 with Exp_Dbug; use Exp_Dbug;
35 with Exp_Tss; use Exp_Tss;
36 with Exp_Util; use Exp_Util;
37 with Itypes; use Itypes;
38 with Nlists; use Nlists;
39 with Nmake; use Nmake;
40 with Namet; use Namet;
41 with Opt; use Opt;
42 with Output; use Output;
43 with Restrict; use Restrict;
44 with Rident; use Rident;
45 with Rtsfind; use Rtsfind;
46 with Sem; use Sem;
47 with Sem_Disp; use Sem_Disp;
48 with Sem_Res; use Sem_Res;
49 with Sem_Type; use Sem_Type;
50 with Sem_Util; use Sem_Util;
51 with Sinfo; use Sinfo;
52 with Snames; use Snames;
53 with Stand; use Stand;
54 with Tbuild; use Tbuild;
55 with Uintp; use Uintp;
57 package body Exp_Disp is
59 --------------------------------
60 -- Select_Expansion_Utilities --
61 --------------------------------
63 -- The following package contains helper routines used in the expansion of
64 -- dispatching asynchronous, conditional and timed selects.
66 package Select_Expansion_Utilities is
67 procedure Build_B
68 (Loc : Source_Ptr;
69 Params : List_Id);
70 -- Generate:
71 -- B : out Communication_Block
73 procedure Build_C
74 (Loc : Source_Ptr;
75 Params : List_Id);
76 -- Generate:
77 -- C : out Prim_Op_Kind
79 procedure Build_Common_Dispatching_Select_Statements
80 (Loc : Source_Ptr;
81 Typ : Entity_Id;
82 DT_Ptr : Entity_Id;
83 Stmts : List_Id);
84 -- Ada 2005 (AI-345): Generate statements that are common between
85 -- asynchronous, conditional and timed select expansion.
87 procedure Build_F
88 (Loc : Source_Ptr;
89 Params : List_Id);
90 -- Generate:
91 -- F : out Boolean
93 procedure Build_P
94 (Loc : Source_Ptr;
95 Params : List_Id);
96 -- Generate:
97 -- P : Address
99 procedure Build_S
100 (Loc : Source_Ptr;
101 Params : List_Id);
102 -- Generate:
103 -- S : Integer
105 procedure Build_T
106 (Loc : Source_Ptr;
107 Typ : Entity_Id;
108 Params : List_Id);
109 -- Generate:
110 -- T : in out Typ
111 end Select_Expansion_Utilities;
113 package body Select_Expansion_Utilities is
115 -------------
116 -- Build_B --
117 -------------
119 procedure Build_B
120 (Loc : Source_Ptr;
121 Params : List_Id)
123 begin
124 Append_To (Params,
125 Make_Parameter_Specification (Loc,
126 Defining_Identifier =>
127 Make_Defining_Identifier (Loc, Name_uB),
128 Parameter_Type =>
129 New_Reference_To (RTE (RE_Communication_Block), Loc),
130 Out_Present => True));
131 end Build_B;
133 -------------
134 -- Build_C --
135 -------------
137 procedure Build_C
138 (Loc : Source_Ptr;
139 Params : List_Id)
141 begin
142 Append_To (Params,
143 Make_Parameter_Specification (Loc,
144 Defining_Identifier =>
145 Make_Defining_Identifier (Loc, Name_uC),
146 Parameter_Type =>
147 New_Reference_To (RTE (RE_Prim_Op_Kind), Loc),
148 Out_Present => True));
149 end Build_C;
151 ------------------------------------------------
152 -- Build_Common_Dispatching_Select_Statements --
153 ------------------------------------------------
155 procedure Build_Common_Dispatching_Select_Statements
156 (Loc : Source_Ptr;
157 Typ : Entity_Id;
158 DT_Ptr : Entity_Id;
159 Stmts : List_Id)
161 begin
162 -- Generate:
163 -- C := get_prim_op_kind (tag! (<type>VP), S);
165 -- where C is the out parameter capturing the call kind and S is the
166 -- dispatch table slot number.
168 Append_To (Stmts,
169 Make_Assignment_Statement (Loc,
170 Name =>
171 Make_Identifier (Loc, Name_uC),
172 Expression =>
173 Make_DT_Access_Action (Typ,
174 Action =>
175 Get_Prim_Op_Kind,
176 Args =>
177 New_List (
178 Unchecked_Convert_To (RTE (RE_Tag),
179 New_Reference_To (DT_Ptr, Loc)),
180 Make_Identifier (Loc, Name_uS)))));
182 -- Generate:
184 -- if C = POK_Procedure
185 -- or else C = POK_Protected_Procedure
186 -- or else C = POK_Task_Procedure;
187 -- then
188 -- F := True;
189 -- return;
191 -- where F is the out parameter capturing the status of a potential
192 -- entry call.
194 Append_To (Stmts,
195 Make_If_Statement (Loc,
197 Condition =>
198 Make_Or_Else (Loc,
199 Left_Opnd =>
200 Make_Op_Eq (Loc,
201 Left_Opnd =>
202 Make_Identifier (Loc, Name_uC),
203 Right_Opnd =>
204 New_Reference_To (RTE (RE_POK_Procedure), Loc)),
205 Right_Opnd =>
206 Make_Or_Else (Loc,
207 Left_Opnd =>
208 Make_Op_Eq (Loc,
209 Left_Opnd =>
210 Make_Identifier (Loc, Name_uC),
211 Right_Opnd =>
212 New_Reference_To (RTE (
213 RE_POK_Protected_Procedure), Loc)),
214 Right_Opnd =>
215 Make_Op_Eq (Loc,
216 Left_Opnd =>
217 Make_Identifier (Loc, Name_uC),
218 Right_Opnd =>
219 New_Reference_To (RTE (
220 RE_POK_Task_Procedure), Loc)))),
222 Then_Statements =>
223 New_List (
224 Make_Assignment_Statement (Loc,
225 Name => Make_Identifier (Loc, Name_uF),
226 Expression => New_Reference_To (Standard_True, Loc)),
228 Make_Return_Statement (Loc))));
229 end Build_Common_Dispatching_Select_Statements;
231 -------------
232 -- Build_F --
233 -------------
235 procedure Build_F
236 (Loc : Source_Ptr;
237 Params : List_Id)
239 begin
240 Append_To (Params,
241 Make_Parameter_Specification (Loc,
242 Defining_Identifier =>
243 Make_Defining_Identifier (Loc, Name_uF),
244 Parameter_Type =>
245 New_Reference_To (Standard_Boolean, Loc),
246 Out_Present => True));
247 end Build_F;
249 -------------
250 -- Build_P --
251 -------------
253 procedure Build_P
254 (Loc : Source_Ptr;
255 Params : List_Id)
257 begin
258 Append_To (Params,
259 Make_Parameter_Specification (Loc,
260 Defining_Identifier =>
261 Make_Defining_Identifier (Loc, Name_uP),
262 Parameter_Type =>
263 New_Reference_To (RTE (RE_Address), Loc)));
264 end Build_P;
266 -------------
267 -- Build_S --
268 -------------
270 procedure Build_S
271 (Loc : Source_Ptr;
272 Params : List_Id)
274 begin
275 Append_To (Params,
276 Make_Parameter_Specification (Loc,
277 Defining_Identifier =>
278 Make_Defining_Identifier (Loc, Name_uS),
279 Parameter_Type =>
280 New_Reference_To (Standard_Integer, Loc)));
281 end Build_S;
283 -------------
284 -- Build_T --
285 -------------
287 procedure Build_T
288 (Loc : Source_Ptr;
289 Typ : Entity_Id;
290 Params : List_Id)
292 begin
293 Append_To (Params,
294 Make_Parameter_Specification (Loc,
295 Defining_Identifier =>
296 Make_Defining_Identifier (Loc, Name_uT),
297 Parameter_Type =>
298 New_Reference_To (Typ, Loc),
299 In_Present => True,
300 Out_Present => True));
301 end Build_T;
302 end Select_Expansion_Utilities;
304 package SEU renames Select_Expansion_Utilities;
306 Ada_Actions : constant array (DT_Access_Action) of RE_Id :=
307 (CW_Membership => RE_CW_Membership,
308 IW_Membership => RE_IW_Membership,
309 DT_Entry_Size => RE_DT_Entry_Size,
310 DT_Prologue_Size => RE_DT_Prologue_Size,
311 Get_Access_Level => RE_Get_Access_Level,
312 Get_Entry_Index => RE_Get_Entry_Index,
313 Get_External_Tag => RE_Get_External_Tag,
314 Get_Predefined_Prim_Op_Address => RE_Get_Predefined_Prim_Op_Address,
315 Get_Prim_Op_Address => RE_Get_Prim_Op_Address,
316 Get_Prim_Op_Kind => RE_Get_Prim_Op_Kind,
317 Get_RC_Offset => RE_Get_RC_Offset,
318 Get_Remotely_Callable => RE_Get_Remotely_Callable,
319 Get_Tagged_Kind => RE_Get_Tagged_Kind,
320 Inherit_DT => RE_Inherit_DT,
321 Inherit_TSD => RE_Inherit_TSD,
322 Register_Interface_Tag => RE_Register_Interface_Tag,
323 Register_Tag => RE_Register_Tag,
324 Set_Access_Level => RE_Set_Access_Level,
325 Set_Entry_Index => RE_Set_Entry_Index,
326 Set_Expanded_Name => RE_Set_Expanded_Name,
327 Set_External_Tag => RE_Set_External_Tag,
328 Set_Interface_Table => RE_Set_Interface_Table,
329 Set_Offset_Index => RE_Set_Offset_Index,
330 Set_OSD => RE_Set_OSD,
331 Set_Predefined_Prim_Op_Address => RE_Set_Predefined_Prim_Op_Address,
332 Set_Prim_Op_Address => RE_Set_Prim_Op_Address,
333 Set_Prim_Op_Kind => RE_Set_Prim_Op_Kind,
334 Set_RC_Offset => RE_Set_RC_Offset,
335 Set_Remotely_Callable => RE_Set_Remotely_Callable,
336 Set_Signature => RE_Set_Signature,
337 Set_SSD => RE_Set_SSD,
338 Set_TSD => RE_Set_TSD,
339 Set_Tagged_Kind => RE_Set_Tagged_Kind,
340 TSD_Entry_Size => RE_TSD_Entry_Size,
341 TSD_Prologue_Size => RE_TSD_Prologue_Size);
343 Action_Is_Proc : constant array (DT_Access_Action) of Boolean :=
344 (CW_Membership => False,
345 IW_Membership => False,
346 DT_Entry_Size => False,
347 DT_Prologue_Size => False,
348 Get_Access_Level => False,
349 Get_Entry_Index => False,
350 Get_External_Tag => False,
351 Get_Predefined_Prim_Op_Address => False,
352 Get_Prim_Op_Address => False,
353 Get_Prim_Op_Kind => False,
354 Get_RC_Offset => False,
355 Get_Remotely_Callable => False,
356 Get_Tagged_Kind => False,
357 Inherit_DT => True,
358 Inherit_TSD => True,
359 Register_Interface_Tag => True,
360 Register_Tag => True,
361 Set_Access_Level => True,
362 Set_Entry_Index => True,
363 Set_Expanded_Name => True,
364 Set_External_Tag => True,
365 Set_Interface_Table => True,
366 Set_Offset_Index => True,
367 Set_OSD => True,
368 Set_Predefined_Prim_Op_Address => True,
369 Set_Prim_Op_Address => True,
370 Set_Prim_Op_Kind => True,
371 Set_RC_Offset => True,
372 Set_Remotely_Callable => True,
373 Set_Signature => True,
374 Set_SSD => True,
375 Set_TSD => True,
376 Set_Tagged_Kind => True,
377 TSD_Entry_Size => False,
378 TSD_Prologue_Size => False);
380 Action_Nb_Arg : constant array (DT_Access_Action) of Int :=
381 (CW_Membership => 2,
382 IW_Membership => 2,
383 DT_Entry_Size => 0,
384 DT_Prologue_Size => 0,
385 Get_Access_Level => 1,
386 Get_Entry_Index => 2,
387 Get_External_Tag => 1,
388 Get_Predefined_Prim_Op_Address => 2,
389 Get_Prim_Op_Address => 2,
390 Get_Prim_Op_Kind => 2,
391 Get_RC_Offset => 1,
392 Get_Remotely_Callable => 1,
393 Get_Tagged_Kind => 1,
394 Inherit_DT => 3,
395 Inherit_TSD => 2,
396 Register_Interface_Tag => 3,
397 Register_Tag => 1,
398 Set_Access_Level => 2,
399 Set_Entry_Index => 3,
400 Set_Expanded_Name => 2,
401 Set_External_Tag => 2,
402 Set_Interface_Table => 2,
403 Set_Offset_Index => 3,
404 Set_OSD => 2,
405 Set_Predefined_Prim_Op_Address => 3,
406 Set_Prim_Op_Address => 3,
407 Set_Prim_Op_Kind => 3,
408 Set_RC_Offset => 2,
409 Set_Remotely_Callable => 2,
410 Set_Signature => 2,
411 Set_SSD => 2,
412 Set_TSD => 2,
413 Set_Tagged_Kind => 2,
414 TSD_Entry_Size => 0,
415 TSD_Prologue_Size => 0);
417 procedure Collect_All_Interfaces (T : Entity_Id);
418 -- Ada 2005 (AI-251): Collect the whole list of interfaces that are
419 -- directly or indirectly implemented by T. Used to compute the size
420 -- of the table of interfaces.
422 function Default_Prim_Op_Position (E : Entity_Id) return Uint;
423 -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table
424 -- of the default primitive operations.
426 function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean;
427 -- Check if the type has a private view or if the public view appears
428 -- in the visible part of a package spec.
430 function Prim_Op_Kind
431 (Prim : Entity_Id;
432 Typ : Entity_Id) return Node_Id;
433 -- Ada 2005 (AI-345): Determine the primitive operation kind of Prim
434 -- according to its type Typ. Return a reference to an RE_Prim_Op_Kind
435 -- enumeration value.
437 function Tagged_Kind (T : Entity_Id) return Node_Id;
438 -- Ada 2005 (AI-345): Determine the tagged kind of T and return a reference
439 -- to an RE_Tagged_Kind enumeration value.
441 ----------------------------
442 -- Collect_All_Interfaces --
443 ----------------------------
445 procedure Collect_All_Interfaces (T : Entity_Id) is
447 procedure Add_Interface (Iface : Entity_Id);
448 -- Add the interface it if is not already in the list
450 procedure Collect (Typ : Entity_Id);
451 -- Subsidiary subprogram used to traverse the whole list
452 -- of directly and indirectly implemented interfaces
454 -------------------
455 -- Add_Interface --
456 -------------------
458 procedure Add_Interface (Iface : Entity_Id) is
459 Elmt : Elmt_Id;
461 begin
462 Elmt := First_Elmt (Abstract_Interfaces (T));
463 while Present (Elmt) and then Node (Elmt) /= Iface loop
464 Next_Elmt (Elmt);
465 end loop;
467 if No (Elmt) then
468 Append_Elmt (Iface, Abstract_Interfaces (T));
469 end if;
470 end Add_Interface;
472 -------------
473 -- Collect --
474 -------------
476 procedure Collect (Typ : Entity_Id) is
477 Ancestor : Entity_Id;
478 Id : Node_Id;
479 Iface : Entity_Id;
480 Nod : Node_Id;
482 begin
483 if Ekind (Typ) = E_Record_Type_With_Private then
484 Nod := Type_Definition (Parent (Full_View (Typ)));
485 else
486 Nod := Type_Definition (Parent (Typ));
487 end if;
489 pragma Assert (False
490 or else Nkind (Nod) = N_Derived_Type_Definition
491 or else Nkind (Nod) = N_Record_Definition);
493 -- Include the ancestor if we are generating the whole list
494 -- of interfaces. This is used to know the size of the table
495 -- that stores the tag of all the ancestor interfaces.
497 Ancestor := Etype (Typ);
499 if Ancestor /= Typ then
500 Collect (Ancestor);
501 end if;
503 if Is_Interface (Ancestor) then
504 Add_Interface (Ancestor);
505 end if;
507 -- Traverse the graph of ancestor interfaces
509 if Is_Non_Empty_List (Interface_List (Nod)) then
510 Id := First (Interface_List (Nod));
511 while Present (Id) loop
512 Iface := Etype (Id);
514 if Is_Interface (Iface) then
515 Add_Interface (Iface);
516 Collect (Iface);
517 end if;
519 Next (Id);
520 end loop;
521 end if;
522 end Collect;
524 -- Start of processing for Collect_All_Interfaces
526 begin
527 Collect (T);
528 end Collect_All_Interfaces;
530 ------------------------------
531 -- Default_Prim_Op_Position --
532 ------------------------------
534 function Default_Prim_Op_Position (E : Entity_Id) return Uint is
535 TSS_Name : TSS_Name_Type;
537 begin
538 Get_Name_String (Chars (E));
539 TSS_Name :=
540 TSS_Name_Type
541 (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
543 if Chars (E) = Name_uSize then
544 return Uint_1;
546 elsif Chars (E) = Name_uAlignment then
547 return Uint_2;
549 elsif TSS_Name = TSS_Stream_Read then
550 return Uint_3;
552 elsif TSS_Name = TSS_Stream_Write then
553 return Uint_4;
555 elsif TSS_Name = TSS_Stream_Input then
556 return Uint_5;
558 elsif TSS_Name = TSS_Stream_Output then
559 return Uint_6;
561 elsif Chars (E) = Name_Op_Eq then
562 return Uint_7;
564 elsif Chars (E) = Name_uAssign then
565 return Uint_8;
567 elsif TSS_Name = TSS_Deep_Adjust then
568 return Uint_9;
570 elsif TSS_Name = TSS_Deep_Finalize then
571 return Uint_10;
573 elsif Ada_Version >= Ada_05 then
574 if Chars (E) = Name_uDisp_Asynchronous_Select then
575 return Uint_11;
577 elsif Chars (E) = Name_uDisp_Conditional_Select then
578 return Uint_12;
580 elsif Chars (E) = Name_uDisp_Get_Prim_Op_Kind then
581 return Uint_13;
583 elsif Chars (E) = Name_uDisp_Get_Task_Id then
584 return Uint_14;
586 elsif Chars (E) = Name_uDisp_Timed_Select then
587 return Uint_15;
588 end if;
589 end if;
591 raise Program_Error;
592 end Default_Prim_Op_Position;
594 -----------------------------
595 -- Expand_Dispatching_Call --
596 -----------------------------
598 procedure Expand_Dispatching_Call (Call_Node : Node_Id) is
599 Loc : constant Source_Ptr := Sloc (Call_Node);
600 Call_Typ : constant Entity_Id := Etype (Call_Node);
602 Ctrl_Arg : constant Node_Id := Controlling_Argument (Call_Node);
603 Param_List : constant List_Id := Parameter_Associations (Call_Node);
604 Subp : Entity_Id := Entity (Name (Call_Node));
606 CW_Typ : Entity_Id;
607 New_Call : Node_Id;
608 New_Call_Name : Node_Id;
609 New_Params : List_Id := No_List;
610 Param : Node_Id;
611 Res_Typ : Entity_Id;
612 Subp_Ptr_Typ : Entity_Id;
613 Subp_Typ : Entity_Id;
614 Typ : Entity_Id;
615 Eq_Prim_Op : Entity_Id := Empty;
616 Controlling_Tag : Node_Id;
618 function New_Value (From : Node_Id) return Node_Id;
619 -- From is the original Expression. New_Value is equivalent to a call
620 -- to Duplicate_Subexpr with an explicit dereference when From is an
621 -- access parameter.
623 function Controlling_Type (Subp : Entity_Id) return Entity_Id;
624 -- Returns the tagged type for which Subp is a primitive subprogram
626 ---------------
627 -- New_Value --
628 ---------------
630 function New_Value (From : Node_Id) return Node_Id is
631 Res : constant Node_Id := Duplicate_Subexpr (From);
632 begin
633 if Is_Access_Type (Etype (From)) then
634 return Make_Explicit_Dereference (Sloc (From), Res);
635 else
636 return Res;
637 end if;
638 end New_Value;
640 ----------------------
641 -- Controlling_Type --
642 ----------------------
644 function Controlling_Type (Subp : Entity_Id) return Entity_Id is
645 begin
646 if Ekind (Subp) = E_Function
647 and then Has_Controlling_Result (Subp)
648 then
649 return Base_Type (Etype (Subp));
651 else
652 declare
653 Formal : Entity_Id;
655 begin
656 Formal := First_Formal (Subp);
657 while Present (Formal) loop
658 if Is_Controlling_Formal (Formal) then
659 if Is_Access_Type (Etype (Formal)) then
660 return Base_Type (Designated_Type (Etype (Formal)));
661 else
662 return Base_Type (Etype (Formal));
663 end if;
664 end if;
666 Next_Formal (Formal);
667 end loop;
668 end;
669 end if;
671 -- Controlling type not found (should never happen)
673 return Empty;
674 end Controlling_Type;
676 -- Start of processing for Expand_Dispatching_Call
678 begin
679 Check_Restriction (No_Dispatching_Calls, Call_Node);
681 -- If this is an inherited operation that was overridden, the body
682 -- that is being called is its alias.
684 if Present (Alias (Subp))
685 and then Is_Inherited_Operation (Subp)
686 and then No (DTC_Entity (Subp))
687 then
688 Subp := Alias (Subp);
689 end if;
691 -- Expand_Dispatching_Call is called directly from the semantics,
692 -- so we need a check to see whether expansion is active before
693 -- proceeding.
695 if not Expander_Active then
696 return;
697 end if;
699 -- Definition of the class-wide type and the tagged type
701 -- If the controlling argument is itself a tag rather than a tagged
702 -- object, then use the class-wide type associated with the subprogram's
703 -- controlling type. This case can occur when a call to an inherited
704 -- primitive has an actual that originated from a default parameter
705 -- given by a tag-indeterminate call and when there is no other
706 -- controlling argument providing the tag (AI-239 requires dispatching).
707 -- This capability of dispatching directly by tag is also needed by the
708 -- implementation of AI-260 (for the generic dispatching constructors).
710 if Etype (Ctrl_Arg) = RTE (RE_Tag)
711 or else (RTE_Available (RE_Interface_Tag)
712 and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag))
713 then
714 CW_Typ := Class_Wide_Type (Controlling_Type (Subp));
716 elsif Is_Access_Type (Etype (Ctrl_Arg)) then
717 CW_Typ := Designated_Type (Etype (Ctrl_Arg));
719 else
720 CW_Typ := Etype (Ctrl_Arg);
721 end if;
723 Typ := Root_Type (CW_Typ);
725 if Ekind (Typ) = E_Incomplete_Type then
726 Typ := Non_Limited_View (Typ);
727 end if;
729 if not Is_Limited_Type (Typ) then
730 Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
731 end if;
733 if Is_CPP_Class (Root_Type (Typ)) then
735 -- Create a new parameter list with the displaced 'this'
737 New_Params := New_List;
738 Param := First_Actual (Call_Node);
739 while Present (Param) loop
740 Append_To (New_Params, Relocate_Node (Param));
741 Next_Actual (Param);
742 end loop;
744 elsif Present (Param_List) then
746 -- Generate the Tag checks when appropriate
748 New_Params := New_List;
749 Param := First_Actual (Call_Node);
750 while Present (Param) loop
752 -- No tag check with itself
754 if Param = Ctrl_Arg then
755 Append_To (New_Params,
756 Duplicate_Subexpr_Move_Checks (Param));
758 -- No tag check for parameter whose type is neither tagged nor
759 -- access to tagged (for access parameters)
761 elsif No (Find_Controlling_Arg (Param)) then
762 Append_To (New_Params, Relocate_Node (Param));
764 -- No tag check for function dispatching on result if the
765 -- Tag given by the context is this one
767 elsif Find_Controlling_Arg (Param) = Ctrl_Arg then
768 Append_To (New_Params, Relocate_Node (Param));
770 -- "=" is the only dispatching operation allowed to get
771 -- operands with incompatible tags (it just returns false).
772 -- We use Duplicate_Subexpr_Move_Checks instead of calling
773 -- Relocate_Node because the value will be duplicated to
774 -- check the tags.
776 elsif Subp = Eq_Prim_Op then
777 Append_To (New_Params,
778 Duplicate_Subexpr_Move_Checks (Param));
780 -- No check in presence of suppress flags
782 elsif Tag_Checks_Suppressed (Etype (Param))
783 or else (Is_Access_Type (Etype (Param))
784 and then Tag_Checks_Suppressed
785 (Designated_Type (Etype (Param))))
786 then
787 Append_To (New_Params, Relocate_Node (Param));
789 -- Optimization: no tag checks if the parameters are identical
791 elsif Is_Entity_Name (Param)
792 and then Is_Entity_Name (Ctrl_Arg)
793 and then Entity (Param) = Entity (Ctrl_Arg)
794 then
795 Append_To (New_Params, Relocate_Node (Param));
797 -- Now we need to generate the Tag check
799 else
800 -- Generate code for tag equality check
801 -- Perhaps should have Checks.Apply_Tag_Equality_Check???
803 Insert_Action (Ctrl_Arg,
804 Make_Implicit_If_Statement (Call_Node,
805 Condition =>
806 Make_Op_Ne (Loc,
807 Left_Opnd =>
808 Make_Selected_Component (Loc,
809 Prefix => New_Value (Ctrl_Arg),
810 Selector_Name =>
811 New_Reference_To
812 (First_Tag_Component (Typ), Loc)),
814 Right_Opnd =>
815 Make_Selected_Component (Loc,
816 Prefix =>
817 Unchecked_Convert_To (Typ, New_Value (Param)),
818 Selector_Name =>
819 New_Reference_To
820 (First_Tag_Component (Typ), Loc))),
822 Then_Statements =>
823 New_List (New_Constraint_Error (Loc))));
825 Append_To (New_Params, Relocate_Node (Param));
826 end if;
828 Next_Actual (Param);
829 end loop;
830 end if;
832 -- Generate the appropriate subprogram pointer type
834 if Etype (Subp) = Typ then
835 Res_Typ := CW_Typ;
836 else
837 Res_Typ := Etype (Subp);
838 end if;
840 Subp_Typ := Create_Itype (E_Subprogram_Type, Call_Node);
841 Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node);
842 Set_Etype (Subp_Typ, Res_Typ);
843 Init_Size_Align (Subp_Ptr_Typ);
844 Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp));
846 -- Create a new list of parameters which is a copy of the old formal
847 -- list including the creation of a new set of matching entities.
849 declare
850 Old_Formal : Entity_Id := First_Formal (Subp);
851 New_Formal : Entity_Id;
852 Extra : Entity_Id;
854 begin
855 if Present (Old_Formal) then
856 New_Formal := New_Copy (Old_Formal);
857 Set_First_Entity (Subp_Typ, New_Formal);
858 Param := First_Actual (Call_Node);
860 loop
861 Set_Scope (New_Formal, Subp_Typ);
863 -- Change all the controlling argument types to be class-wide
864 -- to avoid a recursion in dispatching.
866 if Is_Controlling_Formal (New_Formal) then
867 Set_Etype (New_Formal, Etype (Param));
868 end if;
870 if Is_Itype (Etype (New_Formal)) then
871 Extra := New_Copy (Etype (New_Formal));
873 if Ekind (Extra) = E_Record_Subtype
874 or else Ekind (Extra) = E_Class_Wide_Subtype
875 then
876 Set_Cloned_Subtype (Extra, Etype (New_Formal));
877 end if;
879 Set_Etype (New_Formal, Extra);
880 Set_Scope (Etype (New_Formal), Subp_Typ);
881 end if;
883 Extra := New_Formal;
884 Next_Formal (Old_Formal);
885 exit when No (Old_Formal);
887 Set_Next_Entity (New_Formal, New_Copy (Old_Formal));
888 Next_Entity (New_Formal);
889 Next_Actual (Param);
890 end loop;
891 Set_Last_Entity (Subp_Typ, Extra);
893 -- Copy extra formals
895 New_Formal := First_Entity (Subp_Typ);
896 while Present (New_Formal) loop
897 if Present (Extra_Constrained (New_Formal)) then
898 Set_Extra_Formal (Extra,
899 New_Copy (Extra_Constrained (New_Formal)));
900 Extra := Extra_Formal (Extra);
901 Set_Extra_Constrained (New_Formal, Extra);
903 elsif Present (Extra_Accessibility (New_Formal)) then
904 Set_Extra_Formal (Extra,
905 New_Copy (Extra_Accessibility (New_Formal)));
906 Extra := Extra_Formal (Extra);
907 Set_Extra_Accessibility (New_Formal, Extra);
908 end if;
910 Next_Formal (New_Formal);
911 end loop;
912 end if;
913 end;
915 Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
916 Set_Directly_Designated_Type (Subp_Ptr_Typ, Subp_Typ);
918 -- If the controlling argument is a value of type Ada.Tag or an abstract
919 -- interface class-wide type then use it directly. Otherwise, the tag
920 -- must be extracted from the controlling object.
922 if Etype (Ctrl_Arg) = RTE (RE_Tag)
923 or else (RTE_Available (RE_Interface_Tag)
924 and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag))
925 then
926 Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
928 -- Ada 2005 (AI-251): Abstract interface class-wide type
930 elsif Is_Interface (Etype (Ctrl_Arg))
931 and then Is_Class_Wide_Type (Etype (Ctrl_Arg))
932 then
933 Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
935 else
936 Controlling_Tag :=
937 Make_Selected_Component (Loc,
938 Prefix => Duplicate_Subexpr_Move_Checks (Ctrl_Arg),
939 Selector_Name => New_Reference_To (DTC_Entity (Subp), Loc));
940 end if;
942 -- Generate:
943 -- Subp_Ptr_Typ!(Get_Prim_Op_Address (Ctrl._Tag, pos));
945 if Is_Predefined_Dispatching_Operation (Subp) then
946 New_Call_Name :=
947 Unchecked_Convert_To (Subp_Ptr_Typ,
948 Make_DT_Access_Action (Typ,
949 Action => Get_Predefined_Prim_Op_Address,
950 Args => New_List (
952 -- Vptr
954 Unchecked_Convert_To (RTE (RE_Tag),
955 Controlling_Tag),
957 -- Position
959 Make_Integer_Literal (Loc, DT_Position (Subp)))));
961 else
962 New_Call_Name :=
963 Unchecked_Convert_To (Subp_Ptr_Typ,
964 Make_DT_Access_Action (Typ,
965 Action => Get_Prim_Op_Address,
966 Args => New_List (
968 -- Vptr
970 Unchecked_Convert_To (RTE (RE_Tag),
971 Controlling_Tag),
973 -- Position
975 Make_Integer_Literal (Loc, DT_Position (Subp)))));
976 end if;
978 if Nkind (Call_Node) = N_Function_Call then
980 -- Ada 2005 (AI-251): A dispatching "=" with an abstract interface
981 -- just requires the comparison of the tags.
983 if Ekind (Etype (Ctrl_Arg)) = E_Class_Wide_Type
984 and then Is_Interface (Etype (Ctrl_Arg))
985 and then Subp = Eq_Prim_Op
986 then
987 Param := First_Actual (Call_Node);
989 New_Call :=
990 Make_Op_Eq (Loc,
991 Left_Opnd =>
992 Make_Selected_Component (Loc,
993 Prefix => New_Value (Param),
994 Selector_Name =>
995 New_Reference_To (First_Tag_Component (Typ), Loc)),
997 Right_Opnd =>
998 Make_Selected_Component (Loc,
999 Prefix =>
1000 Unchecked_Convert_To (Typ,
1001 New_Value (Next_Actual (Param))),
1002 Selector_Name =>
1003 New_Reference_To (First_Tag_Component (Typ), Loc)));
1005 else
1006 New_Call :=
1007 Make_Function_Call (Loc,
1008 Name => New_Call_Name,
1009 Parameter_Associations => New_Params);
1011 -- If this is a dispatching "=", we must first compare the tags so
1012 -- we generate: x.tag = y.tag and then x = y
1014 if Subp = Eq_Prim_Op then
1015 Param := First_Actual (Call_Node);
1016 New_Call :=
1017 Make_And_Then (Loc,
1018 Left_Opnd =>
1019 Make_Op_Eq (Loc,
1020 Left_Opnd =>
1021 Make_Selected_Component (Loc,
1022 Prefix => New_Value (Param),
1023 Selector_Name =>
1024 New_Reference_To (First_Tag_Component (Typ),
1025 Loc)),
1027 Right_Opnd =>
1028 Make_Selected_Component (Loc,
1029 Prefix =>
1030 Unchecked_Convert_To (Typ,
1031 New_Value (Next_Actual (Param))),
1032 Selector_Name =>
1033 New_Reference_To (First_Tag_Component (Typ),
1034 Loc))),
1035 Right_Opnd => New_Call);
1036 end if;
1037 end if;
1039 else
1040 New_Call :=
1041 Make_Procedure_Call_Statement (Loc,
1042 Name => New_Call_Name,
1043 Parameter_Associations => New_Params);
1044 end if;
1046 Rewrite (Call_Node, New_Call);
1047 Analyze_And_Resolve (Call_Node, Call_Typ);
1048 end Expand_Dispatching_Call;
1050 ---------------------------------
1051 -- Expand_Interface_Conversion --
1052 ---------------------------------
1054 procedure Expand_Interface_Conversion
1055 (N : Node_Id;
1056 Is_Static : Boolean := True)
1058 Loc : constant Source_Ptr := Sloc (N);
1059 Operand : constant Node_Id := Expression (N);
1060 Operand_Typ : Entity_Id := Etype (Operand);
1061 Iface_Typ : Entity_Id := Etype (N);
1062 Iface_Tag : Entity_Id;
1063 Fent : Entity_Id;
1064 Func : Node_Id;
1065 P : Node_Id;
1066 Null_Op_Nod : Node_Id;
1068 begin
1069 pragma Assert (Nkind (Operand) /= N_Attribute_Reference);
1071 -- Ada 2005 (AI-345): Handle task interfaces
1073 if Ekind (Operand_Typ) = E_Task_Type
1074 or else Ekind (Operand_Typ) = E_Protected_Type
1075 then
1076 Operand_Typ := Corresponding_Record_Type (Operand_Typ);
1077 end if;
1079 -- Handle access types to interfaces
1081 if Is_Access_Type (Iface_Typ) then
1082 Iface_Typ := Etype (Directly_Designated_Type (Iface_Typ));
1083 end if;
1085 -- Handle class-wide interface types. This conversion can appear
1086 -- explicitly in the source code. Example: I'Class (Obj)
1088 if Is_Class_Wide_Type (Iface_Typ) then
1089 Iface_Typ := Etype (Iface_Typ);
1090 end if;
1092 pragma Assert (not Is_Class_Wide_Type (Iface_Typ)
1093 and then Is_Interface (Iface_Typ));
1095 if not Is_Static then
1097 -- Give error if configurable run time and Displace not available
1099 if not RTE_Available (RE_Displace) then
1100 Error_Msg_CRT ("abstract interface types", N);
1101 return;
1102 end if;
1104 Rewrite (N,
1105 Make_Function_Call (Loc,
1106 Name => New_Reference_To (RTE (RE_Displace), Loc),
1107 Parameter_Associations => New_List (
1108 Make_Attribute_Reference (Loc,
1109 Prefix => Relocate_Node (Expression (N)),
1110 Attribute_Name => Name_Address),
1111 New_Occurrence_Of
1112 (Node (First_Elmt (Access_Disp_Table (Iface_Typ))),
1113 Loc))));
1115 Analyze (N);
1117 -- Change the type of the data returned by IW_Convert to
1118 -- indicate that this is a dispatching call.
1120 declare
1121 New_Itype : Entity_Id;
1123 begin
1124 New_Itype := Create_Itype (E_Anonymous_Access_Type, N);
1125 Set_Etype (New_Itype, New_Itype);
1126 Init_Size_Align (New_Itype);
1127 Set_Directly_Designated_Type (New_Itype,
1128 Class_Wide_Type (Iface_Typ));
1130 Rewrite (N, Make_Explicit_Dereference (Loc,
1131 Unchecked_Convert_To (New_Itype,
1132 Relocate_Node (N))));
1133 Analyze (N);
1134 end;
1136 return;
1137 end if;
1139 Iface_Tag := Find_Interface_Tag (Operand_Typ, Iface_Typ);
1140 pragma Assert (Iface_Tag /= Empty);
1142 -- Keep separate access types to interfaces because one internal
1143 -- function is used to handle the null value (see following comment)
1145 if not Is_Access_Type (Etype (N)) then
1146 Rewrite (N,
1147 Unchecked_Convert_To (Etype (N),
1148 Make_Selected_Component (Loc,
1149 Prefix => Relocate_Node (Expression (N)),
1150 Selector_Name =>
1151 New_Occurrence_Of (Iface_Tag, Loc))));
1153 else
1154 -- Build internal function to handle the case in which the
1155 -- actual is null. If the actual is null returns null because
1156 -- no displacement is required; otherwise performs a type
1157 -- conversion that will be expanded in the code that returns
1158 -- the value of the displaced actual. That is:
1160 -- function Func (O : Operand_Typ) return Iface_Typ is
1161 -- begin
1162 -- if O = null then
1163 -- return null;
1164 -- else
1165 -- return Iface_Typ!(O);
1166 -- end if;
1167 -- end Func;
1169 Fent :=
1170 Make_Defining_Identifier (Loc, New_Internal_Name ('F'));
1172 -- Decorate the "null" in the if-statement condition
1174 Null_Op_Nod := Make_Null (Loc);
1175 Set_Etype (Null_Op_Nod, Etype (Operand));
1176 Set_Analyzed (Null_Op_Nod);
1178 Func :=
1179 Make_Subprogram_Body (Loc,
1180 Specification =>
1181 Make_Function_Specification (Loc,
1182 Defining_Unit_Name => Fent,
1184 Parameter_Specifications => New_List (
1185 Make_Parameter_Specification (Loc,
1186 Defining_Identifier =>
1187 Make_Defining_Identifier (Loc, Name_uO),
1188 Parameter_Type =>
1189 New_Reference_To (Etype (Operand), Loc))),
1190 Result_Definition =>
1191 New_Reference_To (Etype (N), Loc)),
1193 Declarations => Empty_List,
1195 Handled_Statement_Sequence =>
1196 Make_Handled_Sequence_Of_Statements (Loc,
1197 Statements => New_List (
1198 Make_If_Statement (Loc,
1199 Condition =>
1200 Make_Op_Eq (Loc,
1201 Left_Opnd => Make_Identifier (Loc, Name_uO),
1202 Right_Opnd => Null_Op_Nod),
1203 Then_Statements => New_List (
1204 Make_Return_Statement (Loc,
1205 Make_Null (Loc))),
1206 Else_Statements => New_List (
1207 Make_Return_Statement (Loc,
1208 Unchecked_Convert_To (Etype (N),
1209 Make_Attribute_Reference (Loc,
1210 Prefix =>
1211 Make_Selected_Component (Loc,
1212 Prefix => Make_Identifier (Loc, Name_uO),
1213 Selector_Name =>
1214 New_Occurrence_Of (Iface_Tag, Loc)),
1215 Attribute_Name => Name_Address))))))));
1217 -- Insert the new declaration in the nearest enclosing scope
1218 -- that has declarations.
1220 P := N;
1221 while not Has_Declarations (Parent (P)) loop
1222 P := Parent (P);
1223 end loop;
1225 if Is_List_Member (P) then
1226 Insert_Before (P, Func);
1228 elsif Nkind (Parent (P)) = N_Package_Specification then
1229 Append_To (Visible_Declarations (Parent (P)), Func);
1231 else
1232 Append_To (Declarations (Parent (P)), Func);
1233 end if;
1235 Analyze (Func);
1237 Rewrite (N,
1238 Make_Function_Call (Loc,
1239 Name => New_Reference_To (Fent, Loc),
1240 Parameter_Associations => New_List (
1241 Relocate_Node (Expression (N)))));
1242 end if;
1244 Analyze (N);
1245 end Expand_Interface_Conversion;
1247 ------------------------------
1248 -- Expand_Interface_Actuals --
1249 ------------------------------
1251 procedure Expand_Interface_Actuals (Call_Node : Node_Id) is
1252 Loc : constant Source_Ptr := Sloc (Call_Node);
1253 Actual : Node_Id;
1254 Actual_Dup : Node_Id;
1255 Actual_Typ : Entity_Id;
1256 Anon : Entity_Id;
1257 Conversion : Node_Id;
1258 Formal : Entity_Id;
1259 Formal_Typ : Entity_Id;
1260 Subp : Entity_Id;
1261 Nam : Name_Id;
1262 Formal_DDT : Entity_Id;
1263 Actual_DDT : Entity_Id;
1265 begin
1266 -- This subprogram is called directly from the semantics, so we need a
1267 -- check to see whether expansion is active before proceeding.
1269 if not Expander_Active then
1270 return;
1271 end if;
1273 -- Call using access to subprogram with explicit dereference
1275 if Nkind (Name (Call_Node)) = N_Explicit_Dereference then
1276 Subp := Etype (Name (Call_Node));
1278 -- Normal case
1280 else
1281 Subp := Entity (Name (Call_Node));
1282 end if;
1284 Formal := First_Formal (Subp);
1285 Actual := First_Actual (Call_Node);
1286 while Present (Formal) loop
1288 -- Ada 2005 (AI-251): Conversion to interface to force "this"
1289 -- displacement.
1291 Formal_Typ := Etype (Etype (Formal));
1293 if Ekind (Formal_Typ) = E_Record_Type_With_Private then
1294 Formal_Typ := Full_View (Formal_Typ);
1295 end if;
1297 if Is_Access_Type (Formal_Typ) then
1298 Formal_DDT := Directly_Designated_Type (Formal_Typ);
1299 end if;
1301 Actual_Typ := Etype (Actual);
1303 if Is_Access_Type (Actual_Typ) then
1304 Actual_DDT := Directly_Designated_Type (Actual_Typ);
1305 end if;
1307 if Is_Interface (Formal_Typ) then
1309 -- No need to displace the pointer if the type of the actual
1310 -- is class-wide of the formal-type interface; in this case the
1311 -- displacement of the pointer was already done at the point of
1312 -- the call to the enclosing subprogram. This case corresponds
1313 -- with the call to P (Obj) in the following example:
1315 -- type I is interface;
1316 -- procedure P (X : I) is abstract;
1318 -- procedure General_Op (Obj : I'Class) is
1319 -- begin
1320 -- P (Obj);
1321 -- end General_Op;
1323 if Is_Class_Wide_Type (Actual_Typ)
1324 and then Etype (Actual_Typ) = Formal_Typ
1325 then
1326 null;
1328 -- No need to displace the pointer if the type of the actual is a
1329 -- derivation of the formal-type interface because in this case
1330 -- the interface primitives are located in the primary dispatch
1331 -- table.
1333 elsif Is_Ancestor (Formal_Typ, Actual_Typ) then
1334 null;
1336 else
1337 Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual));
1338 Rewrite (Actual, Conversion);
1339 Analyze_And_Resolve (Actual, Formal_Typ);
1340 end if;
1342 -- Anonymous access type
1344 elsif Is_Access_Type (Formal_Typ)
1345 and then Is_Interface (Etype (Formal_DDT))
1346 and then Interface_Present_In_Ancestor
1347 (Typ => Actual_DDT,
1348 Iface => Etype (Formal_DDT))
1349 then
1350 if Nkind (Actual) = N_Attribute_Reference
1351 and then
1352 (Attribute_Name (Actual) = Name_Access
1353 or else Attribute_Name (Actual) = Name_Unchecked_Access)
1354 then
1355 Nam := Attribute_Name (Actual);
1357 Conversion := Convert_To (Etype (Formal_DDT), Prefix (Actual));
1359 Rewrite (Actual, Conversion);
1360 Analyze_And_Resolve (Actual, Etype (Formal_DDT));
1362 Rewrite (Actual,
1363 Unchecked_Convert_To (Formal_Typ,
1364 Make_Attribute_Reference (Loc,
1365 Prefix => Relocate_Node (Actual),
1366 Attribute_Name => Nam)));
1368 Analyze_And_Resolve (Actual, Formal_Typ);
1370 -- No need to displace the pointer if the actual is a class-wide
1371 -- type of the formal-type interface because in this case the
1372 -- displacement of the pointer was already done at the point of
1373 -- the call to the enclosing subprogram (this case is similar
1374 -- to the example described above for the non access-type case)
1376 elsif Is_Class_Wide_Type (Actual_DDT)
1377 and then Etype (Actual_DDT) = Formal_DDT
1378 then
1379 null;
1381 -- No need to displace the pointer if the type of the actual is a
1382 -- derivation of the interface (because in this case the interface
1383 -- primitives are located in the primary dispatch table)
1385 elsif Is_Ancestor (Formal_DDT, Actual_DDT) then
1386 null;
1388 else
1389 Actual_Dup := Relocate_Node (Actual);
1391 if From_With_Type (Actual_Typ) then
1393 -- If the type of the actual parameter comes from a limited
1394 -- with-clause and the non-limited view is already available
1395 -- we replace the anonymous access type by a duplicate decla
1396 -- ration whose designated type is the non-limited view
1398 if Ekind (Actual_DDT) = E_Incomplete_Type
1399 and then Present (Non_Limited_View (Actual_DDT))
1400 then
1401 Anon := New_Copy (Actual_Typ);
1403 if Is_Itype (Anon) then
1404 Set_Scope (Anon, Current_Scope);
1405 end if;
1407 Set_Directly_Designated_Type (Anon,
1408 Non_Limited_View (Actual_DDT));
1409 Set_Etype (Actual_Dup, Anon);
1411 elsif Is_Class_Wide_Type (Actual_DDT)
1412 and then Ekind (Etype (Actual_DDT)) = E_Incomplete_Type
1413 and then Present (Non_Limited_View (Etype (Actual_DDT)))
1414 then
1415 Anon := New_Copy (Actual_Typ);
1417 if Is_Itype (Anon) then
1418 Set_Scope (Anon, Current_Scope);
1419 end if;
1421 Set_Directly_Designated_Type (Anon,
1422 New_Copy (Actual_DDT));
1423 Set_Class_Wide_Type (Directly_Designated_Type (Anon),
1424 New_Copy (Class_Wide_Type (Actual_DDT)));
1425 Set_Etype (Directly_Designated_Type (Anon),
1426 Non_Limited_View (Etype (Actual_DDT)));
1427 Set_Etype (
1428 Class_Wide_Type (Directly_Designated_Type (Anon)),
1429 Non_Limited_View (Etype (Actual_DDT)));
1430 Set_Etype (Actual_Dup, Anon);
1431 end if;
1432 end if;
1434 Conversion := Convert_To (Formal_Typ, Actual_Dup);
1435 Rewrite (Actual, Conversion);
1436 Analyze_And_Resolve (Actual, Formal_Typ);
1437 end if;
1438 end if;
1440 Next_Actual (Actual);
1441 Next_Formal (Formal);
1442 end loop;
1443 end Expand_Interface_Actuals;
1445 ----------------------------
1446 -- Expand_Interface_Thunk --
1447 ----------------------------
1449 function Expand_Interface_Thunk
1450 (N : Node_Id;
1451 Thunk_Alias : Entity_Id;
1452 Thunk_Id : Entity_Id) return Node_Id
1454 Loc : constant Source_Ptr := Sloc (N);
1455 Actuals : constant List_Id := New_List;
1456 Decl : constant List_Id := New_List;
1457 Formals : constant List_Id := New_List;
1458 Target : Entity_Id;
1459 New_Code : Node_Id;
1460 Formal : Node_Id;
1461 New_Formal : Node_Id;
1462 Decl_1 : Node_Id;
1463 Decl_2 : Node_Id;
1464 E : Entity_Id;
1466 begin
1467 -- Traverse the list of alias to find the final target
1469 Target := Thunk_Alias;
1470 while Present (Alias (Target)) loop
1471 Target := Alias (Target);
1472 end loop;
1474 -- Duplicate the formals
1476 Formal := First_Formal (Target);
1477 E := First_Formal (N);
1478 while Present (Formal) loop
1479 New_Formal := Copy_Separate_Tree (Parent (Formal));
1481 -- Propagate the parameter type to the copy. This is required to
1482 -- properly handle the case in which the subprogram covering the
1483 -- interface has been inherited:
1485 -- Example:
1486 -- type I is interface;
1487 -- procedure P (X : in I) is abstract;
1489 -- type T is tagged null record;
1490 -- procedure P (X : T);
1492 -- type DT is new T and I with ...
1494 Set_Parameter_Type (New_Formal, New_Reference_To (Etype (E), Loc));
1495 Append_To (Formals, New_Formal);
1497 Next_Formal (Formal);
1498 Next_Formal (E);
1499 end loop;
1501 -- Give message if configurable run-time and Offset_To_Top unavailable
1503 if not RTE_Available (RE_Offset_To_Top) then
1504 Error_Msg_CRT ("abstract interface types", N);
1505 return Empty;
1506 end if;
1508 if Ekind (First_Formal (Target)) = E_In_Parameter
1509 and then Ekind (Etype (First_Formal (Target)))
1510 = E_Anonymous_Access_Type
1511 then
1512 -- Generate:
1514 -- type T is access all <<type of the first formal>>
1515 -- S1 := Storage_Offset!(First_formal)
1516 -- - Offset_To_Top (First_Formal.Tag)
1518 -- ... and the first actual of the call is generated as T!(S1)
1520 Decl_2 :=
1521 Make_Full_Type_Declaration (Loc,
1522 Defining_Identifier =>
1523 Make_Defining_Identifier (Loc,
1524 New_Internal_Name ('T')),
1525 Type_Definition =>
1526 Make_Access_To_Object_Definition (Loc,
1527 All_Present => True,
1528 Null_Exclusion_Present => False,
1529 Constant_Present => False,
1530 Subtype_Indication =>
1531 New_Reference_To
1532 (Directly_Designated_Type
1533 (Etype (First_Formal (Target))), Loc)));
1535 Decl_1 :=
1536 Make_Object_Declaration (Loc,
1537 Defining_Identifier =>
1538 Make_Defining_Identifier (Loc,
1539 New_Internal_Name ('S')),
1540 Constant_Present => True,
1541 Object_Definition =>
1542 New_Reference_To (RTE (RE_Storage_Offset), Loc),
1543 Expression =>
1544 Make_Op_Subtract (Loc,
1545 Left_Opnd =>
1546 Unchecked_Convert_To
1547 (RTE (RE_Storage_Offset),
1548 New_Reference_To
1549 (Defining_Identifier (First (Formals)), Loc)),
1550 Right_Opnd =>
1551 Make_Function_Call (Loc,
1552 Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc),
1553 Parameter_Associations => New_List (
1554 Unchecked_Convert_To
1555 (RTE (RE_Address),
1556 New_Reference_To
1557 (Defining_Identifier (First (Formals)), Loc))))));
1559 Append_To (Decl, Decl_2);
1560 Append_To (Decl, Decl_1);
1562 -- Reference the new first actual
1564 Append_To (Actuals,
1565 Unchecked_Convert_To
1566 (Defining_Identifier (Decl_2),
1567 New_Reference_To (Defining_Identifier (Decl_1), Loc)));
1569 else
1570 -- Generate:
1572 -- S1 := Storage_Offset!(First_formal'Address)
1573 -- - Offset_To_Top (First_Formal.Tag)
1574 -- S2 := Tag_Ptr!(S3)
1576 Decl_1 :=
1577 Make_Object_Declaration (Loc,
1578 Defining_Identifier =>
1579 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
1580 Constant_Present => True,
1581 Object_Definition =>
1582 New_Reference_To (RTE (RE_Storage_Offset), Loc),
1583 Expression =>
1584 Make_Op_Subtract (Loc,
1585 Left_Opnd =>
1586 Unchecked_Convert_To
1587 (RTE (RE_Storage_Offset),
1588 Make_Attribute_Reference (Loc,
1589 Prefix =>
1590 New_Reference_To
1591 (Defining_Identifier (First (Formals)), Loc),
1592 Attribute_Name => Name_Address)),
1593 Right_Opnd =>
1594 Make_Function_Call (Loc,
1595 Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc),
1596 Parameter_Associations => New_List (
1597 Make_Attribute_Reference (Loc,
1598 Prefix => New_Reference_To
1599 (Defining_Identifier (First (Formals)),
1600 Loc),
1601 Attribute_Name => Name_Address)))));
1603 Decl_2 :=
1604 Make_Object_Declaration (Loc,
1605 Defining_Identifier =>
1606 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
1607 Constant_Present => True,
1608 Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc),
1609 Expression =>
1610 Unchecked_Convert_To
1611 (RTE (RE_Addr_Ptr),
1612 New_Reference_To (Defining_Identifier (Decl_1), Loc)));
1614 Append_To (Decl, Decl_1);
1615 Append_To (Decl, Decl_2);
1617 -- Reference the new first actual
1619 Append_To (Actuals,
1620 Unchecked_Convert_To
1621 (Etype (First_Entity (Target)),
1622 Make_Explicit_Dereference (Loc,
1623 New_Reference_To (Defining_Identifier (Decl_2), Loc))));
1624 end if;
1626 Formal := Next (First (Formals));
1627 while Present (Formal) loop
1628 Append_To (Actuals,
1629 New_Reference_To (Defining_Identifier (Formal), Loc));
1630 Next (Formal);
1631 end loop;
1633 if Ekind (Target) = E_Procedure then
1634 New_Code :=
1635 Make_Subprogram_Body (Loc,
1636 Specification =>
1637 Make_Procedure_Specification (Loc,
1638 Defining_Unit_Name => Thunk_Id,
1639 Parameter_Specifications => Formals),
1640 Declarations => Decl,
1641 Handled_Statement_Sequence =>
1642 Make_Handled_Sequence_Of_Statements (Loc,
1643 Statements => New_List (
1644 Make_Procedure_Call_Statement (Loc,
1645 Name => New_Occurrence_Of (Target, Loc),
1646 Parameter_Associations => Actuals))));
1648 else pragma Assert (Ekind (Target) = E_Function);
1650 New_Code :=
1651 Make_Subprogram_Body (Loc,
1652 Specification =>
1653 Make_Function_Specification (Loc,
1654 Defining_Unit_Name => Thunk_Id,
1655 Parameter_Specifications => Formals,
1656 Result_Definition =>
1657 New_Copy (Result_Definition (Parent (Target)))),
1658 Declarations => Decl,
1659 Handled_Statement_Sequence =>
1660 Make_Handled_Sequence_Of_Statements (Loc,
1661 Statements => New_List (
1662 Make_Return_Statement (Loc,
1663 Make_Function_Call (Loc,
1664 Name => New_Occurrence_Of (Target, Loc),
1665 Parameter_Associations => Actuals)))));
1666 end if;
1668 Analyze (New_Code);
1669 return New_Code;
1670 end Expand_Interface_Thunk;
1672 -------------------
1673 -- Fill_DT_Entry --
1674 -------------------
1676 function Fill_DT_Entry
1677 (Loc : Source_Ptr;
1678 Prim : Entity_Id) return Node_Id
1680 Typ : constant Entity_Id := Scope (DTC_Entity (Prim));
1681 DT_Ptr : constant Entity_Id :=
1682 Node (First_Elmt (Access_Disp_Table (Typ)));
1683 Pos : constant Uint := DT_Position (Prim);
1684 Tag : constant Entity_Id := First_Tag_Component (Typ);
1686 begin
1687 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
1689 if Is_Predefined_Dispatching_Operation (Prim) then
1690 return
1691 Make_DT_Access_Action (Typ,
1692 Action => Set_Predefined_Prim_Op_Address,
1693 Args => New_List (
1694 Unchecked_Convert_To (RTE (RE_Tag),
1695 New_Reference_To (DT_Ptr, Loc)), -- DTptr
1697 Make_Integer_Literal (Loc, Pos), -- Position
1699 Make_Attribute_Reference (Loc, -- Value
1700 Prefix => New_Reference_To (Prim, Loc),
1701 Attribute_Name => Name_Address)));
1702 else
1703 pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag));
1705 return
1706 Make_DT_Access_Action (Typ,
1707 Action => Set_Prim_Op_Address,
1708 Args => New_List (
1709 Unchecked_Convert_To (RTE (RE_Tag),
1710 New_Reference_To (DT_Ptr, Loc)), -- DTptr
1712 Make_Integer_Literal (Loc, Pos), -- Position
1714 Make_Attribute_Reference (Loc, -- Value
1715 Prefix => New_Reference_To (Prim, Loc),
1716 Attribute_Name => Name_Address)));
1717 end if;
1718 end Fill_DT_Entry;
1720 -----------------------------
1721 -- Fill_Secondary_DT_Entry --
1722 -----------------------------
1724 function Fill_Secondary_DT_Entry
1725 (Loc : Source_Ptr;
1726 Prim : Entity_Id;
1727 Thunk_Id : Entity_Id;
1728 Iface_DT_Ptr : Entity_Id) return Node_Id
1730 Typ : constant Entity_Id := Scope (DTC_Entity (Alias (Prim)));
1731 Iface_Prim : constant Entity_Id := Abstract_Interface_Alias (Prim);
1732 Pos : constant Uint := DT_Position (Iface_Prim);
1733 Tag : constant Entity_Id :=
1734 First_Tag_Component (Scope (DTC_Entity (Iface_Prim)));
1736 begin
1737 if Is_Predefined_Dispatching_Operation (Prim) then
1738 return
1739 Make_DT_Access_Action (Typ,
1740 Action => Set_Predefined_Prim_Op_Address,
1741 Args => New_List (
1742 Unchecked_Convert_To (RTE (RE_Tag),
1743 New_Reference_To (Iface_DT_Ptr, Loc)), -- DTptr
1745 Make_Integer_Literal (Loc, Pos), -- Position
1747 Make_Attribute_Reference (Loc, -- Value
1748 Prefix => New_Reference_To (Thunk_Id, Loc),
1749 Attribute_Name => Name_Address)));
1750 else
1751 pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag));
1753 return
1754 Make_DT_Access_Action (Typ,
1755 Action => Set_Prim_Op_Address,
1756 Args => New_List (
1757 Unchecked_Convert_To (RTE (RE_Tag),
1758 New_Reference_To (Iface_DT_Ptr, Loc)), -- DTptr
1760 Make_Integer_Literal (Loc, Pos), -- Position
1762 Make_Attribute_Reference (Loc, -- Value
1763 Prefix => New_Reference_To (Thunk_Id, Loc),
1764 Attribute_Name => Name_Address)));
1765 end if;
1766 end Fill_Secondary_DT_Entry;
1768 ---------------------------
1769 -- Get_Remotely_Callable --
1770 ---------------------------
1772 function Get_Remotely_Callable (Obj : Node_Id) return Node_Id is
1773 Loc : constant Source_Ptr := Sloc (Obj);
1774 begin
1775 return Make_DT_Access_Action
1776 (Typ => Etype (Obj),
1777 Action => Get_Remotely_Callable,
1778 Args => New_List (
1779 Make_Selected_Component (Loc,
1780 Prefix => Obj,
1781 Selector_Name => Make_Identifier (Loc, Name_uTag))));
1782 end Get_Remotely_Callable;
1784 ------------------------------------------
1785 -- Init_Predefined_Interface_Primitives --
1786 ------------------------------------------
1788 function Init_Predefined_Interface_Primitives
1789 (Typ : Entity_Id) return List_Id
1791 Loc : constant Source_Ptr := Sloc (Typ);
1792 DT_Ptr : constant Node_Id :=
1793 Node (First_Elmt (Access_Disp_Table (Typ)));
1794 Result : constant List_Id := New_List;
1795 AI : Elmt_Id;
1797 begin
1798 -- No need to inherit primitives if we have an abstract interface
1799 -- type or a concurrent type.
1801 if Is_Interface (Typ)
1802 or else Is_Concurrent_Record_Type (Typ)
1803 or else Restriction_Active (No_Dispatching_Calls)
1804 then
1805 return Result;
1806 end if;
1808 AI := Next_Elmt (First_Elmt (Access_Disp_Table (Typ)));
1809 while Present (AI) loop
1811 -- All the secondary tables inherit the dispatch table entries
1812 -- associated with predefined primitives.
1814 -- Generate:
1815 -- Inherit_DT (T'Tag, Iface'Tag, 0);
1817 Append_To (Result,
1818 Make_DT_Access_Action (Typ,
1819 Action => Inherit_DT,
1820 Args => New_List (
1821 Node1 => New_Reference_To (DT_Ptr, Loc),
1822 Node2 => Unchecked_Convert_To (RTE (RE_Tag),
1823 New_Reference_To (Node (AI), Loc)),
1824 Node3 => Make_Integer_Literal (Loc, Uint_0))));
1826 Next_Elmt (AI);
1827 end loop;
1829 return Result;
1830 end Init_Predefined_Interface_Primitives;
1832 ----------------------------------------
1833 -- Make_Disp_Asynchronous_Select_Body --
1834 ----------------------------------------
1836 function Make_Disp_Asynchronous_Select_Body
1837 (Typ : Entity_Id) return Node_Id
1839 Conc_Typ : Entity_Id := Empty;
1840 Decls : constant List_Id := New_List;
1841 DT_Ptr : Entity_Id;
1842 Loc : constant Source_Ptr := Sloc (Typ);
1843 Stmts : constant List_Id := New_List;
1845 begin
1846 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
1848 -- Null body is generated for interface types
1850 if Is_Interface (Typ) then
1851 return
1852 Make_Subprogram_Body (Loc,
1853 Specification =>
1854 Make_Disp_Asynchronous_Select_Spec (Typ),
1855 Declarations =>
1856 New_List,
1857 Handled_Statement_Sequence =>
1858 Make_Handled_Sequence_Of_Statements (Loc,
1859 New_List (Make_Null_Statement (Loc))));
1860 end if;
1862 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
1864 if Is_Concurrent_Record_Type (Typ) then
1865 Conc_Typ := Corresponding_Concurrent_Type (Typ);
1867 -- Generate:
1868 -- I : Integer := Get_Entry_Index (tag! (<type>VP), S);
1870 -- where I will be used to capture the entry index of the primitive
1871 -- wrapper at position S.
1873 Append_To (Decls,
1874 Make_Object_Declaration (Loc,
1875 Defining_Identifier =>
1876 Make_Defining_Identifier (Loc, Name_uI),
1877 Object_Definition =>
1878 New_Reference_To (Standard_Integer, Loc),
1879 Expression =>
1880 Make_DT_Access_Action (Typ,
1881 Action =>
1882 Get_Entry_Index,
1883 Args =>
1884 New_List (
1885 Unchecked_Convert_To (RTE (RE_Tag),
1886 New_Reference_To (DT_Ptr, Loc)),
1887 Make_Identifier (Loc, Name_uS)))));
1889 if Ekind (Conc_Typ) = E_Protected_Type then
1891 -- Generate:
1892 -- Protected_Entry_Call (
1893 -- T._object'access,
1894 -- protected_entry_index! (I),
1895 -- P,
1896 -- Asynchronous_Call,
1897 -- B);
1899 -- where T is the protected object, I is the entry index, P are
1900 -- the wrapped parameters and B is the name of the communication
1901 -- block.
1903 Append_To (Stmts,
1904 Make_Procedure_Call_Statement (Loc,
1905 Name =>
1906 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
1907 Parameter_Associations =>
1908 New_List (
1910 Make_Attribute_Reference (Loc, -- T._object'access
1911 Attribute_Name =>
1912 Name_Unchecked_Access,
1913 Prefix =>
1914 Make_Selected_Component (Loc,
1915 Prefix =>
1916 Make_Identifier (Loc, Name_uT),
1917 Selector_Name =>
1918 Make_Identifier (Loc, Name_uObject))),
1920 Make_Unchecked_Type_Conversion (Loc, -- entry index
1921 Subtype_Mark =>
1922 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc),
1923 Expression =>
1924 Make_Identifier (Loc, Name_uI)),
1926 Make_Identifier (Loc, Name_uP), -- parameter block
1927 New_Reference_To ( -- Asynchronous_Call
1928 RTE (RE_Asynchronous_Call), Loc),
1929 Make_Identifier (Loc, Name_uB)))); -- comm block
1930 else
1931 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
1933 -- Generate:
1934 -- Protected_Entry_Call (
1935 -- T._task_id,
1936 -- task_entry_index! (I),
1937 -- P,
1938 -- Conditional_Call,
1939 -- F);
1941 -- where T is the task object, I is the entry index, P are the
1942 -- wrapped parameters and F is the status flag.
1944 Append_To (Stmts,
1945 Make_Procedure_Call_Statement (Loc,
1946 Name =>
1947 New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
1948 Parameter_Associations =>
1949 New_List (
1951 Make_Selected_Component (Loc, -- T._task_id
1952 Prefix =>
1953 Make_Identifier (Loc, Name_uT),
1954 Selector_Name =>
1955 Make_Identifier (Loc, Name_uTask_Id)),
1957 Make_Unchecked_Type_Conversion (Loc, -- entry index
1958 Subtype_Mark =>
1959 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
1960 Expression =>
1961 Make_Identifier (Loc, Name_uI)),
1963 Make_Identifier (Loc, Name_uP), -- parameter block
1964 New_Reference_To ( -- Asynchronous_Call
1965 RTE (RE_Asynchronous_Call), Loc),
1966 Make_Identifier (Loc, Name_uF)))); -- status flag
1967 end if;
1968 end if;
1970 return
1971 Make_Subprogram_Body (Loc,
1972 Specification =>
1973 Make_Disp_Asynchronous_Select_Spec (Typ),
1974 Declarations =>
1975 Decls,
1976 Handled_Statement_Sequence =>
1977 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
1978 end Make_Disp_Asynchronous_Select_Body;
1980 ----------------------------------------
1981 -- Make_Disp_Asynchronous_Select_Spec --
1982 ----------------------------------------
1984 function Make_Disp_Asynchronous_Select_Spec
1985 (Typ : Entity_Id) return Node_Id
1987 Loc : constant Source_Ptr := Sloc (Typ);
1988 Def_Id : constant Node_Id :=
1989 Make_Defining_Identifier (Loc,
1990 Name_uDisp_Asynchronous_Select);
1991 Params : constant List_Id := New_List;
1993 begin
1994 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
1996 -- "T" - Object parameter
1997 -- "S" - Primitive operation slot
1998 -- "P" - Wrapped parameters
1999 -- "B" - Communication block
2000 -- "F" - Status flag
2002 SEU.Build_T (Loc, Typ, Params);
2003 SEU.Build_S (Loc, Params);
2004 SEU.Build_P (Loc, Params);
2005 SEU.Build_B (Loc, Params);
2006 SEU.Build_F (Loc, Params);
2008 Set_Is_Internal (Def_Id);
2010 return
2011 Make_Procedure_Specification (Loc,
2012 Defining_Unit_Name => Def_Id,
2013 Parameter_Specifications => Params);
2014 end Make_Disp_Asynchronous_Select_Spec;
2016 ---------------------------------------
2017 -- Make_Disp_Conditional_Select_Body --
2018 ---------------------------------------
2020 function Make_Disp_Conditional_Select_Body
2021 (Typ : Entity_Id) return Node_Id
2023 Loc : constant Source_Ptr := Sloc (Typ);
2024 Blk_Nam : Entity_Id;
2025 Conc_Typ : Entity_Id := Empty;
2026 Decls : constant List_Id := New_List;
2027 DT_Ptr : Entity_Id;
2028 Stmts : constant List_Id := New_List;
2030 begin
2031 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2033 -- Null body is generated for interface types
2035 if Is_Interface (Typ) then
2036 return
2037 Make_Subprogram_Body (Loc,
2038 Specification =>
2039 Make_Disp_Conditional_Select_Spec (Typ),
2040 Declarations =>
2041 No_List,
2042 Handled_Statement_Sequence =>
2043 Make_Handled_Sequence_Of_Statements (Loc,
2044 New_List (Make_Null_Statement (Loc))));
2045 end if;
2047 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
2049 if Is_Concurrent_Record_Type (Typ) then
2050 Conc_Typ := Corresponding_Concurrent_Type (Typ);
2052 -- Generate:
2053 -- I : Integer;
2055 -- where I will be used to capture the entry index of the primitive
2056 -- wrapper at position S.
2058 Append_To (Decls,
2059 Make_Object_Declaration (Loc,
2060 Defining_Identifier =>
2061 Make_Defining_Identifier (Loc, Name_uI),
2062 Object_Definition =>
2063 New_Reference_To (Standard_Integer, Loc)));
2065 -- Generate:
2066 -- C := Get_Prim_Op_Kind (tag! (<type>VP), S);
2068 -- if C = POK_Procedure
2069 -- or else C = POK_Protected_Procedure
2070 -- or else C = POK_Task_Procedure;
2071 -- then
2072 -- F := True;
2073 -- return;
2074 -- end if;
2076 SEU.Build_Common_Dispatching_Select_Statements
2077 (Loc, Typ, DT_Ptr, Stmts);
2079 -- Generate:
2080 -- Bnn : Communication_Block;
2082 -- where Bnn is the name of the communication block used in
2083 -- the call to Protected_Entry_Call.
2085 Blk_Nam := Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
2087 Append_To (Decls,
2088 Make_Object_Declaration (Loc,
2089 Defining_Identifier =>
2090 Blk_Nam,
2091 Object_Definition =>
2092 New_Reference_To (RTE (RE_Communication_Block), Loc)));
2094 -- Generate:
2095 -- I := Get_Entry_Index (tag! (<type>VP), S);
2097 -- I is the entry index and S is the dispatch table slot
2099 Append_To (Stmts,
2100 Make_Assignment_Statement (Loc,
2101 Name =>
2102 Make_Identifier (Loc, Name_uI),
2103 Expression =>
2104 Make_DT_Access_Action (Typ,
2105 Action =>
2106 Get_Entry_Index,
2107 Args =>
2108 New_List (
2109 Unchecked_Convert_To (RTE (RE_Tag),
2110 New_Reference_To (DT_Ptr, Loc)),
2111 Make_Identifier (Loc, Name_uS)))));
2113 if Ekind (Conc_Typ) = E_Protected_Type then
2115 -- Generate:
2116 -- Protected_Entry_Call (
2117 -- T._object'access,
2118 -- protected_entry_index! (I),
2119 -- P,
2120 -- Conditional_Call,
2121 -- Bnn);
2123 -- where T is the protected object, I is the entry index, P are
2124 -- the wrapped parameters and Bnn is the name of the communication
2125 -- block.
2127 Append_To (Stmts,
2128 Make_Procedure_Call_Statement (Loc,
2129 Name =>
2130 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
2131 Parameter_Associations =>
2132 New_List (
2134 Make_Attribute_Reference (Loc, -- T._object'access
2135 Attribute_Name =>
2136 Name_Unchecked_Access,
2137 Prefix =>
2138 Make_Selected_Component (Loc,
2139 Prefix =>
2140 Make_Identifier (Loc, Name_uT),
2141 Selector_Name =>
2142 Make_Identifier (Loc, Name_uObject))),
2144 Make_Unchecked_Type_Conversion (Loc, -- entry index
2145 Subtype_Mark =>
2146 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc),
2147 Expression =>
2148 Make_Identifier (Loc, Name_uI)),
2150 Make_Identifier (Loc, Name_uP), -- parameter block
2151 New_Reference_To ( -- Conditional_Call
2152 RTE (RE_Conditional_Call), Loc),
2153 New_Reference_To ( -- Bnn
2154 Blk_Nam, Loc))));
2156 -- Generate:
2157 -- F := not Cancelled (Bnn);
2159 -- where F is the success flag. The status of Cancelled is negated
2160 -- in order to match the behaviour of the version for task types.
2162 Append_To (Stmts,
2163 Make_Assignment_Statement (Loc,
2164 Name =>
2165 Make_Identifier (Loc, Name_uF),
2166 Expression =>
2167 Make_Op_Not (Loc,
2168 Right_Opnd =>
2169 Make_Function_Call (Loc,
2170 Name =>
2171 New_Reference_To (RTE (RE_Cancelled), Loc),
2172 Parameter_Associations =>
2173 New_List (
2174 New_Reference_To (Blk_Nam, Loc))))));
2175 else
2176 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
2178 -- Generate:
2179 -- Protected_Entry_Call (
2180 -- T._task_id,
2181 -- task_entry_index! (I),
2182 -- P,
2183 -- Conditional_Call,
2184 -- F);
2186 -- where T is the task object, I is the entry index, P are the
2187 -- wrapped parameters and F is the status flag.
2189 Append_To (Stmts,
2190 Make_Procedure_Call_Statement (Loc,
2191 Name =>
2192 New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
2193 Parameter_Associations =>
2194 New_List (
2196 Make_Selected_Component (Loc, -- T._task_id
2197 Prefix =>
2198 Make_Identifier (Loc, Name_uT),
2199 Selector_Name =>
2200 Make_Identifier (Loc, Name_uTask_Id)),
2202 Make_Unchecked_Type_Conversion (Loc, -- entry index
2203 Subtype_Mark =>
2204 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2205 Expression =>
2206 Make_Identifier (Loc, Name_uI)),
2208 Make_Identifier (Loc, Name_uP), -- parameter block
2209 New_Reference_To ( -- Conditional_Call
2210 RTE (RE_Conditional_Call), Loc),
2211 Make_Identifier (Loc, Name_uF)))); -- status flag
2212 end if;
2213 end if;
2215 return
2216 Make_Subprogram_Body (Loc,
2217 Specification =>
2218 Make_Disp_Conditional_Select_Spec (Typ),
2219 Declarations =>
2220 Decls,
2221 Handled_Statement_Sequence =>
2222 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
2223 end Make_Disp_Conditional_Select_Body;
2225 ---------------------------------------
2226 -- Make_Disp_Conditional_Select_Spec --
2227 ---------------------------------------
2229 function Make_Disp_Conditional_Select_Spec
2230 (Typ : Entity_Id) return Node_Id
2232 Loc : constant Source_Ptr := Sloc (Typ);
2233 Def_Id : constant Node_Id :=
2234 Make_Defining_Identifier (Loc,
2235 Name_uDisp_Conditional_Select);
2236 Params : constant List_Id := New_List;
2238 begin
2239 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2241 -- "T" - Object parameter
2242 -- "S" - Primitive operation slot
2243 -- "P" - Wrapped parameters
2244 -- "C" - Call kind
2245 -- "F" - Status flag
2247 SEU.Build_T (Loc, Typ, Params);
2248 SEU.Build_S (Loc, Params);
2249 SEU.Build_P (Loc, Params);
2250 SEU.Build_C (Loc, Params);
2251 SEU.Build_F (Loc, Params);
2253 Set_Is_Internal (Def_Id);
2255 return
2256 Make_Procedure_Specification (Loc,
2257 Defining_Unit_Name => Def_Id,
2258 Parameter_Specifications => Params);
2259 end Make_Disp_Conditional_Select_Spec;
2261 -------------------------------------
2262 -- Make_Disp_Get_Prim_Op_Kind_Body --
2263 -------------------------------------
2265 function Make_Disp_Get_Prim_Op_Kind_Body
2266 (Typ : Entity_Id) return Node_Id
2268 Loc : constant Source_Ptr := Sloc (Typ);
2269 DT_Ptr : Entity_Id;
2271 begin
2272 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2274 if Is_Interface (Typ) then
2275 return
2276 Make_Subprogram_Body (Loc,
2277 Specification =>
2278 Make_Disp_Get_Prim_Op_Kind_Spec (Typ),
2279 Declarations =>
2280 New_List,
2281 Handled_Statement_Sequence =>
2282 Make_Handled_Sequence_Of_Statements (Loc,
2283 New_List (Make_Null_Statement (Loc))));
2284 end if;
2286 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
2288 -- Generate:
2289 -- C := get_prim_op_kind (tag! (<type>VP), S);
2291 -- where C is the out parameter capturing the call kind and S is the
2292 -- dispatch table slot number.
2294 return
2295 Make_Subprogram_Body (Loc,
2296 Specification =>
2297 Make_Disp_Get_Prim_Op_Kind_Spec (Typ),
2298 Declarations =>
2299 New_List,
2300 Handled_Statement_Sequence =>
2301 Make_Handled_Sequence_Of_Statements (Loc,
2302 New_List (
2303 Make_Assignment_Statement (Loc,
2304 Name =>
2305 Make_Identifier (Loc, Name_uC),
2306 Expression =>
2307 Make_DT_Access_Action (Typ,
2308 Action =>
2309 Get_Prim_Op_Kind,
2310 Args =>
2311 New_List (
2312 Unchecked_Convert_To (RTE (RE_Tag),
2313 New_Reference_To (DT_Ptr, Loc)),
2314 Make_Identifier (Loc, Name_uS)))))));
2315 end Make_Disp_Get_Prim_Op_Kind_Body;
2317 -------------------------------------
2318 -- Make_Disp_Get_Prim_Op_Kind_Spec --
2319 -------------------------------------
2321 function Make_Disp_Get_Prim_Op_Kind_Spec
2322 (Typ : Entity_Id) return Node_Id
2324 Loc : constant Source_Ptr := Sloc (Typ);
2325 Def_Id : constant Node_Id :=
2326 Make_Defining_Identifier (Loc,
2327 Name_uDisp_Get_Prim_Op_Kind);
2328 Params : constant List_Id := New_List;
2330 begin
2331 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2333 -- "T" - Object parameter
2334 -- "S" - Primitive operation slot
2335 -- "C" - Call kind
2337 SEU.Build_T (Loc, Typ, Params);
2338 SEU.Build_S (Loc, Params);
2339 SEU.Build_C (Loc, Params);
2341 Set_Is_Internal (Def_Id);
2343 return
2344 Make_Procedure_Specification (Loc,
2345 Defining_Unit_Name => Def_Id,
2346 Parameter_Specifications => Params);
2347 end Make_Disp_Get_Prim_Op_Kind_Spec;
2349 --------------------------------
2350 -- Make_Disp_Get_Task_Id_Body --
2351 --------------------------------
2353 function Make_Disp_Get_Task_Id_Body
2354 (Typ : Entity_Id) return Node_Id
2356 Loc : constant Source_Ptr := Sloc (Typ);
2357 Ret : Node_Id;
2359 begin
2360 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2362 if Is_Concurrent_Record_Type (Typ)
2363 and then Ekind (Corresponding_Concurrent_Type (Typ)) = E_Task_Type
2364 then
2365 Ret :=
2366 Make_Return_Statement (Loc,
2367 Expression =>
2368 Make_Selected_Component (Loc,
2369 Prefix =>
2370 Make_Identifier (Loc, Name_uT),
2371 Selector_Name =>
2372 Make_Identifier (Loc, Name_uTask_Id)));
2374 -- A null body is constructed for non-task types
2376 else
2377 Ret :=
2378 Make_Return_Statement (Loc,
2379 Expression =>
2380 New_Reference_To (RTE (RO_ST_Null_Task), Loc));
2381 end if;
2383 return
2384 Make_Subprogram_Body (Loc,
2385 Specification =>
2386 Make_Disp_Get_Task_Id_Spec (Typ),
2387 Declarations =>
2388 New_List,
2389 Handled_Statement_Sequence =>
2390 Make_Handled_Sequence_Of_Statements (Loc,
2391 New_List (Ret)));
2392 end Make_Disp_Get_Task_Id_Body;
2394 --------------------------------
2395 -- Make_Disp_Get_Task_Id_Spec --
2396 --------------------------------
2398 function Make_Disp_Get_Task_Id_Spec
2399 (Typ : Entity_Id) return Node_Id
2401 Loc : constant Source_Ptr := Sloc (Typ);
2402 Def_Id : constant Node_Id :=
2403 Make_Defining_Identifier (Loc,
2404 Name_uDisp_Get_Task_Id);
2406 begin
2407 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2409 Set_Is_Internal (Def_Id);
2411 return
2412 Make_Function_Specification (Loc,
2413 Defining_Unit_Name => Def_Id,
2414 Parameter_Specifications => New_List (
2415 Make_Parameter_Specification (Loc,
2416 Defining_Identifier =>
2417 Make_Defining_Identifier (Loc, Name_uT),
2418 Parameter_Type =>
2419 New_Reference_To (Typ, Loc))),
2420 Result_Definition =>
2421 New_Reference_To (RTE (RO_ST_Task_Id), Loc));
2422 end Make_Disp_Get_Task_Id_Spec;
2424 ---------------------------------
2425 -- Make_Disp_Timed_Select_Body --
2426 ---------------------------------
2428 function Make_Disp_Timed_Select_Body
2429 (Typ : Entity_Id) return Node_Id
2431 Loc : constant Source_Ptr := Sloc (Typ);
2432 Conc_Typ : Entity_Id := Empty;
2433 Decls : constant List_Id := New_List;
2434 DT_Ptr : Entity_Id;
2435 Stmts : constant List_Id := New_List;
2437 begin
2438 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2440 -- Null body is generated for interface types
2442 if Is_Interface (Typ) then
2443 return
2444 Make_Subprogram_Body (Loc,
2445 Specification =>
2446 Make_Disp_Timed_Select_Spec (Typ),
2447 Declarations =>
2448 New_List,
2449 Handled_Statement_Sequence =>
2450 Make_Handled_Sequence_Of_Statements (Loc,
2451 New_List (Make_Null_Statement (Loc))));
2452 end if;
2454 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
2456 if Is_Concurrent_Record_Type (Typ) then
2457 Conc_Typ := Corresponding_Concurrent_Type (Typ);
2459 -- Generate:
2460 -- I : Integer;
2462 -- where I will be used to capture the entry index of the primitive
2463 -- wrapper at position S.
2465 Append_To (Decls,
2466 Make_Object_Declaration (Loc,
2467 Defining_Identifier =>
2468 Make_Defining_Identifier (Loc, Name_uI),
2469 Object_Definition =>
2470 New_Reference_To (Standard_Integer, Loc)));
2472 -- Generate:
2473 -- C := Get_Prim_Op_Kind (tag! (<type>VP), S);
2475 -- if C = POK_Procedure
2476 -- or else C = POK_Protected_Procedure
2477 -- or else C = POK_Task_Procedure;
2478 -- then
2479 -- F := True;
2480 -- return;
2481 -- end if;
2483 SEU.Build_Common_Dispatching_Select_Statements
2484 (Loc, Typ, DT_Ptr, Stmts);
2486 -- Generate:
2487 -- I := Get_Entry_Index (tag! (<type>VP), S);
2489 -- I is the entry index and S is the dispatch table slot
2491 Append_To (Stmts,
2492 Make_Assignment_Statement (Loc,
2493 Name =>
2494 Make_Identifier (Loc, Name_uI),
2495 Expression =>
2496 Make_DT_Access_Action (Typ,
2497 Action =>
2498 Get_Entry_Index,
2499 Args =>
2500 New_List (
2501 Unchecked_Convert_To (RTE (RE_Tag),
2502 New_Reference_To (DT_Ptr, Loc)),
2503 Make_Identifier (Loc, Name_uS)))));
2505 if Ekind (Conc_Typ) = E_Protected_Type then
2507 -- Generate:
2508 -- Timed_Protected_Entry_Call (
2509 -- T._object'access,
2510 -- protected_entry_index! (I),
2511 -- P,
2512 -- D,
2513 -- M,
2514 -- F);
2516 -- where T is the protected object, I is the entry index, P are
2517 -- the wrapped parameters, D is the delay amount, M is the delay
2518 -- mode and F is the status flag.
2520 Append_To (Stmts,
2521 Make_Procedure_Call_Statement (Loc,
2522 Name =>
2523 New_Reference_To (RTE (RE_Timed_Protected_Entry_Call), Loc),
2524 Parameter_Associations =>
2525 New_List (
2527 Make_Attribute_Reference (Loc, -- T._object'access
2528 Attribute_Name =>
2529 Name_Unchecked_Access,
2530 Prefix =>
2531 Make_Selected_Component (Loc,
2532 Prefix =>
2533 Make_Identifier (Loc, Name_uT),
2534 Selector_Name =>
2535 Make_Identifier (Loc, Name_uObject))),
2537 Make_Unchecked_Type_Conversion (Loc, -- entry index
2538 Subtype_Mark =>
2539 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc),
2540 Expression =>
2541 Make_Identifier (Loc, Name_uI)),
2543 Make_Identifier (Loc, Name_uP), -- parameter block
2544 Make_Identifier (Loc, Name_uD), -- delay
2545 Make_Identifier (Loc, Name_uM), -- delay mode
2546 Make_Identifier (Loc, Name_uF)))); -- status flag
2548 else
2549 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
2551 -- Generate:
2552 -- Timed_Task_Entry_Call (
2553 -- T._task_id,
2554 -- task_entry_index! (I),
2555 -- P,
2556 -- D,
2557 -- M,
2558 -- F);
2560 -- where T is the task object, I is the entry index, P are the
2561 -- wrapped parameters, D is the delay amount, M is the delay
2562 -- mode and F is the status flag.
2564 Append_To (Stmts,
2565 Make_Procedure_Call_Statement (Loc,
2566 Name =>
2567 New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc),
2568 Parameter_Associations =>
2569 New_List (
2571 Make_Selected_Component (Loc, -- T._task_id
2572 Prefix =>
2573 Make_Identifier (Loc, Name_uT),
2574 Selector_Name =>
2575 Make_Identifier (Loc, Name_uTask_Id)),
2577 Make_Unchecked_Type_Conversion (Loc, -- entry index
2578 Subtype_Mark =>
2579 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2580 Expression =>
2581 Make_Identifier (Loc, Name_uI)),
2583 Make_Identifier (Loc, Name_uP), -- parameter block
2584 Make_Identifier (Loc, Name_uD), -- delay
2585 Make_Identifier (Loc, Name_uM), -- delay mode
2586 Make_Identifier (Loc, Name_uF)))); -- status flag
2587 end if;
2588 end if;
2590 return
2591 Make_Subprogram_Body (Loc,
2592 Specification =>
2593 Make_Disp_Timed_Select_Spec (Typ),
2594 Declarations =>
2595 Decls,
2596 Handled_Statement_Sequence =>
2597 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
2598 end Make_Disp_Timed_Select_Body;
2600 ---------------------------------
2601 -- Make_Disp_Timed_Select_Spec --
2602 ---------------------------------
2604 function Make_Disp_Timed_Select_Spec
2605 (Typ : Entity_Id) return Node_Id
2607 Loc : constant Source_Ptr := Sloc (Typ);
2608 Def_Id : constant Node_Id :=
2609 Make_Defining_Identifier (Loc,
2610 Name_uDisp_Timed_Select);
2611 Params : constant List_Id := New_List;
2613 begin
2614 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
2616 -- "T" - Object parameter
2617 -- "S" - Primitive operation slot
2618 -- "P" - Wrapped parameters
2619 -- "D" - Delay
2620 -- "M" - Delay Mode
2621 -- "C" - Call kind
2622 -- "F" - Status flag
2624 SEU.Build_T (Loc, Typ, Params);
2625 SEU.Build_S (Loc, Params);
2626 SEU.Build_P (Loc, Params);
2628 Append_To (Params,
2629 Make_Parameter_Specification (Loc,
2630 Defining_Identifier =>
2631 Make_Defining_Identifier (Loc, Name_uD),
2632 Parameter_Type =>
2633 New_Reference_To (Standard_Duration, Loc)));
2635 Append_To (Params,
2636 Make_Parameter_Specification (Loc,
2637 Defining_Identifier =>
2638 Make_Defining_Identifier (Loc, Name_uM),
2639 Parameter_Type =>
2640 New_Reference_To (Standard_Integer, Loc)));
2642 SEU.Build_C (Loc, Params);
2643 SEU.Build_F (Loc, Params);
2645 Set_Is_Internal (Def_Id);
2647 return
2648 Make_Procedure_Specification (Loc,
2649 Defining_Unit_Name => Def_Id,
2650 Parameter_Specifications => Params);
2651 end Make_Disp_Timed_Select_Spec;
2653 -------------
2654 -- Make_DT --
2655 -------------
2657 function Make_DT (Typ : Entity_Id) return List_Id is
2658 Loc : constant Source_Ptr := Sloc (Typ);
2659 Result : constant List_Id := New_List;
2660 Elab_Code : constant List_Id := New_List;
2662 Tname : constant Name_Id := Chars (Typ);
2663 Name_DT : constant Name_Id := New_External_Name (Tname, 'T');
2664 Name_DT_Ptr : constant Name_Id := New_External_Name (Tname, 'P');
2665 Name_SSD : constant Name_Id := New_External_Name (Tname, 'S');
2666 Name_TSD : constant Name_Id := New_External_Name (Tname, 'B');
2667 Name_Exname : constant Name_Id := New_External_Name (Tname, 'E');
2668 Name_No_Reg : constant Name_Id := New_External_Name (Tname, 'F');
2669 Name_ITable : Name_Id;
2671 DT : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT);
2672 DT_Ptr : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT_Ptr);
2673 SSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_SSD);
2674 TSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_TSD);
2675 Exname : constant Node_Id := Make_Defining_Identifier (Loc, Name_Exname);
2676 No_Reg : constant Node_Id := Make_Defining_Identifier (Loc, Name_No_Reg);
2677 ITable : Node_Id;
2679 Generalized_Tag : constant Entity_Id := RTE (RE_Tag);
2680 AI : Elmt_Id;
2681 I_Depth : Int;
2682 Nb_Prim : Int;
2683 Num_Ifaces : Int;
2684 Old_Tag1 : Node_Id;
2685 Old_Tag2 : Node_Id;
2686 Parent_Num_Ifaces : Int;
2687 Size_Expr_Node : Node_Id;
2688 TSD_Num_Entries : Int;
2690 Ancestor_Copy : Entity_Id;
2691 Empty_DT : Boolean := False;
2692 Typ_Copy : Entity_Id;
2694 begin
2695 if not RTE_Available (RE_Tag) then
2696 Error_Msg_CRT ("tagged types", Typ);
2697 return New_List;
2698 end if;
2700 -- Calculate the size of the DT and the TSD
2702 if Is_Interface (Typ) then
2704 -- Abstract interfaces need neither the DT nor the ancestors table.
2705 -- We reserve a single entry for its DT because at run-time the
2706 -- pointer to this dummy DT will be used as the tag of this abstract
2707 -- interface type.
2709 Empty_DT := True;
2710 Nb_Prim := 1;
2711 TSD_Num_Entries := 0;
2712 Num_Ifaces := 0;
2714 else
2715 -- Count the number of interfaces implemented by the ancestors
2717 Parent_Num_Ifaces := 0;
2718 Num_Ifaces := 0;
2720 if Typ /= Etype (Typ) then
2721 Ancestor_Copy := New_Copy (Etype (Typ));
2722 Set_Parent (Ancestor_Copy, Parent (Etype (Typ)));
2723 Set_Abstract_Interfaces (Ancestor_Copy, New_Elmt_List);
2724 Collect_All_Interfaces (Ancestor_Copy);
2726 AI := First_Elmt (Abstract_Interfaces (Ancestor_Copy));
2727 while Present (AI) loop
2728 Parent_Num_Ifaces := Parent_Num_Ifaces + 1;
2729 Next_Elmt (AI);
2730 end loop;
2731 end if;
2733 -- Count the number of additional interfaces implemented by Typ
2735 Typ_Copy := New_Copy (Typ);
2736 Set_Parent (Typ_Copy, Parent (Typ));
2737 Set_Abstract_Interfaces (Typ_Copy, New_Elmt_List);
2738 Collect_All_Interfaces (Typ_Copy);
2740 AI := First_Elmt (Abstract_Interfaces (Typ_Copy));
2741 while Present (AI) loop
2742 Num_Ifaces := Num_Ifaces + 1;
2743 Next_Elmt (AI);
2744 end loop;
2746 -- Count ancestors to compute the inheritance depth. For private
2747 -- extensions, always go to the full view in order to compute the
2748 -- real inheritance depth.
2750 declare
2751 Parent_Type : Entity_Id := Typ;
2752 P : Entity_Id;
2754 begin
2755 I_Depth := 0;
2756 loop
2757 P := Etype (Parent_Type);
2759 if Is_Private_Type (P) then
2760 P := Full_View (Base_Type (P));
2761 end if;
2763 exit when P = Parent_Type;
2765 I_Depth := I_Depth + 1;
2766 Parent_Type := P;
2767 end loop;
2768 end;
2770 TSD_Num_Entries := I_Depth + 1;
2771 Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ)));
2773 -- If the number of primitives of Typ is 0 (or we are compiling with
2774 -- the No_Dispatching_Calls restriction) we reserve a dummy single
2775 -- entry for its DT because at run-time the pointer to this dummy DT
2776 -- will be used as the tag of this tagged type.
2778 if Nb_Prim = 0 or else Restriction_Active (No_Dispatching_Calls) then
2779 Empty_DT := True;
2780 Nb_Prim := 1;
2781 end if;
2782 end if;
2784 -- Dispatch table and related entities are allocated statically
2786 Set_Ekind (DT, E_Variable);
2787 Set_Is_Statically_Allocated (DT);
2789 Set_Ekind (DT_Ptr, E_Variable);
2790 Set_Is_Statically_Allocated (DT_Ptr);
2792 if not Is_Interface (Typ)
2793 and then Num_Ifaces > 0
2794 then
2795 Name_ITable := New_External_Name (Tname, 'I');
2796 ITable := Make_Defining_Identifier (Loc, Name_ITable);
2798 Set_Ekind (ITable, E_Variable);
2799 Set_Is_Statically_Allocated (ITable);
2800 end if;
2802 Set_Ekind (SSD, E_Variable);
2803 Set_Is_Statically_Allocated (SSD);
2805 Set_Ekind (TSD, E_Variable);
2806 Set_Is_Statically_Allocated (TSD);
2808 Set_Ekind (Exname, E_Variable);
2809 Set_Is_Statically_Allocated (Exname);
2811 Set_Ekind (No_Reg, E_Variable);
2812 Set_Is_Statically_Allocated (No_Reg);
2814 -- Generate code to create the storage for the Dispatch_Table object:
2816 -- DT : Storage_Array (1..DT_Prologue_Size+nb_prim*DT_Entry_Size);
2817 -- for DT'Alignment use Address'Alignment
2819 Size_Expr_Node :=
2820 Make_Op_Add (Loc,
2821 Left_Opnd => Make_DT_Access_Action (Typ, DT_Prologue_Size, No_List),
2822 Right_Opnd =>
2823 Make_Op_Multiply (Loc,
2824 Left_Opnd =>
2825 Make_DT_Access_Action (Typ, DT_Entry_Size, No_List),
2826 Right_Opnd =>
2827 Make_Integer_Literal (Loc, Nb_Prim)));
2829 Append_To (Result,
2830 Make_Object_Declaration (Loc,
2831 Defining_Identifier => DT,
2832 Aliased_Present => True,
2833 Object_Definition =>
2834 Make_Subtype_Indication (Loc,
2835 Subtype_Mark => New_Reference_To
2836 (RTE (RE_Storage_Array), Loc),
2837 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
2838 Constraints => New_List (
2839 Make_Range (Loc,
2840 Low_Bound => Make_Integer_Literal (Loc, 1),
2841 High_Bound => Size_Expr_Node))))));
2843 Append_To (Result,
2844 Make_Attribute_Definition_Clause (Loc,
2845 Name => New_Reference_To (DT, Loc),
2846 Chars => Name_Alignment,
2847 Expression =>
2848 Make_Attribute_Reference (Loc,
2849 Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc),
2850 Attribute_Name => Name_Alignment)));
2852 -- Generate code to create the pointer to the dispatch table
2854 -- DT_Ptr : Tag := Tag!(DT'Address);
2856 -- According to the C++ ABI, the base of the vtable is located after a
2857 -- prologue containing Offset_To_Top, and Typeinfo_Ptr. Hence, we move
2858 -- down the pointer to the real base of the vtable
2860 Append_To (Result,
2861 Make_Object_Declaration (Loc,
2862 Defining_Identifier => DT_Ptr,
2863 Constant_Present => True,
2864 Object_Definition => New_Reference_To (Generalized_Tag, Loc),
2865 Expression =>
2866 Unchecked_Convert_To (Generalized_Tag,
2867 Make_Op_Add (Loc,
2868 Left_Opnd =>
2869 Unchecked_Convert_To (RTE (RE_Storage_Offset),
2870 Make_Attribute_Reference (Loc,
2871 Prefix => New_Reference_To (DT, Loc),
2872 Attribute_Name => Name_Address)),
2873 Right_Opnd =>
2874 Make_DT_Access_Action (Typ,
2875 DT_Prologue_Size, No_List)))));
2877 -- Generate code to define the boolean that controls registration, in
2878 -- order to avoid multiple registrations for tagged types defined in
2879 -- multiple-called scopes.
2881 Append_To (Result,
2882 Make_Object_Declaration (Loc,
2883 Defining_Identifier => No_Reg,
2884 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
2885 Expression => New_Reference_To (Standard_True, Loc)));
2887 -- Set Access_Disp_Table field to be the dispatch table pointer
2889 if No (Access_Disp_Table (Typ)) then
2890 Set_Access_Disp_Table (Typ, New_Elmt_List);
2891 end if;
2893 Prepend_Elmt (DT_Ptr, Access_Disp_Table (Typ));
2895 -- Generate code to create the storage for the type specific data object
2896 -- with enough space to store the tags of the ancestors plus the tags
2897 -- of all the implemented interfaces (as described in a-tags.adb).
2899 -- TSD: Storage_Array
2900 -- (1..TSD_Prologue_Size+TSD_Num_Entries*TSD_Entry_Size);
2901 -- for TSD'Alignment use Address'Alignment
2903 Size_Expr_Node :=
2904 Make_Op_Add (Loc,
2905 Left_Opnd =>
2906 Make_DT_Access_Action (Typ, TSD_Prologue_Size, No_List),
2907 Right_Opnd =>
2908 Make_Op_Multiply (Loc,
2909 Left_Opnd =>
2910 Make_DT_Access_Action (Typ, TSD_Entry_Size, No_List),
2911 Right_Opnd =>
2912 Make_Integer_Literal (Loc, TSD_Num_Entries)));
2914 Append_To (Result,
2915 Make_Object_Declaration (Loc,
2916 Defining_Identifier => TSD,
2917 Aliased_Present => True,
2918 Object_Definition =>
2919 Make_Subtype_Indication (Loc,
2920 Subtype_Mark => New_Reference_To (RTE (RE_Storage_Array), Loc),
2921 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
2922 Constraints => New_List (
2923 Make_Range (Loc,
2924 Low_Bound => Make_Integer_Literal (Loc, 1),
2925 High_Bound => Size_Expr_Node))))));
2927 Append_To (Result,
2928 Make_Attribute_Definition_Clause (Loc,
2929 Name => New_Reference_To (TSD, Loc),
2930 Chars => Name_Alignment,
2931 Expression =>
2932 Make_Attribute_Reference (Loc,
2933 Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc),
2934 Attribute_Name => Name_Alignment)));
2936 -- Generate:
2937 -- Set_Signature (DT_Ptr, Value);
2939 if Is_Interface (Typ) then
2940 Append_To (Elab_Code,
2941 Make_DT_Access_Action (Typ,
2942 Action => Set_Signature,
2943 Args => New_List (
2944 New_Reference_To (DT_Ptr, Loc), -- DTptr
2945 New_Reference_To (RTE (RE_Abstract_Interface), Loc))));
2947 elsif RTE_Available (RE_Set_Signature) then
2948 Append_To (Elab_Code,
2949 Make_DT_Access_Action (Typ,
2950 Action => Set_Signature,
2951 Args => New_List (
2952 New_Reference_To (DT_Ptr, Loc), -- DTptr
2953 New_Reference_To (RTE (RE_Primary_DT), Loc))));
2954 end if;
2956 -- Generate code to put the Address of the TSD in the dispatch table
2957 -- Set_TSD (DT_Ptr, TSD);
2959 Append_To (Elab_Code,
2960 Make_DT_Access_Action (Typ,
2961 Action => Set_TSD,
2962 Args => New_List (
2963 New_Reference_To (DT_Ptr, Loc), -- DTptr
2964 Make_Attribute_Reference (Loc, -- Value
2965 Prefix => New_Reference_To (TSD, Loc),
2966 Attribute_Name => Name_Address))));
2968 -- Set the pointer to the Interfaces_Table (if any). Otherwise the
2969 -- corresponding access component is set to null.
2971 if Is_Interface (Typ) then
2972 null;
2974 elsif Num_Ifaces = 0 then
2975 if RTE_Available (RE_Set_Interface_Table) then
2976 Append_To (Elab_Code,
2977 Make_DT_Access_Action (Typ,
2978 Action => Set_Interface_Table,
2979 Args => New_List (
2980 New_Reference_To (DT_Ptr, Loc), -- DTptr
2981 New_Reference_To (RTE (RE_Null_Address), Loc)))); -- null
2982 end if;
2984 -- Generate the Interface_Table object and set the access
2985 -- component if the TSD to it.
2987 elsif RTE_Available (RE_Set_Interface_Table) then
2988 Append_To (Result,
2989 Make_Object_Declaration (Loc,
2990 Defining_Identifier => ITable,
2991 Aliased_Present => True,
2992 Object_Definition =>
2993 Make_Subtype_Indication (Loc,
2994 Subtype_Mark => New_Reference_To
2995 (RTE (RE_Interface_Data), Loc),
2996 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
2997 Constraints => New_List (
2998 Make_Integer_Literal (Loc,
2999 Num_Ifaces))))));
3001 Append_To (Elab_Code,
3002 Make_DT_Access_Action (Typ,
3003 Action => Set_Interface_Table,
3004 Args => New_List (
3005 New_Reference_To (DT_Ptr, Loc), -- DTptr
3006 Make_Attribute_Reference (Loc, -- Value
3007 Prefix => New_Reference_To (ITable, Loc),
3008 Attribute_Name => Name_Address))));
3009 end if;
3011 -- Generate:
3012 -- Set_Num_Prim_Ops (T'Tag, Nb_Prim)
3014 if RTE_Available (RE_Set_Num_Prim_Ops) then
3015 if not Is_Interface (Typ) then
3016 if Empty_DT then
3017 Append_To (Elab_Code,
3018 Make_Procedure_Call_Statement (Loc,
3019 Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc),
3020 Parameter_Associations => New_List (
3021 New_Reference_To (DT_Ptr, Loc),
3022 Make_Integer_Literal (Loc, Uint_0))));
3023 else
3024 Append_To (Elab_Code,
3025 Make_Procedure_Call_Statement (Loc,
3026 Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc),
3027 Parameter_Associations => New_List (
3028 New_Reference_To (DT_Ptr, Loc),
3029 Make_Integer_Literal (Loc, Nb_Prim))));
3030 end if;
3031 end if;
3033 if Ada_Version >= Ada_05
3034 and then not Is_Interface (Typ)
3035 and then not Is_Abstract (Typ)
3036 and then not Is_Controlled (Typ)
3037 and then not Restriction_Active (No_Dispatching_Calls)
3038 then
3039 -- Generate:
3040 -- Set_Type_Kind (T'Tag, Type_Kind (Typ));
3042 Append_To (Elab_Code,
3043 Make_DT_Access_Action (Typ,
3044 Action => Set_Tagged_Kind,
3045 Args => New_List (
3046 New_Reference_To (DT_Ptr, Loc), -- DTptr
3047 Tagged_Kind (Typ)))); -- Value
3049 -- Generate the Select Specific Data table for synchronized
3050 -- types that implement a synchronized interface. The size
3051 -- of the table is constrained by the number of non-predefined
3052 -- primitive operations.
3054 if not Empty_DT
3055 and then Is_Concurrent_Record_Type (Typ)
3056 and then Implements_Interface (
3057 Typ => Typ,
3058 Kind => Any_Limited_Interface,
3059 Check_Parent => True)
3060 then
3061 Append_To (Result,
3062 Make_Object_Declaration (Loc,
3063 Defining_Identifier => SSD,
3064 Aliased_Present => True,
3065 Object_Definition =>
3066 Make_Subtype_Indication (Loc,
3067 Subtype_Mark => New_Reference_To (
3068 RTE (RE_Select_Specific_Data), Loc),
3069 Constraint =>
3070 Make_Index_Or_Discriminant_Constraint (Loc,
3071 Constraints => New_List (
3072 Make_Integer_Literal (Loc, Nb_Prim))))));
3074 -- Set the pointer to the Select Specific Data table in the TSD
3076 Append_To (Elab_Code,
3077 Make_DT_Access_Action (Typ,
3078 Action => Set_SSD,
3079 Args => New_List (
3080 New_Reference_To (DT_Ptr, Loc), -- DTptr
3081 Make_Attribute_Reference (Loc, -- Value
3082 Prefix => New_Reference_To (SSD, Loc),
3083 Attribute_Name => Name_Address))));
3084 end if;
3085 end if;
3086 end if;
3088 -- Generate: Exname : constant String := full_qualified_name (typ);
3089 -- The type itself may be an anonymous parent type, so use the first
3090 -- subtype to have a user-recognizable name.
3092 Append_To (Result,
3093 Make_Object_Declaration (Loc,
3094 Defining_Identifier => Exname,
3095 Constant_Present => True,
3096 Object_Definition => New_Reference_To (Standard_String, Loc),
3097 Expression =>
3098 Make_String_Literal (Loc,
3099 Full_Qualified_Name (First_Subtype (Typ)))));
3101 -- Generate: Set_Expanded_Name (DT_Ptr, exname'Address);
3103 Append_To (Elab_Code,
3104 Make_DT_Access_Action (Typ,
3105 Action => Set_Expanded_Name,
3106 Args => New_List (
3107 Node1 => New_Reference_To (DT_Ptr, Loc),
3108 Node2 =>
3109 Make_Attribute_Reference (Loc,
3110 Prefix => New_Reference_To (Exname, Loc),
3111 Attribute_Name => Name_Address))));
3113 if not Is_Interface (Typ) then
3114 -- Generate: Set_Access_Level (DT_Ptr, <type's accessibility level>);
3116 Append_To (Elab_Code,
3117 Make_DT_Access_Action (Typ,
3118 Action => Set_Access_Level,
3119 Args => New_List (
3120 Node1 => New_Reference_To (DT_Ptr, Loc),
3121 Node2 => Make_Integer_Literal (Loc, Type_Access_Level (Typ)))));
3122 end if;
3124 if Typ = Etype (Typ)
3125 or else Is_CPP_Class (Etype (Typ))
3126 or else Is_Interface (Typ)
3127 then
3128 Old_Tag1 :=
3129 Unchecked_Convert_To (Generalized_Tag,
3130 Make_Integer_Literal (Loc, 0));
3131 Old_Tag2 :=
3132 Unchecked_Convert_To (Generalized_Tag,
3133 Make_Integer_Literal (Loc, 0));
3135 else
3136 Old_Tag1 :=
3137 New_Reference_To
3138 (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc);
3139 Old_Tag2 :=
3140 New_Reference_To
3141 (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc);
3142 end if;
3144 if Typ /= Etype (Typ)
3145 and then not Is_Interface (Typ)
3146 and then not Restriction_Active (No_Dispatching_Calls)
3147 then
3148 -- Generate: Inherit_DT (parent'tag, DT_Ptr, nb_prim of parent);
3150 if not Is_Interface (Etype (Typ)) then
3151 if Restriction_Active (No_Dispatching_Calls) then
3152 Append_To (Elab_Code,
3153 Make_DT_Access_Action (Typ,
3154 Action => Inherit_DT,
3155 Args => New_List (
3156 Node1 => Old_Tag1,
3157 Node2 => New_Reference_To (DT_Ptr, Loc),
3158 Node3 => Make_Integer_Literal (Loc, Uint_0))));
3159 else
3160 Append_To (Elab_Code,
3161 Make_DT_Access_Action (Typ,
3162 Action => Inherit_DT,
3163 Args => New_List (
3164 Node1 => Old_Tag1,
3165 Node2 => New_Reference_To (DT_Ptr, Loc),
3166 Node3 => Make_Integer_Literal (Loc,
3167 DT_Entry_Count
3168 (First_Tag_Component (Etype (Typ)))))));
3169 end if;
3170 end if;
3172 -- Inherit the secondary dispatch tables of the ancestor
3174 if not Restriction_Active (No_Dispatching_Calls)
3175 and then not Is_CPP_Class (Etype (Typ))
3176 then
3177 declare
3178 Sec_DT_Ancestor : Elmt_Id :=
3179 Next_Elmt
3180 (First_Elmt
3181 (Access_Disp_Table (Etype (Typ))));
3182 Sec_DT_Typ : Elmt_Id :=
3183 Next_Elmt
3184 (First_Elmt
3185 (Access_Disp_Table (Typ)));
3187 procedure Copy_Secondary_DTs (Typ : Entity_Id);
3188 -- Local procedure required to climb through the ancestors and
3189 -- copy the contents of all their secondary dispatch tables.
3191 ------------------------
3192 -- Copy_Secondary_DTs --
3193 ------------------------
3195 procedure Copy_Secondary_DTs (Typ : Entity_Id) is
3196 E : Entity_Id;
3197 Iface : Elmt_Id;
3199 begin
3200 -- Climb to the ancestor (if any) handling private types
3202 if Present (Full_View (Etype (Typ))) then
3203 if Full_View (Etype (Typ)) /= Typ then
3204 Copy_Secondary_DTs (Full_View (Etype (Typ)));
3205 end if;
3207 elsif Etype (Typ) /= Typ then
3208 Copy_Secondary_DTs (Etype (Typ));
3209 end if;
3211 if Present (Abstract_Interfaces (Typ))
3212 and then not Is_Empty_Elmt_List
3213 (Abstract_Interfaces (Typ))
3214 then
3215 Iface := First_Elmt (Abstract_Interfaces (Typ));
3216 E := First_Entity (Typ);
3217 while Present (E)
3218 and then Present (Node (Sec_DT_Ancestor))
3219 loop
3220 if Is_Tag (E) and then Chars (E) /= Name_uTag then
3221 if not Is_Interface (Etype (Typ)) then
3222 Append_To (Elab_Code,
3223 Make_DT_Access_Action (Typ,
3224 Action => Inherit_DT,
3225 Args => New_List (
3226 Node1 => Unchecked_Convert_To
3227 (RTE (RE_Tag),
3228 New_Reference_To
3229 (Node (Sec_DT_Ancestor),
3230 Loc)),
3231 Node2 => Unchecked_Convert_To
3232 (RTE (RE_Tag),
3233 New_Reference_To
3234 (Node (Sec_DT_Typ), Loc)),
3235 Node3 => Make_Integer_Literal (Loc,
3236 DT_Entry_Count (E)))));
3237 end if;
3239 Next_Elmt (Sec_DT_Ancestor);
3240 Next_Elmt (Sec_DT_Typ);
3241 Next_Elmt (Iface);
3242 end if;
3244 Next_Entity (E);
3245 end loop;
3246 end if;
3247 end Copy_Secondary_DTs;
3249 begin
3250 if Present (Node (Sec_DT_Ancestor)) then
3252 -- Handle private types
3254 if Present (Full_View (Typ)) then
3255 Copy_Secondary_DTs (Full_View (Typ));
3256 else
3257 Copy_Secondary_DTs (Typ);
3258 end if;
3259 end if;
3260 end;
3261 end if;
3262 end if;
3264 -- Generate:
3265 -- Inherit_TSD (parent'tag, DT_Ptr);
3267 Append_To (Elab_Code,
3268 Make_DT_Access_Action (Typ,
3269 Action => Inherit_TSD,
3270 Args => New_List (
3271 Node1 => Old_Tag2,
3272 Node2 => New_Reference_To (DT_Ptr, Loc))));
3274 if not Is_Interface (Typ) then
3276 -- For types with no controlled components, generate:
3277 -- Set_RC_Offset (DT_Ptr, 0);
3279 -- For simple types with controlled components, generate:
3280 -- Set_RC_Offset (DT_Ptr, type._record_controller'position);
3282 -- For complex types with controlled components where the position
3283 -- of the record controller is not statically computable, if there
3284 -- are controlled components at this level, generate:
3285 -- Set_RC_Offset (DT_Ptr, -1);
3286 -- to indicate that the _controller field is right after the _parent
3288 -- Or if there are no controlled components at this level, generate:
3289 -- Set_RC_Offset (DT_Ptr, -2);
3290 -- to indicate that we need to get the position from the parent.
3292 declare
3293 Position : Node_Id;
3295 begin
3296 if not Has_Controlled_Component (Typ) then
3297 Position := Make_Integer_Literal (Loc, 0);
3299 elsif Etype (Typ) /= Typ
3300 and then Has_Discriminants (Etype (Typ))
3301 then
3302 if Has_New_Controlled_Component (Typ) then
3303 Position := Make_Integer_Literal (Loc, -1);
3304 else
3305 Position := Make_Integer_Literal (Loc, -2);
3306 end if;
3307 else
3308 Position :=
3309 Make_Attribute_Reference (Loc,
3310 Prefix =>
3311 Make_Selected_Component (Loc,
3312 Prefix => New_Reference_To (Typ, Loc),
3313 Selector_Name =>
3314 New_Reference_To (Controller_Component (Typ), Loc)),
3315 Attribute_Name => Name_Position);
3317 -- This is not proper Ada code to use the attribute 'Position
3318 -- on something else than an object but this is supported by
3319 -- the back end (see comment on the Bit_Component attribute in
3320 -- sem_attr). So we avoid semantic checking here.
3322 -- Is this documented in sinfo.ads??? it should be!
3324 Set_Analyzed (Position);
3325 Set_Etype (Prefix (Position), RTE (RE_Record_Controller));
3326 Set_Etype (Prefix (Prefix (Position)), Typ);
3327 Set_Etype (Selector_Name (Prefix (Position)),
3328 RTE (RE_Record_Controller));
3329 Set_Etype (Position, RTE (RE_Storage_Offset));
3330 end if;
3332 Append_To (Elab_Code,
3333 Make_DT_Access_Action (Typ,
3334 Action => Set_RC_Offset,
3335 Args => New_List (
3336 Node1 => New_Reference_To (DT_Ptr, Loc),
3337 Node2 => Position)));
3338 end;
3340 -- Generate: Set_Remotely_Callable (DT_Ptr, Status); where Status is
3341 -- described in E.4 (18)
3343 declare
3344 Status : Entity_Id;
3346 begin
3347 Status :=
3348 Boolean_Literals
3349 (Is_Pure (Typ)
3350 or else Is_Shared_Passive (Typ)
3351 or else
3352 ((Is_Remote_Types (Typ)
3353 or else Is_Remote_Call_Interface (Typ))
3354 and then Original_View_In_Visible_Part (Typ))
3355 or else not Comes_From_Source (Typ));
3357 Append_To (Elab_Code,
3358 Make_DT_Access_Action (Typ,
3359 Action => Set_Remotely_Callable,
3360 Args => New_List (
3361 New_Occurrence_Of (DT_Ptr, Loc),
3362 New_Occurrence_Of (Status, Loc))));
3363 end;
3365 if RTE_Available (RE_Set_Offset_To_Top) then
3366 -- Generate:
3367 -- Set_Offset_To_Top (0, DT_Ptr, True, 0, null);
3369 Append_To (Elab_Code,
3370 Make_Procedure_Call_Statement (Loc,
3371 Name => New_Reference_To (RTE (RE_Set_Offset_To_Top), Loc),
3372 Parameter_Associations => New_List (
3373 New_Reference_To (RTE (RE_Null_Address), Loc),
3374 New_Reference_To (DT_Ptr, Loc),
3375 New_Occurrence_Of (Standard_True, Loc),
3376 Make_Integer_Literal (Loc, Uint_0),
3377 New_Reference_To (RTE (RE_Null_Address), Loc))));
3378 end if;
3379 end if;
3381 -- Generate: Set_External_Tag (DT_Ptr, exname'Address);
3382 -- Should be the external name not the qualified name???
3384 if not Has_External_Tag_Rep_Clause (Typ) then
3385 Append_To (Elab_Code,
3386 Make_DT_Access_Action (Typ,
3387 Action => Set_External_Tag,
3388 Args => New_List (
3389 Node1 => New_Reference_To (DT_Ptr, Loc),
3390 Node2 =>
3391 Make_Attribute_Reference (Loc,
3392 Prefix => New_Reference_To (Exname, Loc),
3393 Attribute_Name => Name_Address))));
3395 -- Generate code to register the Tag in the External_Tag hash
3396 -- table for the pure Ada type only.
3398 -- Register_Tag (Dt_Ptr);
3400 -- Skip this if routine not available, or in No_Run_Time mode
3401 -- or Typ is an abstract interface type (because the table to
3402 -- register it is not available in the abstract type but in
3403 -- types implementing this interface)
3405 if not No_Run_Time_Mode
3406 and then RTE_Available (RE_Register_Tag)
3407 and then Is_RTE (Generalized_Tag, RE_Tag)
3408 and then not Is_Interface (Typ)
3409 then
3410 Append_To (Elab_Code,
3411 Make_Procedure_Call_Statement (Loc,
3412 Name => New_Reference_To (RTE (RE_Register_Tag), Loc),
3413 Parameter_Associations =>
3414 New_List (New_Reference_To (DT_Ptr, Loc))));
3415 end if;
3416 end if;
3418 -- Generate:
3419 -- if No_Reg then
3420 -- <elab_code>
3421 -- No_Reg := False;
3422 -- end if;
3424 Append_To (Elab_Code,
3425 Make_Assignment_Statement (Loc,
3426 Name => New_Reference_To (No_Reg, Loc),
3427 Expression => New_Reference_To (Standard_False, Loc)));
3429 Append_To (Result,
3430 Make_Implicit_If_Statement (Typ,
3431 Condition => New_Reference_To (No_Reg, Loc),
3432 Then_Statements => Elab_Code));
3434 -- Ada 2005 (AI-251): Register the tag of the interfaces into
3435 -- the table of implemented interfaces.
3437 if not Is_Interface (Typ)
3438 and then Num_Ifaces > 0
3439 then
3440 declare
3441 Position : Int;
3443 begin
3444 -- If the parent is an interface we must generate code to register
3445 -- all its interfaces; otherwise this code is not needed because
3446 -- Inherit_TSD has already inherited such interfaces.
3448 if Is_Interface (Etype (Typ)) then
3449 Position := 1;
3451 AI := First_Elmt (Abstract_Interfaces (Ancestor_Copy));
3452 while Present (AI) loop
3453 -- Generate:
3454 -- Register_Interface (DT_Ptr, Interface'Tag);
3456 Append_To (Result,
3457 Make_DT_Access_Action (Typ,
3458 Action => Register_Interface_Tag,
3459 Args => New_List (
3460 Node1 => New_Reference_To (DT_Ptr, Loc),
3461 Node2 => New_Reference_To
3462 (Node
3463 (First_Elmt
3464 (Access_Disp_Table (Node (AI)))),
3465 Loc),
3466 Node3 => Make_Integer_Literal (Loc, Position))));
3468 Position := Position + 1;
3469 Next_Elmt (AI);
3470 end loop;
3471 end if;
3473 -- Register the interfaces that are not implemented by the
3474 -- ancestor
3476 if Present (Abstract_Interfaces (Typ_Copy)) then
3477 AI := First_Elmt (Abstract_Interfaces (Typ_Copy));
3479 -- Skip the interfaces implemented by the ancestor
3481 for Count in 1 .. Parent_Num_Ifaces loop
3482 Next_Elmt (AI);
3483 end loop;
3485 -- Register the additional interfaces
3487 Position := Parent_Num_Ifaces + 1;
3488 while Present (AI) loop
3489 -- Generate:
3490 -- Register_Interface (DT_Ptr, Interface'Tag);
3492 Append_To (Result,
3493 Make_DT_Access_Action (Typ,
3494 Action => Register_Interface_Tag,
3495 Args => New_List (
3496 Node1 => New_Reference_To (DT_Ptr, Loc),
3497 Node2 => New_Reference_To
3498 (Node
3499 (First_Elmt
3500 (Access_Disp_Table (Node (AI)))),
3501 Loc),
3502 Node3 => Make_Integer_Literal (Loc, Position))));
3504 Position := Position + 1;
3505 Next_Elmt (AI);
3506 end loop;
3507 end if;
3509 pragma Assert (Position = Num_Ifaces + 1);
3510 end;
3511 end if;
3513 return Result;
3514 end Make_DT;
3516 ---------------------------
3517 -- Make_DT_Access_Action --
3518 ---------------------------
3520 function Make_DT_Access_Action
3521 (Typ : Entity_Id;
3522 Action : DT_Access_Action;
3523 Args : List_Id) return Node_Id
3525 Action_Name : constant Entity_Id := RTE (Ada_Actions (Action));
3526 Loc : Source_Ptr;
3528 begin
3529 if No (Args) then
3531 -- This is a constant
3533 return New_Reference_To (Action_Name, Sloc (Typ));
3534 end if;
3536 pragma Assert (List_Length (Args) = Action_Nb_Arg (Action));
3538 Loc := Sloc (First (Args));
3540 if Action_Is_Proc (Action) then
3541 return
3542 Make_Procedure_Call_Statement (Loc,
3543 Name => New_Reference_To (Action_Name, Loc),
3544 Parameter_Associations => Args);
3546 else
3547 return
3548 Make_Function_Call (Loc,
3549 Name => New_Reference_To (Action_Name, Loc),
3550 Parameter_Associations => Args);
3551 end if;
3552 end Make_DT_Access_Action;
3554 -----------------------
3555 -- Make_Secondary_DT --
3556 -----------------------
3558 procedure Make_Secondary_DT
3559 (Typ : Entity_Id;
3560 Ancestor_Typ : Entity_Id;
3561 Suffix_Index : Int;
3562 Iface : Entity_Id;
3563 AI_Tag : Entity_Id;
3564 Acc_Disp_Tables : in out Elist_Id;
3565 Result : out List_Id)
3567 Loc : constant Source_Ptr := Sloc (AI_Tag);
3568 Generalized_Tag : constant Entity_Id := RTE (RE_Interface_Tag);
3569 Name_DT : constant Name_Id := New_Internal_Name ('T');
3570 Empty_DT : Boolean := False;
3571 Iface_DT : Node_Id;
3572 Iface_DT_Ptr : Node_Id;
3573 Name_DT_Ptr : Name_Id;
3574 Nb_Prim : Int;
3575 OSD : Entity_Id;
3576 Size_Expr_Node : Node_Id;
3577 Tname : Name_Id;
3579 begin
3580 Result := New_List;
3582 -- Generate a unique external name associated with the secondary
3583 -- dispatch table. This external name will be used to declare an
3584 -- access to this secondary dispatch table, value that will be used
3585 -- for the elaboration of Typ's objects and also for the elaboration
3586 -- of objects of any derivation of Typ that do not override any
3587 -- primitive operation of Typ.
3589 Get_Secondary_DT_External_Name (Typ, Ancestor_Typ, Suffix_Index);
3591 Tname := Name_Find;
3592 Name_DT_Ptr := New_External_Name (Tname, "P");
3593 Iface_DT := Make_Defining_Identifier (Loc, Name_DT);
3594 Iface_DT_Ptr := Make_Defining_Identifier (Loc, Name_DT_Ptr);
3596 -- Dispatch table and related entities are allocated statically
3598 Set_Ekind (Iface_DT, E_Variable);
3599 Set_Is_Statically_Allocated (Iface_DT);
3601 Set_Ekind (Iface_DT_Ptr, E_Variable);
3602 Set_Is_Statically_Allocated (Iface_DT_Ptr);
3604 -- Generate code to create the storage for the Dispatch_Table object.
3605 -- If the number of primitives of Typ is 0 we reserve a dummy single
3606 -- entry for its DT because at run-time the pointer to this dummy entry
3607 -- will be used as the tag.
3609 Nb_Prim := UI_To_Int (DT_Entry_Count (AI_Tag));
3611 if Nb_Prim = 0 then
3612 Empty_DT := True;
3613 Nb_Prim := 1;
3614 end if;
3616 -- DT : Storage_Array (1..DT_Prologue_Size+nb_prim*DT_Entry_Size);
3617 -- for DT'Alignment use Address'Alignment
3619 Size_Expr_Node :=
3620 Make_Op_Add (Loc,
3621 Left_Opnd => Make_DT_Access_Action (Etype (AI_Tag),
3622 DT_Prologue_Size,
3623 No_List),
3624 Right_Opnd =>
3625 Make_Op_Multiply (Loc,
3626 Left_Opnd =>
3627 Make_DT_Access_Action (Etype (AI_Tag),
3628 DT_Entry_Size,
3629 No_List),
3630 Right_Opnd =>
3631 Make_Integer_Literal (Loc, Nb_Prim)));
3633 Append_To (Result,
3634 Make_Object_Declaration (Loc,
3635 Defining_Identifier => Iface_DT,
3636 Aliased_Present => True,
3637 Object_Definition =>
3638 Make_Subtype_Indication (Loc,
3639 Subtype_Mark => New_Reference_To (RTE (RE_Storage_Array), Loc),
3640 Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
3641 Constraints => New_List (
3642 Make_Range (Loc,
3643 Low_Bound => Make_Integer_Literal (Loc, 1),
3644 High_Bound => Size_Expr_Node))))));
3646 Append_To (Result,
3647 Make_Attribute_Definition_Clause (Loc,
3648 Name => New_Reference_To (Iface_DT, Loc),
3649 Chars => Name_Alignment,
3650 Expression =>
3651 Make_Attribute_Reference (Loc,
3652 Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc),
3653 Attribute_Name => Name_Alignment)));
3655 -- Generate code to create the pointer to the dispatch table
3657 -- Iface_DT_Ptr : Tag := Tag!(DT'Address);
3659 -- According to the C++ ABI, the base of the vtable is located
3660 -- after the following prologue: Offset_To_Top, and Typeinfo_Ptr.
3661 -- Hence, move the pointer down to the real base of the vtable.
3663 Append_To (Result,
3664 Make_Object_Declaration (Loc,
3665 Defining_Identifier => Iface_DT_Ptr,
3666 Constant_Present => True,
3667 Object_Definition => New_Reference_To (Generalized_Tag, Loc),
3668 Expression =>
3669 Unchecked_Convert_To (Generalized_Tag,
3670 Make_Op_Add (Loc,
3671 Left_Opnd =>
3672 Unchecked_Convert_To (RTE (RE_Storage_Offset),
3673 Make_Attribute_Reference (Loc,
3674 Prefix => New_Reference_To (Iface_DT, Loc),
3675 Attribute_Name => Name_Address)),
3676 Right_Opnd =>
3677 Make_DT_Access_Action (Etype (AI_Tag),
3678 DT_Prologue_Size, No_List)))));
3680 -- Note: Offset_To_Top will be initialized by the init subprogram
3682 -- Set Access_Disp_Table field to be the dispatch table pointer
3684 if not (Present (Acc_Disp_Tables)) then
3685 Acc_Disp_Tables := New_Elmt_List;
3686 end if;
3688 Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables);
3690 -- Step 1: Generate an Object Specific Data (OSD) table
3692 OSD := Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
3694 -- Nothing to do if configurable run time does not support the
3695 -- Object_Specific_Data entity.
3697 if not RTE_Available (RE_Object_Specific_Data) then
3698 Error_Msg_CRT ("abstract interface types", Typ);
3699 return;
3700 end if;
3702 -- Generate:
3703 -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims);
3704 -- where the constraint is used to allocate space for the
3705 -- non-predefined primitive operations only.
3707 Append_To (Result,
3708 Make_Object_Declaration (Loc,
3709 Defining_Identifier => OSD,
3710 Object_Definition =>
3711 Make_Subtype_Indication (Loc,
3712 Subtype_Mark => New_Reference_To (
3713 RTE (RE_Object_Specific_Data), Loc),
3714 Constraint =>
3715 Make_Index_Or_Discriminant_Constraint (Loc,
3716 Constraints => New_List (
3717 Make_Integer_Literal (Loc, Nb_Prim))))));
3719 Append_To (Result,
3720 Make_DT_Access_Action (Typ,
3721 Action => Set_Signature,
3722 Args => New_List (
3723 Unchecked_Convert_To (RTE (RE_Tag),
3724 New_Reference_To (Iface_DT_Ptr, Loc)),
3725 New_Reference_To (RTE (RE_Secondary_DT), Loc))));
3727 -- Generate:
3728 -- Ada.Tags.Set_OSD (Iface_DT_Ptr, OSD);
3730 Append_To (Result,
3731 Make_DT_Access_Action (Typ,
3732 Action => Set_OSD,
3733 Args => New_List (
3734 Unchecked_Convert_To (RTE (RE_Tag),
3735 New_Reference_To (Iface_DT_Ptr, Loc)),
3736 Make_Attribute_Reference (Loc,
3737 Prefix => New_Reference_To (OSD, Loc),
3738 Attribute_Name => Name_Address))));
3740 -- Generate:
3741 -- Set_Num_Prim_Ops (T'Tag, Nb_Prim)
3743 if RTE_Available (RE_Set_Num_Prim_Ops) then
3744 if Empty_DT then
3745 Append_To (Result,
3746 Make_Procedure_Call_Statement (Loc,
3747 Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc),
3748 Parameter_Associations => New_List (
3749 Unchecked_Convert_To (RTE (RE_Tag),
3750 New_Reference_To (Iface_DT_Ptr, Loc)),
3751 Make_Integer_Literal (Loc, Uint_0))));
3752 else
3753 Append_To (Result,
3754 Make_Procedure_Call_Statement (Loc,
3755 Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc),
3756 Parameter_Associations => New_List (
3757 Unchecked_Convert_To (RTE (RE_Tag),
3758 New_Reference_To (Iface_DT_Ptr, Loc)),
3759 Make_Integer_Literal (Loc, Nb_Prim))));
3760 end if;
3761 end if;
3763 if Ada_Version >= Ada_05
3764 and then not Is_Interface (Typ)
3765 and then not Is_Abstract (Typ)
3766 and then not Is_Controlled (Typ)
3767 and then RTE_Available (RE_Set_Tagged_Kind)
3768 and then not Restriction_Active (No_Dispatching_Calls)
3769 then
3770 -- Generate:
3771 -- Set_Tagged_Kind (Iface'Tag, Tagged_Kind (Iface));
3773 Append_To (Result,
3774 Make_DT_Access_Action (Typ,
3775 Action => Set_Tagged_Kind,
3776 Args => New_List (
3777 Unchecked_Convert_To (RTE (RE_Tag), -- DTptr
3778 New_Reference_To (Iface_DT_Ptr, Loc)),
3779 Tagged_Kind (Typ)))); -- Value
3781 if not Empty_DT
3782 and then Is_Concurrent_Record_Type (Typ)
3783 and then Implements_Interface (
3784 Typ => Typ,
3785 Kind => Any_Limited_Interface,
3786 Check_Parent => True)
3787 then
3788 declare
3789 Prim : Entity_Id;
3790 Prim_Alias : Entity_Id;
3791 Prim_Elmt : Elmt_Id;
3793 begin
3794 -- Step 2: Populate the OSD table
3796 Prim_Alias := Empty;
3797 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3798 while Present (Prim_Elmt) loop
3799 Prim := Node (Prim_Elmt);
3801 if Present (Abstract_Interface_Alias (Prim)) then
3802 Prim_Alias := Abstract_Interface_Alias (Prim);
3803 end if;
3805 if Present (Prim_Alias)
3806 and then Present (First_Entity (Prim_Alias))
3807 and then Etype (First_Entity (Prim_Alias)) = Iface
3808 then
3809 -- Generate:
3810 -- Ada.Tags.Set_Offset_Index (Tag (Iface_DT_Ptr),
3811 -- Secondary_DT_Pos, Primary_DT_pos);
3813 Append_To (Result,
3814 Make_DT_Access_Action (Iface,
3815 Action => Set_Offset_Index,
3816 Args => New_List (
3817 Unchecked_Convert_To (RTE (RE_Tag),
3818 New_Reference_To (Iface_DT_Ptr, Loc)),
3819 Make_Integer_Literal (Loc,
3820 DT_Position (Prim_Alias)),
3821 Make_Integer_Literal (Loc,
3822 DT_Position (Prim)))));
3824 Prim_Alias := Empty;
3825 end if;
3827 Next_Elmt (Prim_Elmt);
3828 end loop;
3829 end;
3830 end if;
3831 end if;
3832 end Make_Secondary_DT;
3834 -------------------------------------
3835 -- Make_Select_Specific_Data_Table --
3836 -------------------------------------
3838 function Make_Select_Specific_Data_Table
3839 (Typ : Entity_Id) return List_Id
3841 Assignments : constant List_Id := New_List;
3842 Loc : constant Source_Ptr := Sloc (Typ);
3844 Conc_Typ : Entity_Id;
3845 Decls : List_Id;
3846 DT_Ptr : Entity_Id;
3847 Prim : Entity_Id;
3848 Prim_Als : Entity_Id;
3849 Prim_Elmt : Elmt_Id;
3850 Prim_Pos : Uint;
3851 Nb_Prim : Int := 0;
3853 type Examined_Array is array (Int range <>) of Boolean;
3855 function Find_Entry_Index (E : Entity_Id) return Uint;
3856 -- Given an entry, find its index in the visible declarations of the
3857 -- corresponding concurrent type of Typ.
3859 ----------------------
3860 -- Find_Entry_Index --
3861 ----------------------
3863 function Find_Entry_Index (E : Entity_Id) return Uint is
3864 Index : Uint := Uint_1;
3865 Subp_Decl : Entity_Id;
3867 begin
3868 if Present (Decls)
3869 and then not Is_Empty_List (Decls)
3870 then
3871 Subp_Decl := First (Decls);
3872 while Present (Subp_Decl) loop
3873 if Nkind (Subp_Decl) = N_Entry_Declaration then
3874 if Defining_Identifier (Subp_Decl) = E then
3875 return Index;
3876 end if;
3878 Index := Index + 1;
3879 end if;
3881 Next (Subp_Decl);
3882 end loop;
3883 end if;
3885 return Uint_0;
3886 end Find_Entry_Index;
3888 -- Start of processing for Make_Select_Specific_Data_Table
3890 begin
3891 pragma Assert (not Restriction_Active (No_Dispatching_Calls));
3893 DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
3895 if Present (Corresponding_Concurrent_Type (Typ)) then
3896 Conc_Typ := Corresponding_Concurrent_Type (Typ);
3898 if Ekind (Conc_Typ) = E_Protected_Type then
3899 Decls := Visible_Declarations (Protected_Definition (
3900 Parent (Conc_Typ)));
3901 else
3902 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
3903 Decls := Visible_Declarations (Task_Definition (
3904 Parent (Conc_Typ)));
3905 end if;
3906 end if;
3908 -- Count the non-predefined primitive operations
3910 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3911 while Present (Prim_Elmt) loop
3912 if not Is_Predefined_Dispatching_Operation (Node (Prim_Elmt)) then
3913 Nb_Prim := Nb_Prim + 1;
3914 end if;
3916 Next_Elmt (Prim_Elmt);
3917 end loop;
3919 declare
3920 Examined : Examined_Array (1 .. Nb_Prim) := (others => False);
3922 begin
3923 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
3924 while Present (Prim_Elmt) loop
3925 Prim := Node (Prim_Elmt);
3926 Prim_Pos := DT_Position (Prim);
3928 if not Is_Predefined_Dispatching_Operation (Prim) then
3929 pragma Assert (UI_To_Int (Prim_Pos) <= Nb_Prim);
3931 if Examined (UI_To_Int (Prim_Pos)) then
3932 goto Continue;
3933 else
3934 Examined (UI_To_Int (Prim_Pos)) := True;
3935 end if;
3937 -- The current primitive overrides an interface-level
3938 -- subprogram
3940 if Present (Abstract_Interface_Alias (Prim)) then
3942 -- Set the primitive operation kind regardless of subprogram
3943 -- type. Generate:
3944 -- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, <position>, <kind>);
3946 Append_To (Assignments,
3947 Make_DT_Access_Action (Typ,
3948 Action =>
3949 Set_Prim_Op_Kind,
3950 Args =>
3951 New_List (
3952 New_Reference_To (DT_Ptr, Loc),
3953 Make_Integer_Literal (Loc, Prim_Pos),
3954 Prim_Op_Kind (Prim, Typ))));
3956 -- Retrieve the root of the alias chain if one is present
3958 if Present (Alias (Prim)) then
3959 Prim_Als := Prim;
3960 while Present (Alias (Prim_Als)) loop
3961 Prim_Als := Alias (Prim_Als);
3962 end loop;
3963 else
3964 Prim_Als := Empty;
3965 end if;
3967 -- In the case of an entry wrapper, set the entry index
3969 if Ekind (Prim) = E_Procedure
3970 and then Present (Prim_Als)
3971 and then Is_Primitive_Wrapper (Prim_Als)
3972 and then Ekind (Wrapped_Entity (Prim_Als)) = E_Entry
3973 then
3975 -- Generate:
3976 -- Ada.Tags.Set_Entry_Index
3977 -- (DT_Ptr, <position>, <index>);
3979 Append_To (Assignments,
3980 Make_DT_Access_Action (Typ,
3981 Action =>
3982 Set_Entry_Index,
3983 Args =>
3984 New_List (
3985 New_Reference_To (DT_Ptr, Loc),
3986 Make_Integer_Literal (Loc, Prim_Pos),
3987 Make_Integer_Literal (Loc,
3988 Find_Entry_Index
3989 (Wrapped_Entity (Prim_Als))))));
3990 end if;
3991 end if;
3992 end if;
3994 <<Continue>>
3996 Next_Elmt (Prim_Elmt);
3997 end loop;
3998 end;
4000 return Assignments;
4001 end Make_Select_Specific_Data_Table;
4003 -----------------------------------
4004 -- Original_View_In_Visible_Part --
4005 -----------------------------------
4007 function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean is
4008 Scop : constant Entity_Id := Scope (Typ);
4010 begin
4011 -- The scope must be a package
4013 if Ekind (Scop) /= E_Package
4014 and then Ekind (Scop) /= E_Generic_Package
4015 then
4016 return False;
4017 end if;
4019 -- A type with a private declaration has a private view declared in
4020 -- the visible part.
4022 if Has_Private_Declaration (Typ) then
4023 return True;
4024 end if;
4026 return List_Containing (Parent (Typ)) =
4027 Visible_Declarations (Specification (Unit_Declaration_Node (Scop)));
4028 end Original_View_In_Visible_Part;
4030 ------------------
4031 -- Prim_Op_Kind --
4032 ------------------
4034 function Prim_Op_Kind
4035 (Prim : Entity_Id;
4036 Typ : Entity_Id) return Node_Id
4038 Full_Typ : Entity_Id := Typ;
4039 Loc : constant Source_Ptr := Sloc (Prim);
4040 Prim_Op : Entity_Id;
4042 begin
4043 -- Retrieve the original primitive operation
4045 Prim_Op := Prim;
4046 while Present (Alias (Prim_Op)) loop
4047 Prim_Op := Alias (Prim_Op);
4048 end loop;
4050 if Ekind (Typ) = E_Record_Type
4051 and then Present (Corresponding_Concurrent_Type (Typ))
4052 then
4053 Full_Typ := Corresponding_Concurrent_Type (Typ);
4054 end if;
4056 if Ekind (Prim_Op) = E_Function then
4058 -- Protected function
4060 if Ekind (Full_Typ) = E_Protected_Type then
4061 return New_Reference_To (RTE (RE_POK_Protected_Function), Loc);
4063 -- Task function
4065 elsif Ekind (Full_Typ) = E_Task_Type then
4066 return New_Reference_To (RTE (RE_POK_Task_Function), Loc);
4068 -- Regular function
4070 else
4071 return New_Reference_To (RTE (RE_POK_Function), Loc);
4072 end if;
4074 else
4075 pragma Assert (Ekind (Prim_Op) = E_Procedure);
4077 if Ekind (Full_Typ) = E_Protected_Type then
4079 -- Protected entry
4081 if Is_Primitive_Wrapper (Prim_Op)
4082 and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry
4083 then
4084 return New_Reference_To (RTE (RE_POK_Protected_Entry), Loc);
4086 -- Protected procedure
4088 else
4089 return New_Reference_To (RTE (RE_POK_Protected_Procedure), Loc);
4090 end if;
4092 elsif Ekind (Full_Typ) = E_Task_Type then
4094 -- Task entry
4096 if Is_Primitive_Wrapper (Prim_Op)
4097 and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry
4098 then
4099 return New_Reference_To (RTE (RE_POK_Task_Entry), Loc);
4101 -- Task "procedure". These are the internally Expander-generated
4102 -- procedures (task body for instance).
4104 else
4105 return New_Reference_To (RTE (RE_POK_Task_Procedure), Loc);
4106 end if;
4108 -- Regular procedure
4110 else
4111 return New_Reference_To (RTE (RE_POK_Procedure), Loc);
4112 end if;
4113 end if;
4114 end Prim_Op_Kind;
4116 -------------------------
4117 -- Set_All_DT_Position --
4118 -------------------------
4120 procedure Set_All_DT_Position (Typ : Entity_Id) is
4121 Parent_Typ : constant Entity_Id := Etype (Typ);
4122 Root_Typ : constant Entity_Id := Root_Type (Typ);
4123 First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ));
4124 The_Tag : constant Entity_Id := First_Tag_Component (Typ);
4126 Adjusted : Boolean := False;
4127 Finalized : Boolean := False;
4129 Count_Prim : Int;
4130 DT_Length : Int;
4131 Nb_Prim : Int;
4132 Parent_EC : Int;
4133 Prim : Entity_Id;
4134 Prim_Elmt : Elmt_Id;
4136 procedure Validate_Position (Prim : Entity_Id);
4137 -- Check that the position assignated to Prim is completely safe
4138 -- (it has not been assigned to a previously defined primitive
4139 -- operation of Typ)
4141 -----------------------
4142 -- Validate_Position --
4143 -----------------------
4145 procedure Validate_Position (Prim : Entity_Id) is
4146 Prim_Elmt : Elmt_Id;
4148 begin
4149 Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
4150 while Present (Prim_Elmt)
4151 and then Node (Prim_Elmt) /= Prim
4152 loop
4153 -- Primitive operations covering abstract interfaces are
4154 -- allocated later
4156 if Present (Abstract_Interface_Alias (Node (Prim_Elmt))) then
4157 null;
4159 -- Predefined dispatching operations are completely safe. They
4160 -- are allocated at fixed positions in a separate table.
4162 elsif Is_Predefined_Dispatching_Operation (Node (Prim_Elmt)) then
4163 null;
4165 -- Aliased subprograms are safe
4167 elsif Present (Alias (Prim)) then
4168 null;
4170 elsif DT_Position (Node (Prim_Elmt)) = DT_Position (Prim) then
4172 -- Handle aliased subprograms
4174 declare
4175 Op_1 : Entity_Id;
4176 Op_2 : Entity_Id;
4178 begin
4179 Op_1 := Node (Prim_Elmt);
4180 loop
4181 if Present (Overridden_Operation (Op_1)) then
4182 Op_1 := Overridden_Operation (Op_1);
4183 elsif Present (Alias (Op_1)) then
4184 Op_1 := Alias (Op_1);
4185 else
4186 exit;
4187 end if;
4188 end loop;
4190 Op_2 := Prim;
4191 loop
4192 if Present (Overridden_Operation (Op_2)) then
4193 Op_2 := Overridden_Operation (Op_2);
4194 elsif Present (Alias (Op_2)) then
4195 Op_2 := Alias (Op_2);
4196 else
4197 exit;
4198 end if;
4199 end loop;
4201 if Op_1 /= Op_2 then
4202 raise Program_Error;
4203 end if;
4204 end;
4205 end if;
4207 Next_Elmt (Prim_Elmt);
4208 end loop;
4209 end Validate_Position;
4211 -- Start of processing for Set_All_DT_Position
4213 begin
4214 -- Get Entry_Count of the parent
4216 if Parent_Typ /= Typ
4217 and then DT_Entry_Count (First_Tag_Component (Parent_Typ)) /= No_Uint
4218 then
4219 Parent_EC := UI_To_Int (DT_Entry_Count
4220 (First_Tag_Component (Parent_Typ)));
4221 else
4222 Parent_EC := 0;
4223 end if;
4225 -- C++ Case, check that pragma CPP_Class, CPP_Virtual and CPP_Vtable
4226 -- give a coherent set of information
4228 if Is_CPP_Class (Root_Typ) then
4230 -- Compute the number of primitive operations in the main Vtable
4231 -- Set their position:
4232 -- - where it was set if overriden or inherited
4233 -- - after the end of the parent vtable otherwise
4235 Prim_Elmt := First_Prim;
4236 Nb_Prim := 0;
4237 while Present (Prim_Elmt) loop
4238 Prim := Node (Prim_Elmt);
4240 if not Is_CPP_Class (Typ) then
4241 Set_DTC_Entity (Prim, The_Tag);
4243 elsif Present (Alias (Prim)) then
4244 Set_DTC_Entity (Prim, DTC_Entity (Alias (Prim)));
4245 Set_DT_Position (Prim, DT_Position (Alias (Prim)));
4247 elsif No (DTC_Entity (Prim)) and then Is_CPP_Class (Typ) then
4248 Error_Msg_NE ("is a primitive operation of&," &
4249 " pragma Cpp_Virtual required", Prim, Typ);
4250 end if;
4252 if DTC_Entity (Prim) = The_Tag then
4254 -- Get the slot from the parent subprogram if any
4256 declare
4257 H : Entity_Id;
4259 begin
4260 H := Homonym (Prim);
4261 while Present (H) loop
4262 if Present (DTC_Entity (H))
4263 and then Root_Type (Scope (DTC_Entity (H))) = Root_Typ
4264 then
4265 Set_DT_Position (Prim, DT_Position (H));
4266 exit;
4267 end if;
4269 H := Homonym (H);
4270 end loop;
4271 end;
4273 -- Otherwise take the canonical slot after the end of the
4274 -- parent Vtable
4276 if DT_Position (Prim) = No_Uint then
4277 Nb_Prim := Nb_Prim + 1;
4278 Set_DT_Position (Prim, UI_From_Int (Parent_EC + Nb_Prim));
4280 elsif UI_To_Int (DT_Position (Prim)) > Parent_EC then
4281 Nb_Prim := Nb_Prim + 1;
4282 end if;
4283 end if;
4285 Next_Elmt (Prim_Elmt);
4286 end loop;
4288 -- Check that the declared size of the Vtable is bigger or equal
4289 -- than the number of primitive operations (if bigger it means that
4290 -- some of the c++ virtual functions were not imported, that is
4291 -- allowed).
4293 if DT_Entry_Count (The_Tag) = No_Uint
4294 or else not Is_CPP_Class (Typ)
4295 then
4296 Set_DT_Entry_Count (The_Tag, UI_From_Int (Parent_EC + Nb_Prim));
4298 elsif UI_To_Int (DT_Entry_Count (The_Tag)) < Parent_EC + Nb_Prim then
4299 Error_Msg_N ("not enough room in the Vtable for all virtual"
4300 & " functions", The_Tag);
4301 end if;
4303 -- Check that Positions are not duplicate nor outside the range of
4304 -- the Vtable.
4306 declare
4307 Size : constant Int := UI_To_Int (DT_Entry_Count (The_Tag));
4308 Pos : Int;
4309 Prim_Pos_Table : array (1 .. Size) of Entity_Id :=
4310 (others => Empty);
4312 begin
4313 Prim_Elmt := First_Prim;
4314 while Present (Prim_Elmt) loop
4315 Prim := Node (Prim_Elmt);
4317 if DTC_Entity (Prim) = The_Tag then
4318 Pos := UI_To_Int (DT_Position (Prim));
4320 if Pos not in Prim_Pos_Table'Range then
4321 Error_Msg_N
4322 ("position not in range of virtual table", Prim);
4324 elsif Present (Prim_Pos_Table (Pos)) then
4325 Error_Msg_NE ("cannot be at the same position in the"
4326 & " vtable than&", Prim, Prim_Pos_Table (Pos));
4328 else
4329 Prim_Pos_Table (Pos) := Prim;
4330 end if;
4331 end if;
4333 Next_Elmt (Prim_Elmt);
4334 end loop;
4335 end;
4337 -- Generate listing showing the contents of the dispatch tables
4339 if Debug_Flag_ZZ then
4340 Write_DT (Typ);
4341 end if;
4343 -- For regular Ada tagged types, just set the DT_Position for
4344 -- each primitive operation. Perform some sanity checks to avoid
4345 -- to build completely inconsistant dispatch tables.
4347 -- Note that the _Size primitive is always set at position 1 in order
4348 -- to comply with the needs of Ada.Tags.Parent_Size (see documentation
4349 -- in Ada.Tags).
4351 else
4352 -- First stage: Set the DTC entity of all the primitive operations
4353 -- This is required to properly read the DT_Position attribute in
4354 -- the latter stages.
4356 Prim_Elmt := First_Prim;
4357 Count_Prim := 0;
4358 while Present (Prim_Elmt) loop
4359 Count_Prim := Count_Prim + 1;
4360 Prim := Node (Prim_Elmt);
4362 -- Ada 2005 (AI-251)
4364 if Present (Abstract_Interface_Alias (Prim))
4365 and then Is_Interface (Scope (DTC_Entity
4366 (Abstract_Interface_Alias (Prim))))
4367 then
4368 Set_DTC_Entity (Prim,
4369 Find_Interface_Tag
4370 (T => Typ,
4371 Iface => Scope (DTC_Entity
4372 (Abstract_Interface_Alias (Prim)))));
4374 else
4375 Set_DTC_Entity (Prim, The_Tag);
4376 end if;
4378 -- Clear any previous value of the DT_Position attribute. In this
4379 -- way we ensure that the final position of all the primitives is
4380 -- stablished by the following stages of this algorithm.
4382 Set_DT_Position (Prim, No_Uint);
4384 Next_Elmt (Prim_Elmt);
4385 end loop;
4387 declare
4388 Fixed_Prim : array (Int range 0 .. Parent_EC + Count_Prim)
4389 of Boolean := (others => False);
4391 E : Entity_Id;
4393 begin
4394 -- Second stage: Register fixed entries
4396 Nb_Prim := 0;
4397 Prim_Elmt := First_Prim;
4398 while Present (Prim_Elmt) loop
4399 Prim := Node (Prim_Elmt);
4401 -- Predefined primitives have a separate table and all its
4402 -- entries are at predefined fixed positions
4404 if Is_Predefined_Dispatching_Operation (Prim) then
4405 Set_DT_Position (Prim, Default_Prim_Op_Position (Prim));
4407 -- Overriding interface primitives of an ancestor
4409 elsif DT_Position (Prim) = No_Uint
4410 and then Present (Abstract_Interface_Alias (Prim))
4411 and then Present (DTC_Entity
4412 (Abstract_Interface_Alias (Prim)))
4413 and then DT_Position (Abstract_Interface_Alias (Prim))
4414 /= No_Uint
4415 and then Is_Inherited_Operation (Prim)
4416 and then Is_Ancestor (Scope
4417 (DTC_Entity
4418 (Abstract_Interface_Alias (Prim))),
4419 Typ)
4420 then
4421 Set_DT_Position (Prim,
4422 DT_Position (Abstract_Interface_Alias (Prim)));
4423 Set_DT_Position (Alias (Prim),
4424 DT_Position (Abstract_Interface_Alias (Prim)));
4425 Fixed_Prim (UI_To_Int (DT_Position (Prim))) := True;
4427 -- Overriding primitives must use the same entry as the
4428 -- overriden primitive
4430 elsif DT_Position (Prim) = No_Uint
4431 and then Present (Alias (Prim))
4432 and then Present (DTC_Entity (Alias (Prim)))
4433 and then DT_Position (Alias (Prim)) /= No_Uint
4434 and then Is_Inherited_Operation (Prim)
4435 and then Is_Ancestor (Scope (DTC_Entity (Alias (Prim))), Typ)
4436 then
4437 E := Alias (Prim);
4438 while not (Present (DTC_Entity (E))
4439 or else DT_Position (E) = No_Uint)
4440 and then Present (Alias (E))
4441 loop
4442 E := Alias (E);
4443 end loop;
4445 pragma Assert (Present (DTC_Entity (E))
4446 and then
4447 DT_Position (E) /= No_Uint);
4449 Set_DT_Position (Prim, DT_Position (E));
4450 Fixed_Prim (UI_To_Int (DT_Position (E))) := True;
4452 -- If this is not the last element in the chain continue
4453 -- traversing the chain. This is required to properly
4454 -- handling renamed primitives
4456 while Present (Alias (E)) loop
4457 E := Alias (E);
4458 Fixed_Prim (UI_To_Int (DT_Position (E))) := True;
4459 end loop;
4460 end if;
4462 Next_Elmt (Prim_Elmt);
4463 end loop;
4465 -- Third stage: Fix the position of all the new primitives
4466 -- Entries associated with primitives covering interfaces
4467 -- are handled in a latter round.
4469 Prim_Elmt := First_Prim;
4470 while Present (Prim_Elmt) loop
4471 Prim := Node (Prim_Elmt);
4473 -- Skip primitives previously set entries
4475 if Is_Predefined_Dispatching_Operation (Prim) then
4476 null;
4478 elsif DT_Position (Prim) /= No_Uint then
4479 null;
4481 elsif Etype (DTC_Entity (Prim)) /= RTE (RE_Tag) then
4482 null;
4484 -- Primitives covering interface primitives are
4485 -- handled later
4487 elsif Present (Abstract_Interface_Alias (Prim)) then
4488 null;
4490 else
4491 -- Take the next available position in the DT
4493 loop
4494 Nb_Prim := Nb_Prim + 1;
4495 exit when not Fixed_Prim (Nb_Prim);
4496 end loop;
4498 Set_DT_Position (Prim, UI_From_Int (Nb_Prim));
4499 Fixed_Prim (Nb_Prim) := True;
4500 end if;
4502 Next_Elmt (Prim_Elmt);
4503 end loop;
4504 end;
4506 -- Fourth stage: Complete the decoration of primitives covering
4507 -- interfaces (that is, propagate the DT_Position attribute
4508 -- from the aliased primitive)
4510 Prim_Elmt := First_Prim;
4511 while Present (Prim_Elmt) loop
4512 Prim := Node (Prim_Elmt);
4514 if DT_Position (Prim) = No_Uint
4515 and then Present (Abstract_Interface_Alias (Prim))
4516 then
4517 -- Check if this entry will be placed in the primary DT
4519 if Etype (DTC_Entity (Abstract_Interface_Alias (Prim)))
4520 = RTE (RE_Tag)
4521 then
4522 pragma Assert (DT_Position (Alias (Prim)) /= No_Uint);
4523 Set_DT_Position (Prim, DT_Position (Alias (Prim)));
4525 -- Otherwise it will be placed in the secondary DT
4527 else
4528 pragma Assert
4529 (DT_Position (Abstract_Interface_Alias (Prim)) /= No_Uint);
4531 Set_DT_Position (Prim,
4532 DT_Position (Abstract_Interface_Alias (Prim)));
4533 end if;
4534 end if;
4536 Next_Elmt (Prim_Elmt);
4537 end loop;
4539 -- Generate listing showing the contents of the dispatch tables.
4540 -- This action is done before some further static checks because
4541 -- in case of critical errors caused by a wrong dispatch table
4542 -- we need to see the contents of such table.
4544 if Debug_Flag_ZZ then
4545 Write_DT (Typ);
4546 end if;
4548 -- Final stage: Ensure that the table is correct plus some further
4549 -- verifications concerning the primitives.
4551 Prim_Elmt := First_Prim;
4552 DT_Length := 0;
4553 while Present (Prim_Elmt) loop
4554 Prim := Node (Prim_Elmt);
4556 -- At this point all the primitives MUST have a position
4557 -- in the dispatch table
4559 if DT_Position (Prim) = No_Uint then
4560 raise Program_Error;
4561 end if;
4563 -- Calculate real size of the dispatch table
4565 if not Is_Predefined_Dispatching_Operation (Prim)
4566 and then UI_To_Int (DT_Position (Prim)) > DT_Length
4567 then
4568 DT_Length := UI_To_Int (DT_Position (Prim));
4569 end if;
4571 -- Ensure that the asignated position to non-predefined
4572 -- dispatching operations in the dispatch table is correct.
4574 if not Is_Predefined_Dispatching_Operation (Prim) then
4575 Validate_Position (Prim);
4576 end if;
4578 if Chars (Prim) = Name_Finalize then
4579 Finalized := True;
4580 end if;
4582 if Chars (Prim) = Name_Adjust then
4583 Adjusted := True;
4584 end if;
4586 -- An abstract operation cannot be declared in the private part
4587 -- for a visible abstract type, because it could never be over-
4588 -- ridden. For explicit declarations this is checked at the
4589 -- point of declaration, but for inherited operations it must
4590 -- be done when building the dispatch table. Input is excluded
4591 -- because
4593 if Is_Abstract (Typ)
4594 and then Is_Abstract (Prim)
4595 and then Present (Alias (Prim))
4596 and then Is_Derived_Type (Typ)
4597 and then In_Private_Part (Current_Scope)
4598 and then
4599 List_Containing (Parent (Prim)) =
4600 Private_Declarations
4601 (Specification (Unit_Declaration_Node (Current_Scope)))
4602 and then Original_View_In_Visible_Part (Typ)
4603 then
4604 -- We exclude Input and Output stream operations because
4605 -- Limited_Controlled inherits useless Input and Output
4606 -- stream operations from Root_Controlled, which can
4607 -- never be overridden.
4609 if not Is_TSS (Prim, TSS_Stream_Input)
4610 and then
4611 not Is_TSS (Prim, TSS_Stream_Output)
4612 then
4613 Error_Msg_NE
4614 ("abstract inherited private operation&" &
4615 " must be overridden ('R'M 3.9.3(10))",
4616 Parent (Typ), Prim);
4617 end if;
4618 end if;
4620 Next_Elmt (Prim_Elmt);
4621 end loop;
4623 -- Additional check
4625 if Is_Controlled (Typ) then
4626 if not Finalized then
4627 Error_Msg_N
4628 ("controlled type has no explicit Finalize method?", Typ);
4630 elsif not Adjusted then
4631 Error_Msg_N
4632 ("controlled type has no explicit Adjust method?", Typ);
4633 end if;
4634 end if;
4636 -- Set the final size of the Dispatch Table
4638 Set_DT_Entry_Count (The_Tag, UI_From_Int (DT_Length));
4640 -- The derived type must have at least as many components as its
4641 -- parent (for root types, the Etype points back to itself
4642 -- and the test should not fail)
4644 -- This test fails compiling the partial view of a tagged type
4645 -- derived from an interface which defines the overriding subprogram
4646 -- in the private part. This needs further investigation???
4648 if not Has_Private_Declaration (Typ) then
4649 pragma Assert (
4650 DT_Entry_Count (The_Tag) >=
4651 DT_Entry_Count (First_Tag_Component (Parent_Typ)));
4652 null;
4653 end if;
4654 end if;
4655 end Set_All_DT_Position;
4657 -----------------------------
4658 -- Set_Default_Constructor --
4659 -----------------------------
4661 procedure Set_Default_Constructor (Typ : Entity_Id) is
4662 Loc : Source_Ptr;
4663 Init : Entity_Id;
4664 Param : Entity_Id;
4665 E : Entity_Id;
4667 begin
4668 -- Look for the default constructor entity. For now only the
4669 -- default constructor has the flag Is_Constructor.
4671 E := Next_Entity (Typ);
4672 while Present (E)
4673 and then (Ekind (E) /= E_Function or else not Is_Constructor (E))
4674 loop
4675 Next_Entity (E);
4676 end loop;
4678 -- Create the init procedure
4680 if Present (E) then
4681 Loc := Sloc (E);
4682 Init := Make_Defining_Identifier (Loc, Make_Init_Proc_Name (Typ));
4683 Param := Make_Defining_Identifier (Loc, Name_X);
4685 Discard_Node (
4686 Make_Subprogram_Declaration (Loc,
4687 Make_Procedure_Specification (Loc,
4688 Defining_Unit_Name => Init,
4689 Parameter_Specifications => New_List (
4690 Make_Parameter_Specification (Loc,
4691 Defining_Identifier => Param,
4692 Parameter_Type => New_Reference_To (Typ, Loc))))));
4694 Set_Init_Proc (Typ, Init);
4695 Set_Is_Imported (Init);
4696 Set_Interface_Name (Init, Interface_Name (E));
4697 Set_Convention (Init, Convention_C);
4698 Set_Is_Public (Init);
4699 Set_Has_Completion (Init);
4701 -- If there are no constructors, mark the type as abstract since we
4702 -- won't be able to declare objects of that type.
4704 else
4705 Set_Is_Abstract (Typ);
4706 end if;
4707 end Set_Default_Constructor;
4709 -----------------
4710 -- Tagged_Kind --
4711 -----------------
4713 function Tagged_Kind (T : Entity_Id) return Node_Id is
4714 Conc_Typ : Entity_Id;
4715 Loc : constant Source_Ptr := Sloc (T);
4717 begin
4718 pragma Assert
4719 (Is_Tagged_Type (T) and then RTE_Available (RE_Tagged_Kind));
4721 -- Abstract kinds
4723 if Is_Abstract (T) then
4724 if Is_Limited_Record (T) then
4725 return New_Reference_To (RTE (RE_TK_Abstract_Limited_Tagged), Loc);
4726 else
4727 return New_Reference_To (RTE (RE_TK_Abstract_Tagged), Loc);
4728 end if;
4730 -- Concurrent kinds
4732 elsif Is_Concurrent_Record_Type (T) then
4733 Conc_Typ := Corresponding_Concurrent_Type (T);
4735 if Ekind (Conc_Typ) = E_Protected_Type then
4736 return New_Reference_To (RTE (RE_TK_Protected), Loc);
4737 else
4738 pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
4739 return New_Reference_To (RTE (RE_TK_Task), Loc);
4740 end if;
4742 -- Regular tagged kinds
4744 else
4745 if Is_Limited_Record (T) then
4746 return New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc);
4747 else
4748 return New_Reference_To (RTE (RE_TK_Tagged), Loc);
4749 end if;
4750 end if;
4751 end Tagged_Kind;
4753 --------------
4754 -- Write_DT --
4755 --------------
4757 procedure Write_DT (Typ : Entity_Id) is
4758 Elmt : Elmt_Id;
4759 Prim : Node_Id;
4761 begin
4762 -- Protect this procedure against wrong usage. Required because it will
4763 -- be used directly from GDB
4765 if not (Typ in First_Node_Id .. Last_Node_Id)
4766 or else not Is_Tagged_Type (Typ)
4767 then
4768 Write_Str ("wrong usage: Write_DT must be used with tagged types");
4769 Write_Eol;
4770 return;
4771 end if;
4773 Write_Int (Int (Typ));
4774 Write_Str (": ");
4775 Write_Name (Chars (Typ));
4777 if Is_Interface (Typ) then
4778 Write_Str (" is interface");
4779 end if;
4781 Write_Eol;
4783 Elmt := First_Elmt (Primitive_Operations (Typ));
4784 while Present (Elmt) loop
4785 Prim := Node (Elmt);
4786 Write_Str (" - ");
4788 -- Indicate if this primitive will be allocated in the primary
4789 -- dispatch table or in a secondary dispatch table associated
4790 -- with an abstract interface type
4792 if Present (DTC_Entity (Prim)) then
4793 if Etype (DTC_Entity (Prim)) = RTE (RE_Tag) then
4794 Write_Str ("[P] ");
4795 else
4796 Write_Str ("[s] ");
4797 end if;
4798 end if;
4800 -- Output the node of this primitive operation and its name
4802 Write_Int (Int (Prim));
4803 Write_Str (": ");
4805 if Is_Predefined_Dispatching_Operation (Prim) then
4806 Write_Str ("(predefined) ");
4807 end if;
4809 Write_Name (Chars (Prim));
4811 -- Indicate if this primitive has an aliased primitive
4813 if Present (Alias (Prim)) then
4814 Write_Str (" (alias = ");
4815 Write_Int (Int (Alias (Prim)));
4817 -- If the DTC_Entity attribute is already set we can also output
4818 -- the name of the interface covered by this primitive (if any)
4820 if Present (DTC_Entity (Alias (Prim)))
4821 and then Is_Interface (Scope (DTC_Entity (Alias (Prim))))
4822 then
4823 Write_Str (" from interface ");
4824 Write_Name (Chars (Scope (DTC_Entity (Alias (Prim)))));
4825 end if;
4827 if Present (Abstract_Interface_Alias (Prim)) then
4828 Write_Str (", AI_Alias of ");
4829 Write_Name (Chars (Scope (DTC_Entity
4830 (Abstract_Interface_Alias (Prim)))));
4831 Write_Char (':');
4832 Write_Int (Int (Abstract_Interface_Alias (Prim)));
4833 end if;
4835 Write_Str (")");
4836 end if;
4838 -- Display the final position of this primitive in its associated
4839 -- (primary or secondary) dispatch table
4841 if Present (DTC_Entity (Prim))
4842 and then DT_Position (Prim) /= No_Uint
4843 then
4844 Write_Str (" at #");
4845 Write_Int (UI_To_Int (DT_Position (Prim)));
4846 end if;
4848 if Is_Abstract (Prim) then
4849 Write_Str (" is abstract;");
4850 end if;
4852 Write_Eol;
4854 Next_Elmt (Elmt);
4855 end loop;
4856 end Write_DT;
4858 end Exp_Disp;