]>
Commit | Line | Data |
---|---|---|
ee6ba406 | 1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3 | -- GNAT COMPILER COMPONENTS -- | |
4 | -- -- | |
5 | -- E X P _ D I S P -- | |
6 | -- -- | |
7 | -- B o d y -- | |
8 | -- -- | |
68f95949 | 9 | -- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- |
ee6ba406 | 10 | -- -- |
11 | -- GNAT is free software; you can redistribute it and/or modify it under -- | |
12 | -- terms of the GNU General Public License as published by the Free Soft- -- | |
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 -- | |
f27cea3a | 19 | -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- |
20 | -- Boston, MA 02110-1301, USA. -- | |
ee6ba406 | 21 | -- -- |
22 | -- GNAT was originally developed by the GNAT team at New York University. -- | |
e78e8c8e | 23 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
ee6ba406 | 24 | -- -- |
25 | ------------------------------------------------------------------------------ | |
26 | ||
27 | with Atree; use Atree; | |
28 | with Checks; use Checks; | |
aad6babd | 29 | with Debug; use Debug; |
ee6ba406 | 30 | with Einfo; use Einfo; |
31 | with Elists; use Elists; | |
32 | with Errout; use Errout; | |
343d35dc | 33 | with Exp_Atag; use Exp_Atag; |
ee6ba406 | 34 | with Exp_Ch7; use Exp_Ch7; |
76a1c25b | 35 | with Exp_Dbug; use Exp_Dbug; |
ee6ba406 | 36 | with Exp_Tss; use Exp_Tss; |
37 | with Exp_Util; use Exp_Util; | |
af647dc7 | 38 | with Freeze; use Freeze; |
ee6ba406 | 39 | with Itypes; use Itypes; |
ee6ba406 | 40 | with Nlists; use Nlists; |
41 | with Nmake; use Nmake; | |
aad6babd | 42 | with Namet; use Namet; |
ee6ba406 | 43 | with Opt; use Opt; |
aad6babd | 44 | with Output; use Output; |
68f95949 | 45 | with Restrict; use Restrict; |
46 | with Rident; use Rident; | |
ee6ba406 | 47 | with Rtsfind; use Rtsfind; |
aad6babd | 48 | with Sem; use Sem; |
ee6ba406 | 49 | with Sem_Disp; use Sem_Disp; |
50 | with Sem_Res; use Sem_Res; | |
aad6babd | 51 | with Sem_Type; use Sem_Type; |
ee6ba406 | 52 | with Sem_Util; use Sem_Util; |
53 | with Sinfo; use Sinfo; | |
54 | with Snames; use Snames; | |
55 | with Stand; use Stand; | |
56 | with Tbuild; use Tbuild; | |
57 | with Uintp; use Uintp; | |
58 | ||
59 | package body Exp_Disp is | |
60 | ||
d62940bf | 61 | -------------------------------- |
62 | -- Select_Expansion_Utilities -- | |
63 | -------------------------------- | |
64 | ||
65 | -- The following package contains helper routines used in the expansion of | |
66 | -- dispatching asynchronous, conditional and timed selects. | |
67 | ||
68 | package Select_Expansion_Utilities is | |
69 | procedure Build_B | |
70 | (Loc : Source_Ptr; | |
71 | Params : List_Id); | |
72 | -- Generate: | |
73 | -- B : out Communication_Block | |
74 | ||
75 | procedure Build_C | |
76 | (Loc : Source_Ptr; | |
77 | Params : List_Id); | |
78 | -- Generate: | |
79 | -- C : out Prim_Op_Kind | |
80 | ||
81 | procedure Build_Common_Dispatching_Select_Statements | |
76a1c25b | 82 | (Loc : Source_Ptr; |
83 | Typ : Entity_Id; | |
84 | DT_Ptr : Entity_Id; | |
85 | Stmts : List_Id); | |
d62940bf | 86 | -- Ada 2005 (AI-345): Generate statements that are common between |
87 | -- asynchronous, conditional and timed select expansion. | |
88 | ||
89 | procedure Build_F | |
90 | (Loc : Source_Ptr; | |
91 | Params : List_Id); | |
92 | -- Generate: | |
93 | -- F : out Boolean | |
94 | ||
95 | procedure Build_P | |
96 | (Loc : Source_Ptr; | |
97 | Params : List_Id); | |
98 | -- Generate: | |
99 | -- P : Address | |
100 | ||
101 | procedure Build_S | |
102 | (Loc : Source_Ptr; | |
103 | Params : List_Id); | |
104 | -- Generate: | |
105 | -- S : Integer | |
106 | ||
107 | procedure Build_T | |
108 | (Loc : Source_Ptr; | |
109 | Typ : Entity_Id; | |
110 | Params : List_Id); | |
111 | -- Generate: | |
112 | -- T : in out Typ | |
113 | end Select_Expansion_Utilities; | |
114 | ||
115 | package body Select_Expansion_Utilities is | |
116 | ||
117 | ------------- | |
118 | -- Build_B -- | |
119 | ------------- | |
120 | ||
121 | procedure Build_B | |
122 | (Loc : Source_Ptr; | |
123 | Params : List_Id) | |
124 | is | |
125 | begin | |
126 | Append_To (Params, | |
127 | Make_Parameter_Specification (Loc, | |
128 | Defining_Identifier => | |
129 | Make_Defining_Identifier (Loc, Name_uB), | |
130 | Parameter_Type => | |
131 | New_Reference_To (RTE (RE_Communication_Block), Loc), | |
132 | Out_Present => True)); | |
133 | end Build_B; | |
134 | ||
135 | ------------- | |
136 | -- Build_C -- | |
137 | ------------- | |
138 | ||
139 | procedure Build_C | |
140 | (Loc : Source_Ptr; | |
141 | Params : List_Id) | |
142 | is | |
143 | begin | |
144 | Append_To (Params, | |
145 | Make_Parameter_Specification (Loc, | |
146 | Defining_Identifier => | |
147 | Make_Defining_Identifier (Loc, Name_uC), | |
148 | Parameter_Type => | |
149 | New_Reference_To (RTE (RE_Prim_Op_Kind), Loc), | |
150 | Out_Present => True)); | |
151 | end Build_C; | |
152 | ||
153 | ------------------------------------------------ | |
154 | -- Build_Common_Dispatching_Select_Statements -- | |
155 | ------------------------------------------------ | |
156 | ||
157 | procedure Build_Common_Dispatching_Select_Statements | |
343d35dc | 158 | (Loc : Source_Ptr; |
159 | Typ : Entity_Id; | |
76a1c25b | 160 | DT_Ptr : Entity_Id; |
343d35dc | 161 | Stmts : List_Id) |
d62940bf | 162 | is |
d62940bf | 163 | begin |
d62940bf | 164 | -- Generate: |
165 | -- C := get_prim_op_kind (tag! (<type>VP), S); | |
166 | ||
167 | -- where C is the out parameter capturing the call kind and S is the | |
168 | -- dispatch table slot number. | |
169 | ||
170 | Append_To (Stmts, | |
171 | Make_Assignment_Statement (Loc, | |
172 | Name => | |
173 | Make_Identifier (Loc, Name_uC), | |
174 | Expression => | |
175 | Make_DT_Access_Action (Typ, | |
176 | Action => | |
177 | Get_Prim_Op_Kind, | |
178 | Args => | |
179 | New_List ( | |
180 | Unchecked_Convert_To (RTE (RE_Tag), | |
181 | New_Reference_To (DT_Ptr, Loc)), | |
182 | Make_Identifier (Loc, Name_uS))))); | |
183 | ||
184 | -- Generate: | |
76a1c25b | 185 | |
d62940bf | 186 | -- if C = POK_Procedure |
187 | -- or else C = POK_Protected_Procedure | |
188 | -- or else C = POK_Task_Procedure; | |
189 | -- then | |
190 | -- F := True; | |
191 | -- return; | |
192 | ||
193 | -- where F is the out parameter capturing the status of a potential | |
194 | -- entry call. | |
195 | ||
196 | Append_To (Stmts, | |
197 | Make_If_Statement (Loc, | |
198 | ||
199 | Condition => | |
200 | Make_Or_Else (Loc, | |
201 | Left_Opnd => | |
202 | Make_Op_Eq (Loc, | |
203 | Left_Opnd => | |
204 | Make_Identifier (Loc, Name_uC), | |
205 | Right_Opnd => | |
206 | New_Reference_To (RTE (RE_POK_Procedure), Loc)), | |
207 | Right_Opnd => | |
208 | Make_Or_Else (Loc, | |
209 | Left_Opnd => | |
210 | Make_Op_Eq (Loc, | |
211 | Left_Opnd => | |
212 | Make_Identifier (Loc, Name_uC), | |
213 | Right_Opnd => | |
214 | New_Reference_To (RTE ( | |
215 | RE_POK_Protected_Procedure), Loc)), | |
216 | Right_Opnd => | |
217 | Make_Op_Eq (Loc, | |
218 | Left_Opnd => | |
219 | Make_Identifier (Loc, Name_uC), | |
220 | Right_Opnd => | |
221 | New_Reference_To (RTE ( | |
222 | RE_POK_Task_Procedure), Loc)))), | |
223 | ||
224 | Then_Statements => | |
225 | New_List ( | |
226 | Make_Assignment_Statement (Loc, | |
227 | Name => Make_Identifier (Loc, Name_uF), | |
228 | Expression => New_Reference_To (Standard_True, Loc)), | |
229 | ||
230 | Make_Return_Statement (Loc)))); | |
231 | end Build_Common_Dispatching_Select_Statements; | |
232 | ||
233 | ------------- | |
234 | -- Build_F -- | |
235 | ------------- | |
236 | ||
237 | procedure Build_F | |
238 | (Loc : Source_Ptr; | |
239 | Params : List_Id) | |
240 | is | |
241 | begin | |
242 | Append_To (Params, | |
243 | Make_Parameter_Specification (Loc, | |
244 | Defining_Identifier => | |
245 | Make_Defining_Identifier (Loc, Name_uF), | |
246 | Parameter_Type => | |
247 | New_Reference_To (Standard_Boolean, Loc), | |
248 | Out_Present => True)); | |
249 | end Build_F; | |
250 | ||
251 | ------------- | |
252 | -- Build_P -- | |
253 | ------------- | |
254 | ||
255 | procedure Build_P | |
256 | (Loc : Source_Ptr; | |
257 | Params : List_Id) | |
258 | is | |
259 | begin | |
260 | Append_To (Params, | |
261 | Make_Parameter_Specification (Loc, | |
262 | Defining_Identifier => | |
263 | Make_Defining_Identifier (Loc, Name_uP), | |
264 | Parameter_Type => | |
265 | New_Reference_To (RTE (RE_Address), Loc))); | |
266 | end Build_P; | |
267 | ||
268 | ------------- | |
269 | -- Build_S -- | |
270 | ------------- | |
271 | ||
272 | procedure Build_S | |
273 | (Loc : Source_Ptr; | |
274 | Params : List_Id) | |
275 | is | |
276 | begin | |
277 | Append_To (Params, | |
278 | Make_Parameter_Specification (Loc, | |
279 | Defining_Identifier => | |
280 | Make_Defining_Identifier (Loc, Name_uS), | |
281 | Parameter_Type => | |
282 | New_Reference_To (Standard_Integer, Loc))); | |
283 | end Build_S; | |
284 | ||
285 | ------------- | |
286 | -- Build_T -- | |
287 | ------------- | |
288 | ||
289 | procedure Build_T | |
290 | (Loc : Source_Ptr; | |
291 | Typ : Entity_Id; | |
292 | Params : List_Id) | |
293 | is | |
294 | begin | |
295 | Append_To (Params, | |
296 | Make_Parameter_Specification (Loc, | |
297 | Defining_Identifier => | |
298 | Make_Defining_Identifier (Loc, Name_uT), | |
299 | Parameter_Type => | |
300 | New_Reference_To (Typ, Loc), | |
301 | In_Present => True, | |
302 | Out_Present => True)); | |
303 | end Build_T; | |
304 | end Select_Expansion_Utilities; | |
305 | ||
306 | package SEU renames Select_Expansion_Utilities; | |
307 | ||
ee6ba406 | 308 | Ada_Actions : constant array (DT_Access_Action) of RE_Id := |
343d35dc | 309 | (IW_Membership => RE_IW_Membership, |
68f95949 | 310 | Get_Entry_Index => RE_Get_Entry_Index, |
68f95949 | 311 | Get_Prim_Op_Kind => RE_Get_Prim_Op_Kind, |
68f95949 | 312 | Get_Tagged_Kind => RE_Get_Tagged_Kind, |
68f95949 | 313 | Register_Interface_Tag => RE_Register_Interface_Tag, |
314 | Register_Tag => RE_Register_Tag, | |
68f95949 | 315 | Set_Entry_Index => RE_Set_Entry_Index, |
68f95949 | 316 | Set_Offset_Index => RE_Set_Offset_Index, |
317 | Set_OSD => RE_Set_OSD, | |
68f95949 | 318 | Set_Prim_Op_Kind => RE_Set_Prim_Op_Kind, |
68f95949 | 319 | Set_Signature => RE_Set_Signature, |
320 | Set_SSD => RE_Set_SSD, | |
343d35dc | 321 | Set_Tagged_Kind => RE_Set_Tagged_Kind); |
ee6ba406 | 322 | |
ee6ba406 | 323 | Action_Is_Proc : constant array (DT_Access_Action) of Boolean := |
343d35dc | 324 | (IW_Membership => False, |
68f95949 | 325 | Get_Entry_Index => False, |
68f95949 | 326 | Get_Prim_Op_Kind => False, |
68f95949 | 327 | Get_Tagged_Kind => False, |
68f95949 | 328 | Register_Interface_Tag => True, |
329 | Register_Tag => True, | |
68f95949 | 330 | Set_Entry_Index => True, |
68f95949 | 331 | Set_Offset_Index => True, |
332 | Set_OSD => True, | |
68f95949 | 333 | Set_Prim_Op_Kind => True, |
68f95949 | 334 | Set_Signature => True, |
335 | Set_SSD => True, | |
343d35dc | 336 | Set_Tagged_Kind => True); |
ee6ba406 | 337 | |
338 | Action_Nb_Arg : constant array (DT_Access_Action) of Int := | |
343d35dc | 339 | (IW_Membership => 2, |
68f95949 | 340 | Get_Entry_Index => 2, |
68f95949 | 341 | Get_Prim_Op_Kind => 2, |
68f95949 | 342 | Get_Tagged_Kind => 1, |
68f95949 | 343 | Register_Interface_Tag => 3, |
344 | Register_Tag => 1, | |
68f95949 | 345 | Set_Entry_Index => 3, |
68f95949 | 346 | Set_Offset_Index => 3, |
347 | Set_OSD => 2, | |
68f95949 | 348 | Set_Prim_Op_Kind => 3, |
68f95949 | 349 | Set_Signature => 2, |
350 | Set_SSD => 2, | |
343d35dc | 351 | Set_Tagged_Kind => 2); |
ee6ba406 | 352 | |
68f95949 | 353 | function Default_Prim_Op_Position (E : Entity_Id) return Uint; |
aad6babd | 354 | -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table |
355 | -- of the default primitive operations. | |
356 | ||
af647dc7 | 357 | function Is_Predefined_Dispatching_Alias (Prim : Entity_Id) return Boolean; |
358 | -- Returns true if Prim is not a predefined dispatching primitive but it is | |
359 | -- an alias of a predefined dispatching primitive (ie. through a renaming) | |
360 | ||
ee6ba406 | 361 | function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean; |
362 | -- Check if the type has a private view or if the public view appears | |
363 | -- in the visible part of a package spec. | |
364 | ||
d62940bf | 365 | function Prim_Op_Kind |
366 | (Prim : Entity_Id; | |
367 | Typ : Entity_Id) return Node_Id; | |
368 | -- Ada 2005 (AI-345): Determine the primitive operation kind of Prim | |
952af0b9 | 369 | -- according to its type Typ. Return a reference to an RE_Prim_Op_Kind |
d62940bf | 370 | -- enumeration value. |
aad6babd | 371 | |
952af0b9 | 372 | function Tagged_Kind (T : Entity_Id) return Node_Id; |
373 | -- Ada 2005 (AI-345): Determine the tagged kind of T and return a reference | |
374 | -- to an RE_Tagged_Kind enumeration value. | |
375 | ||
aad6babd | 376 | ------------------------------ |
377 | -- Default_Prim_Op_Position -- | |
378 | ------------------------------ | |
379 | ||
68f95949 | 380 | function Default_Prim_Op_Position (E : Entity_Id) return Uint is |
aad6babd | 381 | TSS_Name : TSS_Name_Type; |
aad6babd | 382 | |
383 | begin | |
aad6babd | 384 | Get_Name_String (Chars (E)); |
385 | TSS_Name := | |
386 | TSS_Name_Type | |
387 | (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len)); | |
388 | ||
389 | if Chars (E) = Name_uSize then | |
390 | return Uint_1; | |
391 | ||
392 | elsif Chars (E) = Name_uAlignment then | |
393 | return Uint_2; | |
394 | ||
395 | elsif TSS_Name = TSS_Stream_Read then | |
396 | return Uint_3; | |
397 | ||
398 | elsif TSS_Name = TSS_Stream_Write then | |
399 | return Uint_4; | |
400 | ||
401 | elsif TSS_Name = TSS_Stream_Input then | |
402 | return Uint_5; | |
403 | ||
404 | elsif TSS_Name = TSS_Stream_Output then | |
405 | return Uint_6; | |
406 | ||
407 | elsif Chars (E) = Name_Op_Eq then | |
408 | return Uint_7; | |
409 | ||
410 | elsif Chars (E) = Name_uAssign then | |
411 | return Uint_8; | |
412 | ||
413 | elsif TSS_Name = TSS_Deep_Adjust then | |
414 | return Uint_9; | |
415 | ||
416 | elsif TSS_Name = TSS_Deep_Finalize then | |
417 | return Uint_10; | |
418 | ||
76a1c25b | 419 | elsif Ada_Version >= Ada_05 then |
420 | if Chars (E) = Name_uDisp_Asynchronous_Select then | |
421 | return Uint_11; | |
d62940bf | 422 | |
76a1c25b | 423 | elsif Chars (E) = Name_uDisp_Conditional_Select then |
424 | return Uint_12; | |
d62940bf | 425 | |
76a1c25b | 426 | elsif Chars (E) = Name_uDisp_Get_Prim_Op_Kind then |
427 | return Uint_13; | |
d62940bf | 428 | |
76a1c25b | 429 | elsif Chars (E) = Name_uDisp_Get_Task_Id then |
430 | return Uint_14; | |
d62940bf | 431 | |
76a1c25b | 432 | elsif Chars (E) = Name_uDisp_Timed_Select then |
433 | return Uint_15; | |
434 | end if; | |
aad6babd | 435 | end if; |
76a1c25b | 436 | |
437 | raise Program_Error; | |
aad6babd | 438 | end Default_Prim_Op_Position; |
439 | ||
7189d17f | 440 | ----------------------------- |
441 | -- Expand_Dispatching_Call -- | |
442 | ----------------------------- | |
ee6ba406 | 443 | |
7189d17f | 444 | procedure Expand_Dispatching_Call (Call_Node : Node_Id) is |
ee6ba406 | 445 | Loc : constant Source_Ptr := Sloc (Call_Node); |
446 | Call_Typ : constant Entity_Id := Etype (Call_Node); | |
447 | ||
448 | Ctrl_Arg : constant Node_Id := Controlling_Argument (Call_Node); | |
449 | Param_List : constant List_Id := Parameter_Associations (Call_Node); | |
ee6ba406 | 450 | |
af647dc7 | 451 | Subp : Entity_Id; |
7189d17f | 452 | CW_Typ : Entity_Id; |
453 | New_Call : Node_Id; | |
454 | New_Call_Name : Node_Id; | |
455 | New_Params : List_Id := No_List; | |
456 | Param : Node_Id; | |
457 | Res_Typ : Entity_Id; | |
458 | Subp_Ptr_Typ : Entity_Id; | |
459 | Subp_Typ : Entity_Id; | |
460 | Typ : Entity_Id; | |
461 | Eq_Prim_Op : Entity_Id := Empty; | |
462 | Controlling_Tag : Node_Id; | |
ee6ba406 | 463 | |
464 | function New_Value (From : Node_Id) return Node_Id; | |
9dfe12ae | 465 | -- From is the original Expression. New_Value is equivalent to a call |
466 | -- to Duplicate_Subexpr with an explicit dereference when From is an | |
7189d17f | 467 | -- access parameter. |
468 | ||
9dfe12ae | 469 | --------------- |
470 | -- New_Value -- | |
471 | --------------- | |
472 | ||
ee6ba406 | 473 | function New_Value (From : Node_Id) return Node_Id is |
474 | Res : constant Node_Id := Duplicate_Subexpr (From); | |
ee6ba406 | 475 | begin |
476 | if Is_Access_Type (Etype (From)) then | |
af647dc7 | 477 | return |
478 | Make_Explicit_Dereference (Sloc (From), | |
479 | Prefix => Res); | |
ee6ba406 | 480 | else |
481 | return Res; | |
482 | end if; | |
483 | end New_Value; | |
484 | ||
7189d17f | 485 | -- Start of processing for Expand_Dispatching_Call |
ee6ba406 | 486 | |
487 | begin | |
343d35dc | 488 | -- Expand_Dispatching_Call is called directly from the semantics, |
489 | -- so we need a check to see whether expansion is active before | |
490 | -- proceeding. In addition, there is no need to expand the call | |
491 | -- if we are compiling under restriction No_Dispatching_Calls; | |
492 | -- the semantic analyzer has previously notified the violation | |
493 | -- of this restriction. | |
494 | ||
495 | if not Expander_Active | |
496 | or else Restriction_Active (No_Dispatching_Calls) | |
497 | then | |
498 | return; | |
499 | end if; | |
68f95949 | 500 | |
af647dc7 | 501 | -- Set subprogram. If this is an inherited operation that was |
502 | -- overridden, the body that is being called is its alias. | |
503 | ||
504 | Subp := Entity (Name (Call_Node)); | |
ee6ba406 | 505 | |
506 | if Present (Alias (Subp)) | |
507 | and then Is_Inherited_Operation (Subp) | |
508 | and then No (DTC_Entity (Subp)) | |
509 | then | |
510 | Subp := Alias (Subp); | |
511 | end if; | |
512 | ||
7189d17f | 513 | -- Definition of the class-wide type and the tagged type |
ee6ba406 | 514 | |
7189d17f | 515 | -- If the controlling argument is itself a tag rather than a tagged |
516 | -- object, then use the class-wide type associated with the subprogram's | |
517 | -- controlling type. This case can occur when a call to an inherited | |
518 | -- primitive has an actual that originated from a default parameter | |
519 | -- given by a tag-indeterminate call and when there is no other | |
520 | -- controlling argument providing the tag (AI-239 requires dispatching). | |
521 | -- This capability of dispatching directly by tag is also needed by the | |
522 | -- implementation of AI-260 (for the generic dispatching constructors). | |
523 | ||
aad6babd | 524 | if Etype (Ctrl_Arg) = RTE (RE_Tag) |
68f95949 | 525 | or else (RTE_Available (RE_Interface_Tag) |
526 | and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)) | |
aad6babd | 527 | then |
af647dc7 | 528 | CW_Typ := Class_Wide_Type (Find_Dispatching_Type (Subp)); |
7189d17f | 529 | |
530 | elsif Is_Access_Type (Etype (Ctrl_Arg)) then | |
ee6ba406 | 531 | CW_Typ := Designated_Type (Etype (Ctrl_Arg)); |
7189d17f | 532 | |
ee6ba406 | 533 | else |
534 | CW_Typ := Etype (Ctrl_Arg); | |
535 | end if; | |
536 | ||
537 | Typ := Root_Type (CW_Typ); | |
538 | ||
d62940bf | 539 | if Ekind (Typ) = E_Incomplete_Type then |
540 | Typ := Non_Limited_View (Typ); | |
541 | end if; | |
542 | ||
ee6ba406 | 543 | if not Is_Limited_Type (Typ) then |
544 | Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq); | |
545 | end if; | |
546 | ||
343d35dc | 547 | -- Dispatching call to C++ primitive. Create a new parameter list |
548 | -- with no tag checks. | |
ee6ba406 | 549 | |
343d35dc | 550 | if Is_CPP_Class (Typ) then |
ee6ba406 | 551 | New_Params := New_List; |
552 | Param := First_Actual (Call_Node); | |
553 | while Present (Param) loop | |
aad6babd | 554 | Append_To (New_Params, Relocate_Node (Param)); |
ee6ba406 | 555 | Next_Actual (Param); |
556 | end loop; | |
557 | ||
343d35dc | 558 | -- Dispatching call to Ada primitive |
559 | ||
ee6ba406 | 560 | elsif Present (Param_List) then |
561 | ||
562 | -- Generate the Tag checks when appropriate | |
563 | ||
564 | New_Params := New_List; | |
ee6ba406 | 565 | Param := First_Actual (Call_Node); |
566 | while Present (Param) loop | |
567 | ||
568 | -- No tag check with itself | |
569 | ||
570 | if Param = Ctrl_Arg then | |
9dfe12ae | 571 | Append_To (New_Params, |
572 | Duplicate_Subexpr_Move_Checks (Param)); | |
ee6ba406 | 573 | |
574 | -- No tag check for parameter whose type is neither tagged nor | |
575 | -- access to tagged (for access parameters) | |
576 | ||
577 | elsif No (Find_Controlling_Arg (Param)) then | |
578 | Append_To (New_Params, Relocate_Node (Param)); | |
579 | ||
7189d17f | 580 | -- No tag check for function dispatching on result if the |
ee6ba406 | 581 | -- Tag given by the context is this one |
582 | ||
583 | elsif Find_Controlling_Arg (Param) = Ctrl_Arg then | |
584 | Append_To (New_Params, Relocate_Node (Param)); | |
585 | ||
586 | -- "=" is the only dispatching operation allowed to get | |
587 | -- operands with incompatible tags (it just returns false). | |
9dfe12ae | 588 | -- We use Duplicate_Subexpr_Move_Checks instead of calling |
589 | -- Relocate_Node because the value will be duplicated to | |
590 | -- check the tags. | |
ee6ba406 | 591 | |
592 | elsif Subp = Eq_Prim_Op then | |
9dfe12ae | 593 | Append_To (New_Params, |
594 | Duplicate_Subexpr_Move_Checks (Param)); | |
ee6ba406 | 595 | |
596 | -- No check in presence of suppress flags | |
597 | ||
598 | elsif Tag_Checks_Suppressed (Etype (Param)) | |
599 | or else (Is_Access_Type (Etype (Param)) | |
600 | and then Tag_Checks_Suppressed | |
601 | (Designated_Type (Etype (Param)))) | |
602 | then | |
603 | Append_To (New_Params, Relocate_Node (Param)); | |
604 | ||
605 | -- Optimization: no tag checks if the parameters are identical | |
606 | ||
607 | elsif Is_Entity_Name (Param) | |
608 | and then Is_Entity_Name (Ctrl_Arg) | |
609 | and then Entity (Param) = Entity (Ctrl_Arg) | |
610 | then | |
611 | Append_To (New_Params, Relocate_Node (Param)); | |
612 | ||
613 | -- Now we need to generate the Tag check | |
614 | ||
615 | else | |
616 | -- Generate code for tag equality check | |
617 | -- Perhaps should have Checks.Apply_Tag_Equality_Check??? | |
618 | ||
619 | Insert_Action (Ctrl_Arg, | |
620 | Make_Implicit_If_Statement (Call_Node, | |
621 | Condition => | |
622 | Make_Op_Ne (Loc, | |
623 | Left_Opnd => | |
624 | Make_Selected_Component (Loc, | |
625 | Prefix => New_Value (Ctrl_Arg), | |
626 | Selector_Name => | |
4660e715 | 627 | New_Reference_To |
628 | (First_Tag_Component (Typ), Loc)), | |
ee6ba406 | 629 | |
630 | Right_Opnd => | |
631 | Make_Selected_Component (Loc, | |
632 | Prefix => | |
633 | Unchecked_Convert_To (Typ, New_Value (Param)), | |
634 | Selector_Name => | |
4660e715 | 635 | New_Reference_To |
636 | (First_Tag_Component (Typ), Loc))), | |
ee6ba406 | 637 | |
638 | Then_Statements => | |
639 | New_List (New_Constraint_Error (Loc)))); | |
640 | ||
641 | Append_To (New_Params, Relocate_Node (Param)); | |
642 | end if; | |
643 | ||
644 | Next_Actual (Param); | |
645 | end loop; | |
646 | end if; | |
647 | ||
648 | -- Generate the appropriate subprogram pointer type | |
649 | ||
68f95949 | 650 | if Etype (Subp) = Typ then |
ee6ba406 | 651 | Res_Typ := CW_Typ; |
652 | else | |
7189d17f | 653 | Res_Typ := Etype (Subp); |
ee6ba406 | 654 | end if; |
655 | ||
656 | Subp_Typ := Create_Itype (E_Subprogram_Type, Call_Node); | |
657 | Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node); | |
658 | Set_Etype (Subp_Typ, Res_Typ); | |
659 | Init_Size_Align (Subp_Ptr_Typ); | |
660 | Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp)); | |
661 | ||
662 | -- Create a new list of parameters which is a copy of the old formal | |
663 | -- list including the creation of a new set of matching entities. | |
664 | ||
665 | declare | |
666 | Old_Formal : Entity_Id := First_Formal (Subp); | |
667 | New_Formal : Entity_Id; | |
668 | Extra : Entity_Id; | |
669 | ||
670 | begin | |
671 | if Present (Old_Formal) then | |
672 | New_Formal := New_Copy (Old_Formal); | |
673 | Set_First_Entity (Subp_Typ, New_Formal); | |
674 | Param := First_Actual (Call_Node); | |
675 | ||
676 | loop | |
677 | Set_Scope (New_Formal, Subp_Typ); | |
678 | ||
679 | -- Change all the controlling argument types to be class-wide | |
7189d17f | 680 | -- to avoid a recursion in dispatching. |
ee6ba406 | 681 | |
7189d17f | 682 | if Is_Controlling_Formal (New_Formal) then |
ee6ba406 | 683 | Set_Etype (New_Formal, Etype (Param)); |
684 | end if; | |
685 | ||
686 | if Is_Itype (Etype (New_Formal)) then | |
687 | Extra := New_Copy (Etype (New_Formal)); | |
688 | ||
689 | if Ekind (Extra) = E_Record_Subtype | |
690 | or else Ekind (Extra) = E_Class_Wide_Subtype | |
691 | then | |
692 | Set_Cloned_Subtype (Extra, Etype (New_Formal)); | |
693 | end if; | |
694 | ||
695 | Set_Etype (New_Formal, Extra); | |
696 | Set_Scope (Etype (New_Formal), Subp_Typ); | |
697 | end if; | |
698 | ||
699 | Extra := New_Formal; | |
700 | Next_Formal (Old_Formal); | |
701 | exit when No (Old_Formal); | |
702 | ||
703 | Set_Next_Entity (New_Formal, New_Copy (Old_Formal)); | |
704 | Next_Entity (New_Formal); | |
705 | Next_Actual (Param); | |
706 | end loop; | |
af647dc7 | 707 | |
708 | Set_Next_Entity (New_Formal, Empty); | |
ee6ba406 | 709 | Set_Last_Entity (Subp_Typ, Extra); |
710 | ||
711 | -- Copy extra formals | |
712 | ||
713 | New_Formal := First_Entity (Subp_Typ); | |
714 | while Present (New_Formal) loop | |
715 | if Present (Extra_Constrained (New_Formal)) then | |
716 | Set_Extra_Formal (Extra, | |
717 | New_Copy (Extra_Constrained (New_Formal))); | |
718 | Extra := Extra_Formal (Extra); | |
719 | Set_Extra_Constrained (New_Formal, Extra); | |
720 | ||
721 | elsif Present (Extra_Accessibility (New_Formal)) then | |
722 | Set_Extra_Formal (Extra, | |
723 | New_Copy (Extra_Accessibility (New_Formal))); | |
724 | Extra := Extra_Formal (Extra); | |
725 | Set_Extra_Accessibility (New_Formal, Extra); | |
726 | end if; | |
727 | ||
728 | Next_Formal (New_Formal); | |
729 | end loop; | |
730 | end if; | |
731 | end; | |
732 | ||
733 | Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ); | |
734 | Set_Directly_Designated_Type (Subp_Ptr_Typ, Subp_Typ); | |
735 | ||
68f95949 | 736 | -- If the controlling argument is a value of type Ada.Tag or an abstract |
737 | -- interface class-wide type then use it directly. Otherwise, the tag | |
738 | -- must be extracted from the controlling object. | |
7189d17f | 739 | |
aad6babd | 740 | if Etype (Ctrl_Arg) = RTE (RE_Tag) |
68f95949 | 741 | or else (RTE_Available (RE_Interface_Tag) |
742 | and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)) | |
743 | then | |
744 | Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg); | |
745 | ||
343d35dc | 746 | -- Extract the tag from an unchecked type conversion. Done to avoid |
747 | -- the expansion of additional code just to obtain the value of such | |
748 | -- tag because the current management of interface type conversions | |
749 | -- generates in some cases this unchecked type conversion with the | |
750 | -- tag of the object (see Expand_Interface_Conversion). | |
751 | ||
752 | elsif Nkind (Ctrl_Arg) = N_Unchecked_Type_Conversion | |
753 | and then | |
754 | (Etype (Expression (Ctrl_Arg)) = RTE (RE_Tag) | |
755 | or else | |
756 | (RTE_Available (RE_Interface_Tag) | |
757 | and then | |
758 | Etype (Expression (Ctrl_Arg)) = RTE (RE_Interface_Tag))) | |
759 | then | |
760 | Controlling_Tag := Duplicate_Subexpr (Expression (Ctrl_Arg)); | |
761 | ||
68f95949 | 762 | -- Ada 2005 (AI-251): Abstract interface class-wide type |
763 | ||
764 | elsif Is_Interface (Etype (Ctrl_Arg)) | |
765 | and then Is_Class_Wide_Type (Etype (Ctrl_Arg)) | |
aad6babd | 766 | then |
7189d17f | 767 | Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg); |
768 | ||
769 | else | |
770 | Controlling_Tag := | |
771 | Make_Selected_Component (Loc, | |
772 | Prefix => Duplicate_Subexpr_Move_Checks (Ctrl_Arg), | |
773 | Selector_Name => New_Reference_To (DTC_Entity (Subp), Loc)); | |
774 | end if; | |
775 | ||
343d35dc | 776 | -- Handle dispatching calls to predefined primitives |
ee6ba406 | 777 | |
af647dc7 | 778 | if Is_Predefined_Dispatching_Operation (Subp) |
779 | or else Is_Predefined_Dispatching_Alias (Subp) | |
780 | then | |
68f95949 | 781 | New_Call_Name := |
782 | Unchecked_Convert_To (Subp_Ptr_Typ, | |
343d35dc | 783 | Build_Get_Predefined_Prim_Op_Address (Loc, |
784 | Tag_Node => Controlling_Tag, | |
785 | Position_Node => Make_Integer_Literal (Loc, | |
786 | DT_Position (Subp)))); | |
ee6ba406 | 787 | |
343d35dc | 788 | -- Handle dispatching calls to user-defined primitives |
68f95949 | 789 | |
790 | else | |
791 | New_Call_Name := | |
792 | Unchecked_Convert_To (Subp_Ptr_Typ, | |
343d35dc | 793 | Build_Get_Prim_Op_Address (Loc, |
794 | Tag_Node => Controlling_Tag, | |
795 | Position_Node => Make_Integer_Literal (Loc, | |
796 | DT_Position (Subp)))); | |
68f95949 | 797 | end if; |
ee6ba406 | 798 | |
799 | if Nkind (Call_Node) = N_Function_Call then | |
ee6ba406 | 800 | |
aad6babd | 801 | -- Ada 2005 (AI-251): A dispatching "=" with an abstract interface |
802 | -- just requires the comparison of the tags. | |
ee6ba406 | 803 | |
aad6babd | 804 | if Ekind (Etype (Ctrl_Arg)) = E_Class_Wide_Type |
805 | and then Is_Interface (Etype (Ctrl_Arg)) | |
806 | and then Subp = Eq_Prim_Op | |
807 | then | |
ee6ba406 | 808 | Param := First_Actual (Call_Node); |
ee6ba406 | 809 | |
aad6babd | 810 | New_Call := |
811 | Make_Op_Eq (Loc, | |
812 | Left_Opnd => | |
813 | Make_Selected_Component (Loc, | |
814 | Prefix => New_Value (Param), | |
815 | Selector_Name => | |
816 | New_Reference_To (First_Tag_Component (Typ), Loc)), | |
817 | ||
818 | Right_Opnd => | |
819 | Make_Selected_Component (Loc, | |
820 | Prefix => | |
821 | Unchecked_Convert_To (Typ, | |
822 | New_Value (Next_Actual (Param))), | |
823 | Selector_Name => | |
824 | New_Reference_To (First_Tag_Component (Typ), Loc))); | |
ee6ba406 | 825 | |
aad6babd | 826 | else |
827 | New_Call := | |
828 | Make_Function_Call (Loc, | |
829 | Name => New_Call_Name, | |
830 | Parameter_Associations => New_Params); | |
831 | ||
832 | -- If this is a dispatching "=", we must first compare the tags so | |
833 | -- we generate: x.tag = y.tag and then x = y | |
834 | ||
835 | if Subp = Eq_Prim_Op then | |
836 | Param := First_Actual (Call_Node); | |
837 | New_Call := | |
838 | Make_And_Then (Loc, | |
839 | Left_Opnd => | |
840 | Make_Op_Eq (Loc, | |
841 | Left_Opnd => | |
842 | Make_Selected_Component (Loc, | |
843 | Prefix => New_Value (Param), | |
844 | Selector_Name => | |
845 | New_Reference_To (First_Tag_Component (Typ), | |
846 | Loc)), | |
847 | ||
848 | Right_Opnd => | |
849 | Make_Selected_Component (Loc, | |
850 | Prefix => | |
851 | Unchecked_Convert_To (Typ, | |
852 | New_Value (Next_Actual (Param))), | |
853 | Selector_Name => | |
854 | New_Reference_To (First_Tag_Component (Typ), | |
855 | Loc))), | |
856 | Right_Opnd => New_Call); | |
857 | end if; | |
ee6ba406 | 858 | end if; |
859 | ||
860 | else | |
861 | New_Call := | |
862 | Make_Procedure_Call_Statement (Loc, | |
863 | Name => New_Call_Name, | |
864 | Parameter_Associations => New_Params); | |
865 | end if; | |
866 | ||
867 | Rewrite (Call_Node, New_Call); | |
868 | Analyze_And_Resolve (Call_Node, Call_Typ); | |
7189d17f | 869 | end Expand_Dispatching_Call; |
ee6ba406 | 870 | |
aad6babd | 871 | --------------------------------- |
872 | -- Expand_Interface_Conversion -- | |
873 | --------------------------------- | |
874 | ||
952af0b9 | 875 | procedure Expand_Interface_Conversion |
876 | (N : Node_Id; | |
877 | Is_Static : Boolean := True) | |
878 | is | |
aad6babd | 879 | Loc : constant Source_Ptr := Sloc (N); |
af647dc7 | 880 | Etyp : constant Entity_Id := Etype (N); |
aad6babd | 881 | Operand : constant Node_Id := Expression (N); |
882 | Operand_Typ : Entity_Id := Etype (Operand); | |
d62940bf | 883 | Fent : Entity_Id; |
884 | Func : Node_Id; | |
af647dc7 | 885 | Iface_Typ : Entity_Id := Etype (N); |
886 | Iface_Tag : Entity_Id; | |
887 | New_Itype : Entity_Id; | |
aad6babd | 888 | |
889 | begin | |
890 | pragma Assert (Nkind (Operand) /= N_Attribute_Reference); | |
891 | ||
343d35dc | 892 | -- Ada 2005 (AI-345): Handle synchronized interface type derivations |
aad6babd | 893 | |
343d35dc | 894 | if Is_Concurrent_Type (Operand_Typ) then |
895 | Operand_Typ := Base_Type (Corresponding_Record_Type (Operand_Typ)); | |
aad6babd | 896 | end if; |
897 | ||
d62940bf | 898 | -- Handle access types to interfaces |
aad6babd | 899 | |
d62940bf | 900 | if Is_Access_Type (Iface_Typ) then |
901 | Iface_Typ := Etype (Directly_Designated_Type (Iface_Typ)); | |
aad6babd | 902 | end if; |
903 | ||
d62940bf | 904 | -- Handle class-wide interface types. This conversion can appear |
905 | -- explicitly in the source code. Example: I'Class (Obj) | |
aad6babd | 906 | |
d62940bf | 907 | if Is_Class_Wide_Type (Iface_Typ) then |
908 | Iface_Typ := Etype (Iface_Typ); | |
909 | end if; | |
910 | ||
af647dc7 | 911 | pragma Assert (not Is_Static |
912 | or else (not Is_Class_Wide_Type (Iface_Typ) | |
913 | and then Is_Interface (Iface_Typ))); | |
aad6babd | 914 | |
952af0b9 | 915 | if not Is_Static then |
68f95949 | 916 | |
917 | -- Give error if configurable run time and Displace not available | |
918 | ||
919 | if not RTE_Available (RE_Displace) then | |
920 | Error_Msg_CRT ("abstract interface types", N); | |
921 | return; | |
922 | end if; | |
923 | ||
af647dc7 | 924 | -- Handle conversion of access to class-wide interface types. The |
925 | -- target can be an access to object or an access to another class | |
926 | -- wide interfac (see -1- and -2- in the following example): | |
927 | ||
928 | -- type Iface1_Ref is access all Iface1'Class; | |
929 | -- type Iface2_Ref is access all Iface1'Class; | |
930 | ||
931 | -- Acc1 : Iface1_Ref := new ... | |
932 | -- Obj : Obj_Ref := Obj_Ref (Acc); -- 1 | |
933 | -- Acc2 : Iface2_Ref := Iface2_Ref (Acc); -- 2 | |
934 | ||
935 | if Is_Access_Type (Operand_Typ) then | |
936 | pragma Assert | |
937 | (Is_Class_Wide_Type (Directly_Designated_Type (Operand_Typ)) | |
938 | and then | |
939 | Is_Interface (Directly_Designated_Type (Operand_Typ))); | |
940 | ||
941 | Rewrite (N, | |
942 | Unchecked_Convert_To (Etype (N), | |
943 | Make_Function_Call (Loc, | |
944 | Name => New_Reference_To (RTE (RE_Displace), Loc), | |
945 | Parameter_Associations => New_List ( | |
946 | ||
947 | Unchecked_Convert_To (RTE (RE_Address), | |
948 | Relocate_Node (Expression (N))), | |
949 | ||
950 | New_Occurrence_Of | |
951 | (Node (First_Elmt (Access_Disp_Table (Iface_Typ))), | |
952 | Loc))))); | |
953 | ||
954 | Analyze (N); | |
955 | return; | |
956 | end if; | |
957 | ||
952af0b9 | 958 | Rewrite (N, |
959 | Make_Function_Call (Loc, | |
960 | Name => New_Reference_To (RTE (RE_Displace), Loc), | |
961 | Parameter_Associations => New_List ( | |
962 | Make_Attribute_Reference (Loc, | |
963 | Prefix => Relocate_Node (Expression (N)), | |
964 | Attribute_Name => Name_Address), | |
af647dc7 | 965 | |
952af0b9 | 966 | New_Occurrence_Of |
967 | (Node (First_Elmt (Access_Disp_Table (Iface_Typ))), | |
968 | Loc)))); | |
969 | ||
970 | Analyze (N); | |
971 | ||
af647dc7 | 972 | -- If the target is a class-wide interface we change the type of the |
973 | -- data returned by IW_Convert to indicate that this is a dispatching | |
974 | -- call. | |
952af0b9 | 975 | |
af647dc7 | 976 | New_Itype := Create_Itype (E_Anonymous_Access_Type, N); |
977 | Set_Etype (New_Itype, New_Itype); | |
978 | Init_Esize (New_Itype); | |
979 | Init_Size_Align (New_Itype); | |
980 | Set_Directly_Designated_Type (New_Itype, Etyp); | |
952af0b9 | 981 | |
af647dc7 | 982 | Rewrite (N, Make_Explicit_Dereference (Loc, |
68f95949 | 983 | Unchecked_Convert_To (New_Itype, |
984 | Relocate_Node (N)))); | |
af647dc7 | 985 | Analyze (N); |
986 | Freeze_Itype (New_Itype, N); | |
952af0b9 | 987 | |
988 | return; | |
989 | end if; | |
990 | ||
d62940bf | 991 | Iface_Tag := Find_Interface_Tag (Operand_Typ, Iface_Typ); |
aad6babd | 992 | pragma Assert (Iface_Tag /= Empty); |
993 | ||
d62940bf | 994 | -- Keep separate access types to interfaces because one internal |
995 | -- function is used to handle the null value (see following comment) | |
996 | ||
997 | if not Is_Access_Type (Etype (N)) then | |
998 | Rewrite (N, | |
999 | Unchecked_Convert_To (Etype (N), | |
1000 | Make_Selected_Component (Loc, | |
1001 | Prefix => Relocate_Node (Expression (N)), | |
1002 | Selector_Name => | |
1003 | New_Occurrence_Of (Iface_Tag, Loc)))); | |
1004 | ||
1005 | else | |
1006 | -- Build internal function to handle the case in which the | |
1007 | -- actual is null. If the actual is null returns null because | |
1008 | -- no displacement is required; otherwise performs a type | |
1009 | -- conversion that will be expanded in the code that returns | |
1010 | -- the value of the displaced actual. That is: | |
1011 | ||
af647dc7 | 1012 | -- function Func (O : Address) return Iface_Typ is |
d62940bf | 1013 | -- begin |
af647dc7 | 1014 | -- if O = Null_Address then |
d62940bf | 1015 | -- return null; |
1016 | -- else | |
af647dc7 | 1017 | -- return Iface_Typ!(Operand_Typ!(O).Iface_Tag'Address); |
d62940bf | 1018 | -- end if; |
1019 | -- end Func; | |
1020 | ||
af647dc7 | 1021 | Fent := Make_Defining_Identifier (Loc, New_Internal_Name ('F')); |
1022 | Set_Is_Internal (Fent); | |
1023 | ||
1024 | declare | |
1025 | Desig_Typ : Entity_Id; | |
1026 | begin | |
1027 | Desig_Typ := Etype (Expression (N)); | |
d62940bf | 1028 | |
af647dc7 | 1029 | if Is_Access_Type (Desig_Typ) then |
1030 | Desig_Typ := Directly_Designated_Type (Desig_Typ); | |
1031 | end if; | |
d62940bf | 1032 | |
af647dc7 | 1033 | New_Itype := Create_Itype (E_Anonymous_Access_Type, N); |
1034 | Set_Etype (New_Itype, New_Itype); | |
1035 | Set_Scope (New_Itype, Fent); | |
1036 | Init_Size_Align (New_Itype); | |
1037 | Set_Directly_Designated_Type (New_Itype, Desig_Typ); | |
1038 | end; | |
d62940bf | 1039 | |
1040 | Func := | |
1041 | Make_Subprogram_Body (Loc, | |
1042 | Specification => | |
1043 | Make_Function_Specification (Loc, | |
1044 | Defining_Unit_Name => Fent, | |
1045 | ||
1046 | Parameter_Specifications => New_List ( | |
1047 | Make_Parameter_Specification (Loc, | |
1048 | Defining_Identifier => | |
1049 | Make_Defining_Identifier (Loc, Name_uO), | |
1050 | Parameter_Type => | |
af647dc7 | 1051 | New_Reference_To (RTE (RE_Address), Loc))), |
1052 | ||
d62940bf | 1053 | Result_Definition => |
1054 | New_Reference_To (Etype (N), Loc)), | |
1055 | ||
1056 | Declarations => Empty_List, | |
1057 | ||
1058 | Handled_Statement_Sequence => | |
1059 | Make_Handled_Sequence_Of_Statements (Loc, | |
1060 | Statements => New_List ( | |
1061 | Make_If_Statement (Loc, | |
1062 | Condition => | |
1063 | Make_Op_Eq (Loc, | |
1064 | Left_Opnd => Make_Identifier (Loc, Name_uO), | |
af647dc7 | 1065 | Right_Opnd => New_Reference_To |
1066 | (RTE (RE_Null_Address), Loc)), | |
1067 | ||
d62940bf | 1068 | Then_Statements => New_List ( |
1069 | Make_Return_Statement (Loc, | |
1070 | Make_Null (Loc))), | |
af647dc7 | 1071 | |
d62940bf | 1072 | Else_Statements => New_List ( |
1073 | Make_Return_Statement (Loc, | |
1074 | Unchecked_Convert_To (Etype (N), | |
af647dc7 | 1075 | Make_Attribute_Reference (Loc, |
1076 | Prefix => | |
1077 | Make_Selected_Component (Loc, | |
1078 | Prefix => Unchecked_Convert_To (New_Itype, | |
1079 | Make_Identifier (Loc, Name_uO)), | |
1080 | Selector_Name => | |
1081 | New_Occurrence_Of (Iface_Tag, Loc)), | |
1082 | Attribute_Name => Name_Address)))))))); | |
d62940bf | 1083 | |
343d35dc | 1084 | -- Place function body before the expression containing |
1085 | -- the conversion | |
d62940bf | 1086 | |
343d35dc | 1087 | Insert_Action (N, Func); |
d62940bf | 1088 | Analyze (Func); |
1089 | ||
af647dc7 | 1090 | if Is_Access_Type (Etype (Expression (N))) then |
1091 | ||
1092 | -- Generate: Operand_Typ!(Expression.all)'Address | |
1093 | ||
1094 | Rewrite (N, | |
1095 | Make_Function_Call (Loc, | |
1096 | Name => New_Reference_To (Fent, Loc), | |
1097 | Parameter_Associations => New_List ( | |
1098 | Make_Attribute_Reference (Loc, | |
1099 | Prefix => Unchecked_Convert_To (Operand_Typ, | |
1100 | Make_Explicit_Dereference (Loc, | |
1101 | Relocate_Node (Expression (N)))), | |
1102 | Attribute_Name => Name_Address)))); | |
1103 | ||
1104 | else | |
1105 | -- Generate: Operand_Typ!(Expression)'Address | |
1106 | ||
1107 | Rewrite (N, | |
1108 | Make_Function_Call (Loc, | |
1109 | Name => New_Reference_To (Fent, Loc), | |
1110 | Parameter_Associations => New_List ( | |
1111 | Make_Attribute_Reference (Loc, | |
1112 | Prefix => Unchecked_Convert_To (Operand_Typ, | |
1113 | Relocate_Node (Expression (N))), | |
1114 | Attribute_Name => Name_Address)))); | |
1115 | end if; | |
d62940bf | 1116 | end if; |
aad6babd | 1117 | |
1118 | Analyze (N); | |
1119 | end Expand_Interface_Conversion; | |
1120 | ||
1121 | ------------------------------ | |
1122 | -- Expand_Interface_Actuals -- | |
1123 | ------------------------------ | |
1124 | ||
1125 | procedure Expand_Interface_Actuals (Call_Node : Node_Id) is | |
1126 | Loc : constant Source_Ptr := Sloc (Call_Node); | |
1127 | Actual : Node_Id; | |
d62940bf | 1128 | Actual_Dup : Node_Id; |
aad6babd | 1129 | Actual_Typ : Entity_Id; |
d62940bf | 1130 | Anon : Entity_Id; |
aad6babd | 1131 | Conversion : Node_Id; |
1132 | Formal : Entity_Id; | |
1133 | Formal_Typ : Entity_Id; | |
1134 | Subp : Entity_Id; | |
1135 | Nam : Name_Id; | |
d62940bf | 1136 | Formal_DDT : Entity_Id; |
1137 | Actual_DDT : Entity_Id; | |
aad6babd | 1138 | |
1139 | begin | |
1140 | -- This subprogram is called directly from the semantics, so we need a | |
1141 | -- check to see whether expansion is active before proceeding. | |
1142 | ||
1143 | if not Expander_Active then | |
1144 | return; | |
1145 | end if; | |
1146 | ||
1147 | -- Call using access to subprogram with explicit dereference | |
1148 | ||
1149 | if Nkind (Name (Call_Node)) = N_Explicit_Dereference then | |
1150 | Subp := Etype (Name (Call_Node)); | |
1151 | ||
1152 | -- Normal case | |
1153 | ||
1154 | else | |
1155 | Subp := Entity (Name (Call_Node)); | |
1156 | end if; | |
1157 | ||
1158 | Formal := First_Formal (Subp); | |
1159 | Actual := First_Actual (Call_Node); | |
aad6babd | 1160 | while Present (Formal) loop |
1161 | ||
aad6babd | 1162 | -- Ada 2005 (AI-251): Conversion to interface to force "this" |
d62940bf | 1163 | -- displacement. |
aad6babd | 1164 | |
1165 | Formal_Typ := Etype (Etype (Formal)); | |
d62940bf | 1166 | |
1167 | if Ekind (Formal_Typ) = E_Record_Type_With_Private then | |
1168 | Formal_Typ := Full_View (Formal_Typ); | |
1169 | end if; | |
1170 | ||
1171 | if Is_Access_Type (Formal_Typ) then | |
1172 | Formal_DDT := Directly_Designated_Type (Formal_Typ); | |
1173 | end if; | |
1174 | ||
aad6babd | 1175 | Actual_Typ := Etype (Actual); |
1176 | ||
d62940bf | 1177 | if Is_Access_Type (Actual_Typ) then |
1178 | Actual_DDT := Directly_Designated_Type (Actual_Typ); | |
1179 | end if; | |
1180 | ||
aad6babd | 1181 | if Is_Interface (Formal_Typ) then |
1182 | ||
d62940bf | 1183 | -- No need to displace the pointer if the type of the actual |
1184 | -- is class-wide of the formal-type interface; in this case the | |
1185 | -- displacement of the pointer was already done at the point of | |
1186 | -- the call to the enclosing subprogram. This case corresponds | |
1187 | -- with the call to P (Obj) in the following example: | |
aad6babd | 1188 | |
d62940bf | 1189 | -- type I is interface; |
1190 | -- procedure P (X : I) is abstract; | |
1191 | ||
1192 | -- procedure General_Op (Obj : I'Class) is | |
1193 | -- begin | |
1194 | -- P (Obj); | |
1195 | -- end General_Op; | |
1196 | ||
1197 | if Is_Class_Wide_Type (Actual_Typ) | |
1198 | and then Etype (Actual_Typ) = Formal_Typ | |
1199 | then | |
1200 | null; | |
1201 | ||
1202 | -- No need to displace the pointer if the type of the actual is a | |
1203 | -- derivation of the formal-type interface because in this case | |
1204 | -- the interface primitives are located in the primary dispatch | |
1205 | -- table. | |
aad6babd | 1206 | |
343d35dc | 1207 | elsif Is_Parent (Formal_Typ, Actual_Typ) then |
d62940bf | 1208 | null; |
1209 | ||
1210 | else | |
1211 | Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual)); | |
1212 | Rewrite (Actual, Conversion); | |
1213 | Analyze_And_Resolve (Actual, Formal_Typ); | |
1214 | end if; | |
aad6babd | 1215 | |
1216 | -- Anonymous access type | |
1217 | ||
1218 | elsif Is_Access_Type (Formal_Typ) | |
d62940bf | 1219 | and then Is_Interface (Etype (Formal_DDT)) |
aad6babd | 1220 | and then Interface_Present_In_Ancestor |
d62940bf | 1221 | (Typ => Actual_DDT, |
1222 | Iface => Etype (Formal_DDT)) | |
aad6babd | 1223 | then |
aad6babd | 1224 | if Nkind (Actual) = N_Attribute_Reference |
1225 | and then | |
1226 | (Attribute_Name (Actual) = Name_Access | |
1227 | or else Attribute_Name (Actual) = Name_Unchecked_Access) | |
1228 | then | |
1229 | Nam := Attribute_Name (Actual); | |
1230 | ||
d62940bf | 1231 | Conversion := Convert_To (Etype (Formal_DDT), Prefix (Actual)); |
aad6babd | 1232 | |
1233 | Rewrite (Actual, Conversion); | |
d62940bf | 1234 | Analyze_And_Resolve (Actual, Etype (Formal_DDT)); |
aad6babd | 1235 | |
1236 | Rewrite (Actual, | |
1237 | Unchecked_Convert_To (Formal_Typ, | |
1238 | Make_Attribute_Reference (Loc, | |
d62940bf | 1239 | Prefix => Relocate_Node (Actual), |
aad6babd | 1240 | Attribute_Name => Nam))); |
1241 | ||
1242 | Analyze_And_Resolve (Actual, Formal_Typ); | |
1243 | ||
d62940bf | 1244 | -- No need to displace the pointer if the actual is a class-wide |
1245 | -- type of the formal-type interface because in this case the | |
1246 | -- displacement of the pointer was already done at the point of | |
1247 | -- the call to the enclosing subprogram (this case is similar | |
1248 | -- to the example described above for the non access-type case) | |
1249 | ||
1250 | elsif Is_Class_Wide_Type (Actual_DDT) | |
1251 | and then Etype (Actual_DDT) = Formal_DDT | |
1252 | then | |
1253 | null; | |
1254 | ||
1255 | -- No need to displace the pointer if the type of the actual is a | |
1256 | -- derivation of the interface (because in this case the interface | |
1257 | -- primitives are located in the primary dispatch table) | |
1258 | ||
343d35dc | 1259 | elsif Is_Parent (Formal_DDT, Actual_DDT) then |
d62940bf | 1260 | null; |
1261 | ||
aad6babd | 1262 | else |
d62940bf | 1263 | Actual_Dup := Relocate_Node (Actual); |
1264 | ||
1265 | if From_With_Type (Actual_Typ) then | |
1266 | ||
1267 | -- If the type of the actual parameter comes from a limited | |
1268 | -- with-clause and the non-limited view is already available | |
1269 | -- we replace the anonymous access type by a duplicate decla | |
1270 | -- ration whose designated type is the non-limited view | |
1271 | ||
1272 | if Ekind (Actual_DDT) = E_Incomplete_Type | |
1273 | and then Present (Non_Limited_View (Actual_DDT)) | |
1274 | then | |
1275 | Anon := New_Copy (Actual_Typ); | |
1276 | ||
1277 | if Is_Itype (Anon) then | |
1278 | Set_Scope (Anon, Current_Scope); | |
1279 | end if; | |
1280 | ||
1281 | Set_Directly_Designated_Type (Anon, | |
1282 | Non_Limited_View (Actual_DDT)); | |
1283 | Set_Etype (Actual_Dup, Anon); | |
1284 | ||
1285 | elsif Is_Class_Wide_Type (Actual_DDT) | |
1286 | and then Ekind (Etype (Actual_DDT)) = E_Incomplete_Type | |
1287 | and then Present (Non_Limited_View (Etype (Actual_DDT))) | |
1288 | then | |
1289 | Anon := New_Copy (Actual_Typ); | |
1290 | ||
1291 | if Is_Itype (Anon) then | |
1292 | Set_Scope (Anon, Current_Scope); | |
1293 | end if; | |
1294 | ||
1295 | Set_Directly_Designated_Type (Anon, | |
1296 | New_Copy (Actual_DDT)); | |
1297 | Set_Class_Wide_Type (Directly_Designated_Type (Anon), | |
1298 | New_Copy (Class_Wide_Type (Actual_DDT))); | |
1299 | Set_Etype (Directly_Designated_Type (Anon), | |
1300 | Non_Limited_View (Etype (Actual_DDT))); | |
1301 | Set_Etype ( | |
1302 | Class_Wide_Type (Directly_Designated_Type (Anon)), | |
1303 | Non_Limited_View (Etype (Actual_DDT))); | |
1304 | Set_Etype (Actual_Dup, Anon); | |
1305 | end if; | |
1306 | end if; | |
1307 | ||
1308 | Conversion := Convert_To (Formal_Typ, Actual_Dup); | |
1309 | Rewrite (Actual, Conversion); | |
aad6babd | 1310 | Analyze_And_Resolve (Actual, Formal_Typ); |
1311 | end if; | |
1312 | end if; | |
1313 | ||
1314 | Next_Actual (Actual); | |
1315 | Next_Formal (Formal); | |
1316 | end loop; | |
1317 | end Expand_Interface_Actuals; | |
1318 | ||
1319 | ---------------------------- | |
1320 | -- Expand_Interface_Thunk -- | |
1321 | ---------------------------- | |
1322 | ||
1323 | function Expand_Interface_Thunk | |
1324 | (N : Node_Id; | |
e1c20931 | 1325 | Thunk_Alias : Entity_Id; |
952af0b9 | 1326 | Thunk_Id : Entity_Id) return Node_Id |
aad6babd | 1327 | is |
1328 | Loc : constant Source_Ptr := Sloc (N); | |
1329 | Actuals : constant List_Id := New_List; | |
1330 | Decl : constant List_Id := New_List; | |
1331 | Formals : constant List_Id := New_List; | |
aad6babd | 1332 | Target : Entity_Id; |
1333 | New_Code : Node_Id; | |
1334 | Formal : Node_Id; | |
1335 | New_Formal : Node_Id; | |
1336 | Decl_1 : Node_Id; | |
1337 | Decl_2 : Node_Id; | |
d62940bf | 1338 | E : Entity_Id; |
aad6babd | 1339 | |
1340 | begin | |
aad6babd | 1341 | -- Traverse the list of alias to find the final target |
1342 | ||
1343 | Target := Thunk_Alias; | |
aad6babd | 1344 | while Present (Alias (Target)) loop |
1345 | Target := Alias (Target); | |
1346 | end loop; | |
1347 | ||
1348 | -- Duplicate the formals | |
1349 | ||
d62940bf | 1350 | Formal := First_Formal (Target); |
1351 | E := First_Formal (N); | |
aad6babd | 1352 | while Present (Formal) loop |
1353 | New_Formal := Copy_Separate_Tree (Parent (Formal)); | |
1354 | ||
d62940bf | 1355 | -- Propagate the parameter type to the copy. This is required to |
1356 | -- properly handle the case in which the subprogram covering the | |
1357 | -- interface has been inherited: | |
aad6babd | 1358 | |
1359 | -- Example: | |
1360 | -- type I is interface; | |
af647dc7 | 1361 | -- procedure P (X : I) is abstract; |
aad6babd | 1362 | |
1363 | -- type T is tagged null record; | |
1364 | -- procedure P (X : T); | |
1365 | ||
1366 | -- type DT is new T and I with ... | |
1367 | ||
d62940bf | 1368 | Set_Parameter_Type (New_Formal, New_Reference_To (Etype (E), Loc)); |
aad6babd | 1369 | Append_To (Formals, New_Formal); |
d62940bf | 1370 | |
aad6babd | 1371 | Next_Formal (Formal); |
d62940bf | 1372 | Next_Formal (E); |
aad6babd | 1373 | end loop; |
1374 | ||
68f95949 | 1375 | -- Give message if configurable run-time and Offset_To_Top unavailable |
1376 | ||
1377 | if not RTE_Available (RE_Offset_To_Top) then | |
1378 | Error_Msg_CRT ("abstract interface types", N); | |
1379 | return Empty; | |
1380 | end if; | |
1381 | ||
d62940bf | 1382 | if Ekind (First_Formal (Target)) = E_In_Parameter |
1383 | and then Ekind (Etype (First_Formal (Target))) | |
aad6babd | 1384 | = E_Anonymous_Access_Type |
1385 | then | |
aad6babd | 1386 | -- Generate: |
1387 | ||
1388 | -- type T is access all <<type of the first formal>> | |
1389 | -- S1 := Storage_Offset!(First_formal) | |
952af0b9 | 1390 | -- - Offset_To_Top (First_Formal.Tag) |
aad6babd | 1391 | |
1392 | -- ... and the first actual of the call is generated as T!(S1) | |
1393 | ||
1394 | Decl_2 := | |
1395 | Make_Full_Type_Declaration (Loc, | |
1396 | Defining_Identifier => | |
1397 | Make_Defining_Identifier (Loc, | |
1398 | New_Internal_Name ('T')), | |
1399 | Type_Definition => | |
1400 | Make_Access_To_Object_Definition (Loc, | |
1401 | All_Present => True, | |
1402 | Null_Exclusion_Present => False, | |
1403 | Constant_Present => False, | |
1404 | Subtype_Indication => | |
1405 | New_Reference_To | |
1406 | (Directly_Designated_Type | |
d62940bf | 1407 | (Etype (First_Formal (Target))), Loc))); |
aad6babd | 1408 | |
1409 | Decl_1 := | |
1410 | Make_Object_Declaration (Loc, | |
1411 | Defining_Identifier => | |
1412 | Make_Defining_Identifier (Loc, | |
1413 | New_Internal_Name ('S')), | |
1414 | Constant_Present => True, | |
1415 | Object_Definition => | |
1416 | New_Reference_To (RTE (RE_Storage_Offset), Loc), | |
1417 | Expression => | |
1418 | Make_Op_Subtract (Loc, | |
1419 | Left_Opnd => | |
1420 | Unchecked_Convert_To | |
1421 | (RTE (RE_Storage_Offset), | |
1422 | New_Reference_To | |
1423 | (Defining_Identifier (First (Formals)), Loc)), | |
1424 | Right_Opnd => | |
952af0b9 | 1425 | Make_Function_Call (Loc, |
1426 | Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), | |
1427 | Parameter_Associations => New_List ( | |
68f95949 | 1428 | Unchecked_Convert_To |
1429 | (RTE (RE_Address), | |
1430 | New_Reference_To | |
1431 | (Defining_Identifier (First (Formals)), Loc)))))); | |
aad6babd | 1432 | |
1433 | Append_To (Decl, Decl_2); | |
1434 | Append_To (Decl, Decl_1); | |
1435 | ||
1436 | -- Reference the new first actual | |
1437 | ||
1438 | Append_To (Actuals, | |
1439 | Unchecked_Convert_To | |
1440 | (Defining_Identifier (Decl_2), | |
1441 | New_Reference_To (Defining_Identifier (Decl_1), Loc))); | |
1442 | ||
aad6babd | 1443 | else |
1444 | -- Generate: | |
952af0b9 | 1445 | |
aad6babd | 1446 | -- S1 := Storage_Offset!(First_formal'Address) |
952af0b9 | 1447 | -- - Offset_To_Top (First_Formal.Tag) |
aad6babd | 1448 | -- S2 := Tag_Ptr!(S3) |
1449 | ||
1450 | Decl_1 := | |
1451 | Make_Object_Declaration (Loc, | |
1452 | Defining_Identifier => | |
1453 | Make_Defining_Identifier (Loc, New_Internal_Name ('S')), | |
1454 | Constant_Present => True, | |
1455 | Object_Definition => | |
1456 | New_Reference_To (RTE (RE_Storage_Offset), Loc), | |
1457 | Expression => | |
1458 | Make_Op_Subtract (Loc, | |
1459 | Left_Opnd => | |
1460 | Unchecked_Convert_To | |
1461 | (RTE (RE_Storage_Offset), | |
1462 | Make_Attribute_Reference (Loc, | |
1463 | Prefix => | |
1464 | New_Reference_To | |
1465 | (Defining_Identifier (First (Formals)), Loc), | |
1466 | Attribute_Name => Name_Address)), | |
1467 | Right_Opnd => | |
952af0b9 | 1468 | Make_Function_Call (Loc, |
1469 | Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), | |
1470 | Parameter_Associations => New_List ( | |
68f95949 | 1471 | Make_Attribute_Reference (Loc, |
952af0b9 | 1472 | Prefix => New_Reference_To |
1473 | (Defining_Identifier (First (Formals)), | |
1474 | Loc), | |
68f95949 | 1475 | Attribute_Name => Name_Address))))); |
aad6babd | 1476 | |
1477 | Decl_2 := | |
1478 | Make_Object_Declaration (Loc, | |
1479 | Defining_Identifier => | |
1480 | Make_Defining_Identifier (Loc, New_Internal_Name ('S')), | |
1481 | Constant_Present => True, | |
1482 | Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc), | |
1483 | Expression => | |
1484 | Unchecked_Convert_To | |
1485 | (RTE (RE_Addr_Ptr), | |
1486 | New_Reference_To (Defining_Identifier (Decl_1), Loc))); | |
1487 | ||
1488 | Append_To (Decl, Decl_1); | |
1489 | Append_To (Decl, Decl_2); | |
1490 | ||
1491 | -- Reference the new first actual | |
1492 | ||
1493 | Append_To (Actuals, | |
1494 | Unchecked_Convert_To | |
1495 | (Etype (First_Entity (Target)), | |
1496 | Make_Explicit_Dereference (Loc, | |
1497 | New_Reference_To (Defining_Identifier (Decl_2), Loc)))); | |
aad6babd | 1498 | end if; |
1499 | ||
1500 | Formal := Next (First (Formals)); | |
1501 | while Present (Formal) loop | |
1502 | Append_To (Actuals, | |
1503 | New_Reference_To (Defining_Identifier (Formal), Loc)); | |
1504 | Next (Formal); | |
1505 | end loop; | |
1506 | ||
d62940bf | 1507 | if Ekind (Target) = E_Procedure then |
aad6babd | 1508 | New_Code := |
1509 | Make_Subprogram_Body (Loc, | |
1510 | Specification => | |
1511 | Make_Procedure_Specification (Loc, | |
1512 | Defining_Unit_Name => Thunk_Id, | |
1513 | Parameter_Specifications => Formals), | |
1514 | Declarations => Decl, | |
1515 | Handled_Statement_Sequence => | |
1516 | Make_Handled_Sequence_Of_Statements (Loc, | |
1517 | Statements => New_List ( | |
1518 | Make_Procedure_Call_Statement (Loc, | |
1519 | Name => New_Occurrence_Of (Target, Loc), | |
1520 | Parameter_Associations => Actuals)))); | |
1521 | ||
d62940bf | 1522 | else pragma Assert (Ekind (Target) = E_Function); |
aad6babd | 1523 | |
1524 | New_Code := | |
1525 | Make_Subprogram_Body (Loc, | |
1526 | Specification => | |
1527 | Make_Function_Specification (Loc, | |
1528 | Defining_Unit_Name => Thunk_Id, | |
1529 | Parameter_Specifications => Formals, | |
d62940bf | 1530 | Result_Definition => |
1531 | New_Copy (Result_Definition (Parent (Target)))), | |
aad6babd | 1532 | Declarations => Decl, |
1533 | Handled_Statement_Sequence => | |
1534 | Make_Handled_Sequence_Of_Statements (Loc, | |
1535 | Statements => New_List ( | |
1536 | Make_Return_Statement (Loc, | |
1537 | Make_Function_Call (Loc, | |
1538 | Name => New_Occurrence_Of (Target, Loc), | |
1539 | Parameter_Associations => Actuals))))); | |
1540 | end if; | |
1541 | ||
af647dc7 | 1542 | -- Analyze the code of the thunk with checks suppressed because we are |
1543 | -- in the middle of building the dispatch information itself and some | |
1544 | -- characteristics of the type may not be fully available. | |
1545 | ||
1546 | Analyze (New_Code, Suppress => All_Checks); | |
aad6babd | 1547 | return New_Code; |
1548 | end Expand_Interface_Thunk; | |
1549 | ||
e1c20931 | 1550 | ------------------- |
1551 | -- Fill_DT_Entry -- | |
1552 | ------------------- | |
ee6ba406 | 1553 | |
1554 | function Fill_DT_Entry | |
e1c20931 | 1555 | (Loc : Source_Ptr; |
1556 | Prim : Entity_Id) return Node_Id | |
ee6ba406 | 1557 | is |
aad6babd | 1558 | Typ : constant Entity_Id := Scope (DTC_Entity (Prim)); |
e1c20931 | 1559 | DT_Ptr : constant Entity_Id := |
1560 | Node (First_Elmt (Access_Disp_Table (Typ))); | |
1561 | Pos : constant Uint := DT_Position (Prim); | |
1562 | Tag : constant Entity_Id := First_Tag_Component (Typ); | |
ee6ba406 | 1563 | |
1564 | begin | |
68f95949 | 1565 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
aad6babd | 1566 | |
af647dc7 | 1567 | if Is_Predefined_Dispatching_Operation (Prim) |
1568 | or else Is_Predefined_Dispatching_Alias (Prim) | |
1569 | then | |
68f95949 | 1570 | return |
343d35dc | 1571 | Build_Set_Predefined_Prim_Op_Address (Loc, |
1572 | Tag_Node => New_Reference_To (DT_Ptr, Loc), | |
1573 | Position_Node => Make_Integer_Literal (Loc, Pos), | |
1574 | Address_Node => Make_Attribute_Reference (Loc, | |
1575 | Prefix => New_Reference_To (Prim, Loc), | |
1576 | Attribute_Name => Name_Address)); | |
68f95949 | 1577 | |
68f95949 | 1578 | else |
1579 | pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); | |
1580 | ||
1581 | return | |
343d35dc | 1582 | Build_Set_Prim_Op_Address (Loc, |
1583 | Tag_Node => New_Reference_To (DT_Ptr, Loc), | |
1584 | Position_Node => Make_Integer_Literal (Loc, Pos), | |
1585 | Address_Node => Make_Attribute_Reference (Loc, | |
1586 | Prefix => New_Reference_To (Prim, Loc), | |
1587 | Attribute_Name => Name_Address)); | |
68f95949 | 1588 | end if; |
e1c20931 | 1589 | end Fill_DT_Entry; |
aad6babd | 1590 | |
e1c20931 | 1591 | ----------------------------- |
1592 | -- Fill_Secondary_DT_Entry -- | |
1593 | ----------------------------- | |
aad6babd | 1594 | |
e1c20931 | 1595 | function Fill_Secondary_DT_Entry |
1596 | (Loc : Source_Ptr; | |
1597 | Prim : Entity_Id; | |
1598 | Thunk_Id : Entity_Id; | |
1599 | Iface_DT_Ptr : Entity_Id) return Node_Id | |
1600 | is | |
e1c20931 | 1601 | Iface_Prim : constant Entity_Id := Abstract_Interface_Alias (Prim); |
1602 | Pos : constant Uint := DT_Position (Iface_Prim); | |
1603 | Tag : constant Entity_Id := | |
1604 | First_Tag_Component (Scope (DTC_Entity (Iface_Prim))); | |
1605 | ||
1606 | begin | |
af647dc7 | 1607 | if Is_Predefined_Dispatching_Operation (Prim) |
1608 | or else Is_Predefined_Dispatching_Alias (Prim) | |
1609 | then | |
68f95949 | 1610 | return |
343d35dc | 1611 | Build_Set_Predefined_Prim_Op_Address (Loc, |
1612 | Tag_Node => | |
1613 | New_Reference_To (Iface_DT_Ptr, Loc), | |
1614 | Position_Node => | |
1615 | Make_Integer_Literal (Loc, Pos), | |
1616 | Address_Node => | |
1617 | Make_Attribute_Reference (Loc, | |
68f95949 | 1618 | Prefix => New_Reference_To (Thunk_Id, Loc), |
343d35dc | 1619 | Attribute_Name => Name_Address)); |
68f95949 | 1620 | else |
1621 | pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); | |
ee6ba406 | 1622 | |
68f95949 | 1623 | return |
343d35dc | 1624 | Build_Set_Prim_Op_Address (Loc, |
1625 | Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc), | |
1626 | Position_Node => Make_Integer_Literal (Loc, Pos), | |
1627 | Address_Node => Make_Attribute_Reference (Loc, | |
1628 | Prefix => New_Reference_To (Thunk_Id, Loc), | |
1629 | Attribute_Name => Name_Address)); | |
68f95949 | 1630 | end if; |
e1c20931 | 1631 | end Fill_Secondary_DT_Entry; |
ee6ba406 | 1632 | |
af647dc7 | 1633 | ------------------------------------- |
1634 | -- Is_Predefined_Dispatching_Alias -- | |
1635 | ------------------------------------- | |
1636 | ||
1637 | function Is_Predefined_Dispatching_Alias (Prim : Entity_Id) return Boolean | |
1638 | is | |
1639 | E : Entity_Id; | |
1640 | ||
1641 | begin | |
1642 | if not Is_Predefined_Dispatching_Operation (Prim) | |
1643 | and then Present (Alias (Prim)) | |
1644 | then | |
1645 | E := Prim; | |
1646 | while Present (Alias (E)) loop | |
1647 | E := Alias (E); | |
1648 | end loop; | |
1649 | ||
1650 | if Is_Predefined_Dispatching_Operation (E) then | |
1651 | return True; | |
1652 | end if; | |
1653 | end if; | |
1654 | ||
1655 | return False; | |
1656 | end Is_Predefined_Dispatching_Alias; | |
1657 | ||
76a1c25b | 1658 | ---------------------------------------- |
1659 | -- Make_Disp_Asynchronous_Select_Body -- | |
1660 | ---------------------------------------- | |
ee6ba406 | 1661 | |
76a1c25b | 1662 | function Make_Disp_Asynchronous_Select_Body |
1663 | (Typ : Entity_Id) return Node_Id | |
1664 | is | |
1665 | Conc_Typ : Entity_Id := Empty; | |
1666 | Decls : constant List_Id := New_List; | |
1667 | DT_Ptr : Entity_Id; | |
1668 | Loc : constant Source_Ptr := Sloc (Typ); | |
1669 | Stmts : constant List_Id := New_List; | |
ee6ba406 | 1670 | |
1671 | begin | |
68f95949 | 1672 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
1673 | ||
952af0b9 | 1674 | -- Null body is generated for interface types |
1675 | ||
76a1c25b | 1676 | if Is_Interface (Typ) then |
1677 | return | |
1678 | Make_Subprogram_Body (Loc, | |
1679 | Specification => | |
1680 | Make_Disp_Asynchronous_Select_Spec (Typ), | |
1681 | Declarations => | |
1682 | New_List, | |
1683 | Handled_Statement_Sequence => | |
1684 | Make_Handled_Sequence_Of_Statements (Loc, | |
1685 | New_List (Make_Null_Statement (Loc)))); | |
9dfe12ae | 1686 | end if; |
1687 | ||
76a1c25b | 1688 | DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); |
aad6babd | 1689 | |
952af0b9 | 1690 | if Is_Concurrent_Record_Type (Typ) then |
1691 | Conc_Typ := Corresponding_Concurrent_Type (Typ); | |
aad6babd | 1692 | |
76a1c25b | 1693 | -- Generate: |
952af0b9 | 1694 | -- I : Integer := Get_Entry_Index (tag! (<type>VP), S); |
aad6babd | 1695 | |
76a1c25b | 1696 | -- where I will be used to capture the entry index of the primitive |
1697 | -- wrapper at position S. | |
aad6babd | 1698 | |
76a1c25b | 1699 | Append_To (Decls, |
1700 | Make_Object_Declaration (Loc, | |
1701 | Defining_Identifier => | |
1702 | Make_Defining_Identifier (Loc, Name_uI), | |
1703 | Object_Definition => | |
1704 | New_Reference_To (Standard_Integer, Loc), | |
1705 | Expression => | |
1706 | Make_DT_Access_Action (Typ, | |
1707 | Action => | |
1708 | Get_Entry_Index, | |
1709 | Args => | |
1710 | New_List ( | |
1711 | Unchecked_Convert_To (RTE (RE_Tag), | |
1712 | New_Reference_To (DT_Ptr, Loc)), | |
1713 | Make_Identifier (Loc, Name_uS))))); | |
aad6babd | 1714 | |
76a1c25b | 1715 | if Ekind (Conc_Typ) = E_Protected_Type then |
aad6babd | 1716 | |
76a1c25b | 1717 | -- Generate: |
1718 | -- Protected_Entry_Call ( | |
1719 | -- T._object'access, | |
1720 | -- protected_entry_index! (I), | |
1721 | -- P, | |
1722 | -- Asynchronous_Call, | |
1723 | -- B); | |
aad6babd | 1724 | |
76a1c25b | 1725 | -- where T is the protected object, I is the entry index, P are |
1726 | -- the wrapped parameters and B is the name of the communication | |
1727 | -- block. | |
aad6babd | 1728 | |
76a1c25b | 1729 | Append_To (Stmts, |
1730 | Make_Procedure_Call_Statement (Loc, | |
1731 | Name => | |
1732 | New_Reference_To (RTE (RE_Protected_Entry_Call), Loc), | |
1733 | Parameter_Associations => | |
1734 | New_List ( | |
aad6babd | 1735 | |
76a1c25b | 1736 | Make_Attribute_Reference (Loc, -- T._object'access |
1737 | Attribute_Name => | |
1738 | Name_Unchecked_Access, | |
1739 | Prefix => | |
1740 | Make_Selected_Component (Loc, | |
1741 | Prefix => | |
1742 | Make_Identifier (Loc, Name_uT), | |
1743 | Selector_Name => | |
1744 | Make_Identifier (Loc, Name_uObject))), | |
aad6babd | 1745 | |
76a1c25b | 1746 | Make_Unchecked_Type_Conversion (Loc, -- entry index |
1747 | Subtype_Mark => | |
1748 | New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), | |
1749 | Expression => | |
1750 | Make_Identifier (Loc, Name_uI)), | |
d62940bf | 1751 | |
76a1c25b | 1752 | Make_Identifier (Loc, Name_uP), -- parameter block |
1753 | New_Reference_To ( -- Asynchronous_Call | |
1754 | RTE (RE_Asynchronous_Call), Loc), | |
1755 | Make_Identifier (Loc, Name_uB)))); -- comm block | |
1756 | else | |
1757 | pragma Assert (Ekind (Conc_Typ) = E_Task_Type); | |
d62940bf | 1758 | |
76a1c25b | 1759 | -- Generate: |
1760 | -- Protected_Entry_Call ( | |
1761 | -- T._task_id, | |
1762 | -- task_entry_index! (I), | |
1763 | -- P, | |
1764 | -- Conditional_Call, | |
1765 | -- F); | |
ee6ba406 | 1766 | |
76a1c25b | 1767 | -- where T is the task object, I is the entry index, P are the |
1768 | -- wrapped parameters and F is the status flag. | |
ee6ba406 | 1769 | |
76a1c25b | 1770 | Append_To (Stmts, |
1771 | Make_Procedure_Call_Statement (Loc, | |
1772 | Name => | |
1773 | New_Reference_To (RTE (RE_Task_Entry_Call), Loc), | |
1774 | Parameter_Associations => | |
1775 | New_List ( | |
ee6ba406 | 1776 | |
76a1c25b | 1777 | Make_Selected_Component (Loc, -- T._task_id |
1778 | Prefix => | |
1779 | Make_Identifier (Loc, Name_uT), | |
1780 | Selector_Name => | |
1781 | Make_Identifier (Loc, Name_uTask_Id)), | |
ee6ba406 | 1782 | |
76a1c25b | 1783 | Make_Unchecked_Type_Conversion (Loc, -- entry index |
1784 | Subtype_Mark => | |
1785 | New_Reference_To (RTE (RE_Task_Entry_Index), Loc), | |
1786 | Expression => | |
1787 | Make_Identifier (Loc, Name_uI)), | |
ee6ba406 | 1788 | |
76a1c25b | 1789 | Make_Identifier (Loc, Name_uP), -- parameter block |
1790 | New_Reference_To ( -- Asynchronous_Call | |
1791 | RTE (RE_Asynchronous_Call), Loc), | |
1792 | Make_Identifier (Loc, Name_uF)))); -- status flag | |
1793 | end if; | |
76a1c25b | 1794 | end if; |
ee6ba406 | 1795 | |
76a1c25b | 1796 | return |
1797 | Make_Subprogram_Body (Loc, | |
1798 | Specification => | |
1799 | Make_Disp_Asynchronous_Select_Spec (Typ), | |
1800 | Declarations => | |
1801 | Decls, | |
1802 | Handled_Statement_Sequence => | |
1803 | Make_Handled_Sequence_Of_Statements (Loc, Stmts)); | |
1804 | end Make_Disp_Asynchronous_Select_Body; | |
ee6ba406 | 1805 | |
76a1c25b | 1806 | ---------------------------------------- |
1807 | -- Make_Disp_Asynchronous_Select_Spec -- | |
1808 | ---------------------------------------- | |
ee6ba406 | 1809 | |
76a1c25b | 1810 | function Make_Disp_Asynchronous_Select_Spec |
1811 | (Typ : Entity_Id) return Node_Id | |
1812 | is | |
1813 | Loc : constant Source_Ptr := Sloc (Typ); | |
1814 | Def_Id : constant Node_Id := | |
1815 | Make_Defining_Identifier (Loc, | |
1816 | Name_uDisp_Asynchronous_Select); | |
1817 | Params : constant List_Id := New_List; | |
ee6ba406 | 1818 | |
76a1c25b | 1819 | begin |
68f95949 | 1820 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
1821 | ||
76a1c25b | 1822 | -- "T" - Object parameter |
1823 | -- "S" - Primitive operation slot | |
1824 | -- "P" - Wrapped parameters | |
1825 | -- "B" - Communication block | |
1826 | -- "F" - Status flag | |
ee6ba406 | 1827 | |
76a1c25b | 1828 | SEU.Build_T (Loc, Typ, Params); |
1829 | SEU.Build_S (Loc, Params); | |
1830 | SEU.Build_P (Loc, Params); | |
1831 | SEU.Build_B (Loc, Params); | |
1832 | SEU.Build_F (Loc, Params); | |
ee6ba406 | 1833 | |
76a1c25b | 1834 | Set_Is_Internal (Def_Id); |
7189d17f | 1835 | |
76a1c25b | 1836 | return |
1837 | Make_Procedure_Specification (Loc, | |
1838 | Defining_Unit_Name => Def_Id, | |
1839 | Parameter_Specifications => Params); | |
1840 | end Make_Disp_Asynchronous_Select_Spec; | |
ee6ba406 | 1841 | |
76a1c25b | 1842 | --------------------------------------- |
1843 | -- Make_Disp_Conditional_Select_Body -- | |
1844 | --------------------------------------- | |
ee6ba406 | 1845 | |
76a1c25b | 1846 | function Make_Disp_Conditional_Select_Body |
1847 | (Typ : Entity_Id) return Node_Id | |
1848 | is | |
1849 | Loc : constant Source_Ptr := Sloc (Typ); | |
1850 | Blk_Nam : Entity_Id; | |
1851 | Conc_Typ : Entity_Id := Empty; | |
1852 | Decls : constant List_Id := New_List; | |
1853 | DT_Ptr : Entity_Id; | |
1854 | Stmts : constant List_Id := New_List; | |
ee6ba406 | 1855 | |
76a1c25b | 1856 | begin |
68f95949 | 1857 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
1858 | ||
952af0b9 | 1859 | -- Null body is generated for interface types |
1860 | ||
76a1c25b | 1861 | if Is_Interface (Typ) then |
1862 | return | |
1863 | Make_Subprogram_Body (Loc, | |
1864 | Specification => | |
1865 | Make_Disp_Conditional_Select_Spec (Typ), | |
1866 | Declarations => | |
1867 | No_List, | |
1868 | Handled_Statement_Sequence => | |
1869 | Make_Handled_Sequence_Of_Statements (Loc, | |
1870 | New_List (Make_Null_Statement (Loc)))); | |
1871 | end if; | |
ee6ba406 | 1872 | |
76a1c25b | 1873 | DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); |
ee6ba406 | 1874 | |
952af0b9 | 1875 | if Is_Concurrent_Record_Type (Typ) then |
1876 | Conc_Typ := Corresponding_Concurrent_Type (Typ); | |
ee6ba406 | 1877 | |
76a1c25b | 1878 | -- Generate: |
1879 | -- I : Integer; | |
ee6ba406 | 1880 | |
76a1c25b | 1881 | -- where I will be used to capture the entry index of the primitive |
1882 | -- wrapper at position S. | |
ee6ba406 | 1883 | |
76a1c25b | 1884 | Append_To (Decls, |
1885 | Make_Object_Declaration (Loc, | |
1886 | Defining_Identifier => | |
1887 | Make_Defining_Identifier (Loc, Name_uI), | |
1888 | Object_Definition => | |
1889 | New_Reference_To (Standard_Integer, Loc))); | |
ee6ba406 | 1890 | |
952af0b9 | 1891 | -- Generate: |
1892 | -- C := Get_Prim_Op_Kind (tag! (<type>VP), S); | |
ee6ba406 | 1893 | |
952af0b9 | 1894 | -- if C = POK_Procedure |
1895 | -- or else C = POK_Protected_Procedure | |
1896 | -- or else C = POK_Task_Procedure; | |
1897 | -- then | |
1898 | -- F := True; | |
1899 | -- return; | |
1900 | -- end if; | |
aad6babd | 1901 | |
952af0b9 | 1902 | SEU.Build_Common_Dispatching_Select_Statements |
1903 | (Loc, Typ, DT_Ptr, Stmts); | |
aad6babd | 1904 | |
76a1c25b | 1905 | -- Generate: |
1906 | -- Bnn : Communication_Block; | |
aad6babd | 1907 | |
76a1c25b | 1908 | -- where Bnn is the name of the communication block used in |
1909 | -- the call to Protected_Entry_Call. | |
aad6babd | 1910 | |
76a1c25b | 1911 | Blk_Nam := Make_Defining_Identifier (Loc, New_Internal_Name ('B')); |
aad6babd | 1912 | |
76a1c25b | 1913 | Append_To (Decls, |
1914 | Make_Object_Declaration (Loc, | |
1915 | Defining_Identifier => | |
1916 | Blk_Nam, | |
1917 | Object_Definition => | |
1918 | New_Reference_To (RTE (RE_Communication_Block), Loc))); | |
aad6babd | 1919 | |
76a1c25b | 1920 | -- Generate: |
952af0b9 | 1921 | -- I := Get_Entry_Index (tag! (<type>VP), S); |
aad6babd | 1922 | |
76a1c25b | 1923 | -- I is the entry index and S is the dispatch table slot |
aad6babd | 1924 | |
76a1c25b | 1925 | Append_To (Stmts, |
1926 | Make_Assignment_Statement (Loc, | |
1927 | Name => | |
1928 | Make_Identifier (Loc, Name_uI), | |
1929 | Expression => | |
1930 | Make_DT_Access_Action (Typ, | |
1931 | Action => | |
1932 | Get_Entry_Index, | |
1933 | Args => | |
1934 | New_List ( | |
1935 | Unchecked_Convert_To (RTE (RE_Tag), | |
1936 | New_Reference_To (DT_Ptr, Loc)), | |
1937 | Make_Identifier (Loc, Name_uS))))); | |
ee6ba406 | 1938 | |
76a1c25b | 1939 | if Ekind (Conc_Typ) = E_Protected_Type then |
ee6ba406 | 1940 | |
76a1c25b | 1941 | -- Generate: |
1942 | -- Protected_Entry_Call ( | |
1943 | -- T._object'access, | |
1944 | -- protected_entry_index! (I), | |
1945 | -- P, | |
1946 | -- Conditional_Call, | |
1947 | -- Bnn); | |
ee6ba406 | 1948 | |
76a1c25b | 1949 | -- where T is the protected object, I is the entry index, P are |
1950 | -- the wrapped parameters and Bnn is the name of the communication | |
1951 | -- block. | |
e1c20931 | 1952 | |
76a1c25b | 1953 | Append_To (Stmts, |
1954 | Make_Procedure_Call_Statement (Loc, | |
1955 | Name => | |
1956 | New_Reference_To (RTE (RE_Protected_Entry_Call), Loc), | |
1957 | Parameter_Associations => | |
1958 | New_List ( | |
e1c20931 | 1959 | |
76a1c25b | 1960 | Make_Attribute_Reference (Loc, -- T._object'access |
1961 | Attribute_Name => | |
1962 | Name_Unchecked_Access, | |
1963 | Prefix => | |
1964 | Make_Selected_Component (Loc, | |
1965 | Prefix => | |
1966 | Make_Identifier (Loc, Name_uT), | |
1967 | Selector_Name => | |
1968 | Make_Identifier (Loc, Name_uObject))), | |
d62940bf | 1969 | |
76a1c25b | 1970 | Make_Unchecked_Type_Conversion (Loc, -- entry index |
1971 | Subtype_Mark => | |
1972 | New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), | |
1973 | Expression => | |
1974 | Make_Identifier (Loc, Name_uI)), | |
d62940bf | 1975 | |
76a1c25b | 1976 | Make_Identifier (Loc, Name_uP), -- parameter block |
1977 | New_Reference_To ( -- Conditional_Call | |
1978 | RTE (RE_Conditional_Call), Loc), | |
1979 | New_Reference_To ( -- Bnn | |
1980 | Blk_Nam, Loc)))); | |
d62940bf | 1981 | |
76a1c25b | 1982 | -- Generate: |
1983 | -- F := not Cancelled (Bnn); | |
e1c20931 | 1984 | |
76a1c25b | 1985 | -- where F is the success flag. The status of Cancelled is negated |
1986 | -- in order to match the behaviour of the version for task types. | |
e1c20931 | 1987 | |
76a1c25b | 1988 | Append_To (Stmts, |
1989 | Make_Assignment_Statement (Loc, | |
1990 | Name => | |
1991 | Make_Identifier (Loc, Name_uF), | |
1992 | Expression => | |
1993 | Make_Op_Not (Loc, | |
1994 | Right_Opnd => | |
1995 | Make_Function_Call (Loc, | |
1996 | Name => | |
1997 | New_Reference_To (RTE (RE_Cancelled), Loc), | |
1998 | Parameter_Associations => | |
1999 | New_List ( | |
2000 | New_Reference_To (Blk_Nam, Loc)))))); | |
2001 | else | |
2002 | pragma Assert (Ekind (Conc_Typ) = E_Task_Type); | |
d62940bf | 2003 | |
76a1c25b | 2004 | -- Generate: |
2005 | -- Protected_Entry_Call ( | |
2006 | -- T._task_id, | |
2007 | -- task_entry_index! (I), | |
2008 | -- P, | |
2009 | -- Conditional_Call, | |
2010 | -- F); | |
d62940bf | 2011 | |
76a1c25b | 2012 | -- where T is the task object, I is the entry index, P are the |
2013 | -- wrapped parameters and F is the status flag. | |
e1c20931 | 2014 | |
76a1c25b | 2015 | Append_To (Stmts, |
2016 | Make_Procedure_Call_Statement (Loc, | |
2017 | Name => | |
2018 | New_Reference_To (RTE (RE_Task_Entry_Call), Loc), | |
2019 | Parameter_Associations => | |
2020 | New_List ( | |
2021 | ||
2022 | Make_Selected_Component (Loc, -- T._task_id | |
2023 | Prefix => | |
2024 | Make_Identifier (Loc, Name_uT), | |
2025 | Selector_Name => | |
2026 | Make_Identifier (Loc, Name_uTask_Id)), | |
2027 | ||
2028 | Make_Unchecked_Type_Conversion (Loc, -- entry index | |
2029 | Subtype_Mark => | |
2030 | New_Reference_To (RTE (RE_Task_Entry_Index), Loc), | |
2031 | Expression => | |
2032 | Make_Identifier (Loc, Name_uI)), | |
2033 | ||
2034 | Make_Identifier (Loc, Name_uP), -- parameter block | |
2035 | New_Reference_To ( -- Conditional_Call | |
2036 | RTE (RE_Conditional_Call), Loc), | |
2037 | Make_Identifier (Loc, Name_uF)))); -- status flag | |
d62940bf | 2038 | end if; |
76a1c25b | 2039 | end if; |
2040 | ||
2041 | return | |
2042 | Make_Subprogram_Body (Loc, | |
2043 | Specification => | |
2044 | Make_Disp_Conditional_Select_Spec (Typ), | |
2045 | Declarations => | |
2046 | Decls, | |
2047 | Handled_Statement_Sequence => | |
2048 | Make_Handled_Sequence_Of_Statements (Loc, Stmts)); | |
2049 | end Make_Disp_Conditional_Select_Body; | |
2050 | ||
2051 | --------------------------------------- | |
2052 | -- Make_Disp_Conditional_Select_Spec -- | |
2053 | --------------------------------------- | |
2054 | ||
2055 | function Make_Disp_Conditional_Select_Spec | |
2056 | (Typ : Entity_Id) return Node_Id | |
2057 | is | |
2058 | Loc : constant Source_Ptr := Sloc (Typ); | |
2059 | Def_Id : constant Node_Id := | |
2060 | Make_Defining_Identifier (Loc, | |
2061 | Name_uDisp_Conditional_Select); | |
2062 | Params : constant List_Id := New_List; | |
2063 | ||
2064 | begin | |
68f95949 | 2065 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2066 | ||
76a1c25b | 2067 | -- "T" - Object parameter |
2068 | -- "S" - Primitive operation slot | |
2069 | -- "P" - Wrapped parameters | |
2070 | -- "C" - Call kind | |
2071 | -- "F" - Status flag | |
2072 | ||
2073 | SEU.Build_T (Loc, Typ, Params); | |
2074 | SEU.Build_S (Loc, Params); | |
2075 | SEU.Build_P (Loc, Params); | |
2076 | SEU.Build_C (Loc, Params); | |
2077 | SEU.Build_F (Loc, Params); | |
2078 | ||
2079 | Set_Is_Internal (Def_Id); | |
2080 | ||
2081 | return | |
2082 | Make_Procedure_Specification (Loc, | |
2083 | Defining_Unit_Name => Def_Id, | |
2084 | Parameter_Specifications => Params); | |
2085 | end Make_Disp_Conditional_Select_Spec; | |
2086 | ||
2087 | ------------------------------------- | |
2088 | -- Make_Disp_Get_Prim_Op_Kind_Body -- | |
2089 | ------------------------------------- | |
2090 | ||
2091 | function Make_Disp_Get_Prim_Op_Kind_Body | |
2092 | (Typ : Entity_Id) return Node_Id | |
2093 | is | |
2094 | Loc : constant Source_Ptr := Sloc (Typ); | |
2095 | DT_Ptr : Entity_Id; | |
2096 | ||
2097 | begin | |
68f95949 | 2098 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2099 | ||
76a1c25b | 2100 | if Is_Interface (Typ) then |
2101 | return | |
2102 | Make_Subprogram_Body (Loc, | |
2103 | Specification => | |
2104 | Make_Disp_Get_Prim_Op_Kind_Spec (Typ), | |
2105 | Declarations => | |
2106 | New_List, | |
2107 | Handled_Statement_Sequence => | |
2108 | Make_Handled_Sequence_Of_Statements (Loc, | |
2109 | New_List (Make_Null_Statement (Loc)))); | |
e1c20931 | 2110 | end if; |
2111 | ||
76a1c25b | 2112 | DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); |
2113 | ||
d62940bf | 2114 | -- Generate: |
76a1c25b | 2115 | -- C := get_prim_op_kind (tag! (<type>VP), S); |
ee6ba406 | 2116 | |
76a1c25b | 2117 | -- where C is the out parameter capturing the call kind and S is the |
2118 | -- dispatch table slot number. | |
ee6ba406 | 2119 | |
76a1c25b | 2120 | return |
2121 | Make_Subprogram_Body (Loc, | |
2122 | Specification => | |
2123 | Make_Disp_Get_Prim_Op_Kind_Spec (Typ), | |
2124 | Declarations => | |
2125 | New_List, | |
2126 | Handled_Statement_Sequence => | |
2127 | Make_Handled_Sequence_Of_Statements (Loc, | |
2128 | New_List ( | |
2129 | Make_Assignment_Statement (Loc, | |
2130 | Name => | |
2131 | Make_Identifier (Loc, Name_uC), | |
2132 | Expression => | |
2133 | Make_DT_Access_Action (Typ, | |
2134 | Action => | |
2135 | Get_Prim_Op_Kind, | |
2136 | Args => | |
2137 | New_List ( | |
2138 | Unchecked_Convert_To (RTE (RE_Tag), | |
2139 | New_Reference_To (DT_Ptr, Loc)), | |
2140 | Make_Identifier (Loc, Name_uS))))))); | |
2141 | end Make_Disp_Get_Prim_Op_Kind_Body; | |
e1c20931 | 2142 | |
76a1c25b | 2143 | ------------------------------------- |
2144 | -- Make_Disp_Get_Prim_Op_Kind_Spec -- | |
2145 | ------------------------------------- | |
e1c20931 | 2146 | |
76a1c25b | 2147 | function Make_Disp_Get_Prim_Op_Kind_Spec |
2148 | (Typ : Entity_Id) return Node_Id | |
2149 | is | |
2150 | Loc : constant Source_Ptr := Sloc (Typ); | |
2151 | Def_Id : constant Node_Id := | |
2152 | Make_Defining_Identifier (Loc, | |
2153 | Name_uDisp_Get_Prim_Op_Kind); | |
2154 | Params : constant List_Id := New_List; | |
e1c20931 | 2155 | |
76a1c25b | 2156 | begin |
68f95949 | 2157 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2158 | ||
76a1c25b | 2159 | -- "T" - Object parameter |
2160 | -- "S" - Primitive operation slot | |
2161 | -- "C" - Call kind | |
ee6ba406 | 2162 | |
76a1c25b | 2163 | SEU.Build_T (Loc, Typ, Params); |
2164 | SEU.Build_S (Loc, Params); | |
2165 | SEU.Build_C (Loc, Params); | |
ee6ba406 | 2166 | |
76a1c25b | 2167 | Set_Is_Internal (Def_Id); |
2168 | ||
2169 | return | |
2170 | Make_Procedure_Specification (Loc, | |
2171 | Defining_Unit_Name => Def_Id, | |
2172 | Parameter_Specifications => Params); | |
2173 | end Make_Disp_Get_Prim_Op_Kind_Spec; | |
2174 | ||
2175 | -------------------------------- | |
2176 | -- Make_Disp_Get_Task_Id_Body -- | |
2177 | -------------------------------- | |
2178 | ||
2179 | function Make_Disp_Get_Task_Id_Body | |
2180 | (Typ : Entity_Id) return Node_Id | |
2181 | is | |
2182 | Loc : constant Source_Ptr := Sloc (Typ); | |
2183 | Ret : Node_Id; | |
2184 | ||
2185 | begin | |
68f95949 | 2186 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2187 | ||
76a1c25b | 2188 | if Is_Concurrent_Record_Type (Typ) |
2189 | and then Ekind (Corresponding_Concurrent_Type (Typ)) = E_Task_Type | |
2190 | then | |
2191 | Ret := | |
2192 | Make_Return_Statement (Loc, | |
2193 | Expression => | |
2194 | Make_Selected_Component (Loc, | |
2195 | Prefix => | |
2196 | Make_Identifier (Loc, Name_uT), | |
2197 | Selector_Name => | |
2198 | Make_Identifier (Loc, Name_uTask_Id))); | |
2199 | ||
2200 | -- A null body is constructed for non-task types | |
2201 | ||
2202 | else | |
2203 | Ret := | |
2204 | Make_Return_Statement (Loc, | |
2205 | Expression => | |
2206 | New_Reference_To (RTE (RO_ST_Null_Task), Loc)); | |
2207 | end if; | |
2208 | ||
2209 | return | |
2210 | Make_Subprogram_Body (Loc, | |
2211 | Specification => | |
2212 | Make_Disp_Get_Task_Id_Spec (Typ), | |
2213 | Declarations => | |
2214 | New_List, | |
2215 | Handled_Statement_Sequence => | |
2216 | Make_Handled_Sequence_Of_Statements (Loc, | |
2217 | New_List (Ret))); | |
2218 | end Make_Disp_Get_Task_Id_Body; | |
2219 | ||
2220 | -------------------------------- | |
2221 | -- Make_Disp_Get_Task_Id_Spec -- | |
2222 | -------------------------------- | |
2223 | ||
2224 | function Make_Disp_Get_Task_Id_Spec | |
2225 | (Typ : Entity_Id) return Node_Id | |
2226 | is | |
2227 | Loc : constant Source_Ptr := Sloc (Typ); | |
2228 | Def_Id : constant Node_Id := | |
2229 | Make_Defining_Identifier (Loc, | |
2230 | Name_uDisp_Get_Task_Id); | |
2231 | ||
2232 | begin | |
68f95949 | 2233 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2234 | ||
76a1c25b | 2235 | Set_Is_Internal (Def_Id); |
2236 | ||
2237 | return | |
2238 | Make_Function_Specification (Loc, | |
2239 | Defining_Unit_Name => Def_Id, | |
2240 | Parameter_Specifications => New_List ( | |
2241 | Make_Parameter_Specification (Loc, | |
2242 | Defining_Identifier => | |
2243 | Make_Defining_Identifier (Loc, Name_uT), | |
2244 | Parameter_Type => | |
2245 | New_Reference_To (Typ, Loc))), | |
2246 | Result_Definition => | |
2247 | New_Reference_To (RTE (RO_ST_Task_Id), Loc)); | |
2248 | end Make_Disp_Get_Task_Id_Spec; | |
2249 | ||
2250 | --------------------------------- | |
2251 | -- Make_Disp_Timed_Select_Body -- | |
2252 | --------------------------------- | |
2253 | ||
2254 | function Make_Disp_Timed_Select_Body | |
2255 | (Typ : Entity_Id) return Node_Id | |
2256 | is | |
2257 | Loc : constant Source_Ptr := Sloc (Typ); | |
2258 | Conc_Typ : Entity_Id := Empty; | |
2259 | Decls : constant List_Id := New_List; | |
2260 | DT_Ptr : Entity_Id; | |
2261 | Stmts : constant List_Id := New_List; | |
2262 | ||
2263 | begin | |
68f95949 | 2264 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2265 | ||
952af0b9 | 2266 | -- Null body is generated for interface types |
2267 | ||
76a1c25b | 2268 | if Is_Interface (Typ) then |
2269 | return | |
2270 | Make_Subprogram_Body (Loc, | |
2271 | Specification => | |
2272 | Make_Disp_Timed_Select_Spec (Typ), | |
2273 | Declarations => | |
2274 | New_List, | |
2275 | Handled_Statement_Sequence => | |
2276 | Make_Handled_Sequence_Of_Statements (Loc, | |
2277 | New_List (Make_Null_Statement (Loc)))); | |
2278 | end if; | |
2279 | ||
76a1c25b | 2280 | DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); |
2281 | ||
952af0b9 | 2282 | if Is_Concurrent_Record_Type (Typ) then |
2283 | Conc_Typ := Corresponding_Concurrent_Type (Typ); | |
76a1c25b | 2284 | |
2285 | -- Generate: | |
2286 | -- I : Integer; | |
2287 | ||
2288 | -- where I will be used to capture the entry index of the primitive | |
2289 | -- wrapper at position S. | |
2290 | ||
2291 | Append_To (Decls, | |
2292 | Make_Object_Declaration (Loc, | |
2293 | Defining_Identifier => | |
2294 | Make_Defining_Identifier (Loc, Name_uI), | |
2295 | Object_Definition => | |
2296 | New_Reference_To (Standard_Integer, Loc))); | |
76a1c25b | 2297 | |
952af0b9 | 2298 | -- Generate: |
2299 | -- C := Get_Prim_Op_Kind (tag! (<type>VP), S); | |
76a1c25b | 2300 | |
952af0b9 | 2301 | -- if C = POK_Procedure |
2302 | -- or else C = POK_Protected_Procedure | |
2303 | -- or else C = POK_Task_Procedure; | |
2304 | -- then | |
2305 | -- F := True; | |
2306 | -- return; | |
2307 | -- end if; | |
76a1c25b | 2308 | |
952af0b9 | 2309 | SEU.Build_Common_Dispatching_Select_Statements |
2310 | (Loc, Typ, DT_Ptr, Stmts); | |
76a1c25b | 2311 | |
2312 | -- Generate: | |
952af0b9 | 2313 | -- I := Get_Entry_Index (tag! (<type>VP), S); |
76a1c25b | 2314 | |
2315 | -- I is the entry index and S is the dispatch table slot | |
2316 | ||
2317 | Append_To (Stmts, | |
2318 | Make_Assignment_Statement (Loc, | |
2319 | Name => | |
2320 | Make_Identifier (Loc, Name_uI), | |
2321 | Expression => | |
2322 | Make_DT_Access_Action (Typ, | |
2323 | Action => | |
2324 | Get_Entry_Index, | |
2325 | Args => | |
2326 | New_List ( | |
2327 | Unchecked_Convert_To (RTE (RE_Tag), | |
2328 | New_Reference_To (DT_Ptr, Loc)), | |
2329 | Make_Identifier (Loc, Name_uS))))); | |
2330 | ||
2331 | if Ekind (Conc_Typ) = E_Protected_Type then | |
2332 | ||
2333 | -- Generate: | |
2334 | -- Timed_Protected_Entry_Call ( | |
2335 | -- T._object'access, | |
2336 | -- protected_entry_index! (I), | |
2337 | -- P, | |
2338 | -- D, | |
2339 | -- M, | |
2340 | -- F); | |
2341 | ||
2342 | -- where T is the protected object, I is the entry index, P are | |
2343 | -- the wrapped parameters, D is the delay amount, M is the delay | |
2344 | -- mode and F is the status flag. | |
2345 | ||
2346 | Append_To (Stmts, | |
2347 | Make_Procedure_Call_Statement (Loc, | |
2348 | Name => | |
2349 | New_Reference_To (RTE (RE_Timed_Protected_Entry_Call), Loc), | |
2350 | Parameter_Associations => | |
2351 | New_List ( | |
2352 | ||
2353 | Make_Attribute_Reference (Loc, -- T._object'access | |
2354 | Attribute_Name => | |
2355 | Name_Unchecked_Access, | |
2356 | Prefix => | |
2357 | Make_Selected_Component (Loc, | |
2358 | Prefix => | |
2359 | Make_Identifier (Loc, Name_uT), | |
2360 | Selector_Name => | |
2361 | Make_Identifier (Loc, Name_uObject))), | |
2362 | ||
2363 | Make_Unchecked_Type_Conversion (Loc, -- entry index | |
2364 | Subtype_Mark => | |
2365 | New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), | |
2366 | Expression => | |
2367 | Make_Identifier (Loc, Name_uI)), | |
2368 | ||
2369 | Make_Identifier (Loc, Name_uP), -- parameter block | |
2370 | Make_Identifier (Loc, Name_uD), -- delay | |
2371 | Make_Identifier (Loc, Name_uM), -- delay mode | |
2372 | Make_Identifier (Loc, Name_uF)))); -- status flag | |
ee6ba406 | 2373 | |
ee6ba406 | 2374 | else |
76a1c25b | 2375 | pragma Assert (Ekind (Conc_Typ) = E_Task_Type); |
2376 | ||
2377 | -- Generate: | |
2378 | -- Timed_Task_Entry_Call ( | |
2379 | -- T._task_id, | |
2380 | -- task_entry_index! (I), | |
2381 | -- P, | |
2382 | -- D, | |
2383 | -- M, | |
2384 | -- F); | |
2385 | ||
2386 | -- where T is the task object, I is the entry index, P are the | |
2387 | -- wrapped parameters, D is the delay amount, M is the delay | |
2388 | -- mode and F is the status flag. | |
2389 | ||
2390 | Append_To (Stmts, | |
2391 | Make_Procedure_Call_Statement (Loc, | |
2392 | Name => | |
2393 | New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc), | |
2394 | Parameter_Associations => | |
2395 | New_List ( | |
2396 | ||
2397 | Make_Selected_Component (Loc, -- T._task_id | |
2398 | Prefix => | |
2399 | Make_Identifier (Loc, Name_uT), | |
2400 | Selector_Name => | |
2401 | Make_Identifier (Loc, Name_uTask_Id)), | |
2402 | ||
2403 | Make_Unchecked_Type_Conversion (Loc, -- entry index | |
2404 | Subtype_Mark => | |
2405 | New_Reference_To (RTE (RE_Task_Entry_Index), Loc), | |
2406 | Expression => | |
2407 | Make_Identifier (Loc, Name_uI)), | |
2408 | ||
2409 | Make_Identifier (Loc, Name_uP), -- parameter block | |
2410 | Make_Identifier (Loc, Name_uD), -- delay | |
2411 | Make_Identifier (Loc, Name_uM), -- delay mode | |
2412 | Make_Identifier (Loc, Name_uF)))); -- status flag | |
ee6ba406 | 2413 | end if; |
76a1c25b | 2414 | end if; |
2415 | ||
2416 | return | |
2417 | Make_Subprogram_Body (Loc, | |
2418 | Specification => | |
2419 | Make_Disp_Timed_Select_Spec (Typ), | |
2420 | Declarations => | |
2421 | Decls, | |
2422 | Handled_Statement_Sequence => | |
2423 | Make_Handled_Sequence_Of_Statements (Loc, Stmts)); | |
2424 | end Make_Disp_Timed_Select_Body; | |
2425 | ||
2426 | --------------------------------- | |
2427 | -- Make_Disp_Timed_Select_Spec -- | |
2428 | --------------------------------- | |
2429 | ||
2430 | function Make_Disp_Timed_Select_Spec | |
2431 | (Typ : Entity_Id) return Node_Id | |
2432 | is | |
2433 | Loc : constant Source_Ptr := Sloc (Typ); | |
2434 | Def_Id : constant Node_Id := | |
2435 | Make_Defining_Identifier (Loc, | |
2436 | Name_uDisp_Timed_Select); | |
2437 | Params : constant List_Id := New_List; | |
ee6ba406 | 2438 | |
76a1c25b | 2439 | begin |
68f95949 | 2440 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
2441 | ||
76a1c25b | 2442 | -- "T" - Object parameter |
2443 | -- "S" - Primitive operation slot | |
2444 | -- "P" - Wrapped parameters | |
2445 | -- "D" - Delay | |
2446 | -- "M" - Delay Mode | |
2447 | -- "C" - Call kind | |
2448 | -- "F" - Status flag | |
2449 | ||
2450 | SEU.Build_T (Loc, Typ, Params); | |
2451 | SEU.Build_S (Loc, Params); | |
2452 | SEU.Build_P (Loc, Params); | |
2453 | ||
2454 | Append_To (Params, | |
2455 | Make_Parameter_Specification (Loc, | |
2456 | Defining_Identifier => | |
2457 | Make_Defining_Identifier (Loc, Name_uD), | |
2458 | Parameter_Type => | |
2459 | New_Reference_To (Standard_Duration, Loc))); | |
2460 | ||
2461 | Append_To (Params, | |
2462 | Make_Parameter_Specification (Loc, | |
2463 | Defining_Identifier => | |
2464 | Make_Defining_Identifier (Loc, Name_uM), | |
2465 | Parameter_Type => | |
2466 | New_Reference_To (Standard_Integer, Loc))); | |
ee6ba406 | 2467 | |
76a1c25b | 2468 | SEU.Build_C (Loc, Params); |
2469 | SEU.Build_F (Loc, Params); | |
ee6ba406 | 2470 | |
76a1c25b | 2471 | Set_Is_Internal (Def_Id); |
ee6ba406 | 2472 | |
76a1c25b | 2473 | return |
2474 | Make_Procedure_Specification (Loc, | |
2475 | Defining_Unit_Name => Def_Id, | |
2476 | Parameter_Specifications => Params); | |
2477 | end Make_Disp_Timed_Select_Spec; | |
ee6ba406 | 2478 | |
76a1c25b | 2479 | ------------- |
2480 | -- Make_DT -- | |
2481 | ------------- | |
ee6ba406 | 2482 | |
76a1c25b | 2483 | function Make_DT (Typ : Entity_Id) return List_Id is |
2484 | Loc : constant Source_Ptr := Sloc (Typ); | |
2485 | Result : constant List_Id := New_List; | |
2486 | Elab_Code : constant List_Id := New_List; | |
ee6ba406 | 2487 | |
76a1c25b | 2488 | Tname : constant Name_Id := Chars (Typ); |
2489 | Name_DT : constant Name_Id := New_External_Name (Tname, 'T'); | |
2490 | Name_DT_Ptr : constant Name_Id := New_External_Name (Tname, 'P'); | |
2491 | Name_SSD : constant Name_Id := New_External_Name (Tname, 'S'); | |
2492 | Name_TSD : constant Name_Id := New_External_Name (Tname, 'B'); | |
2493 | Name_Exname : constant Name_Id := New_External_Name (Tname, 'E'); | |
2494 | Name_No_Reg : constant Name_Id := New_External_Name (Tname, 'F'); | |
343d35dc | 2495 | |
2496 | -- The following external name is only generated if Typ has interfaces | |
952af0b9 | 2497 | Name_ITable : Name_Id; |
ee6ba406 | 2498 | |
76a1c25b | 2499 | DT : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT); |
2500 | DT_Ptr : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT_Ptr); | |
2501 | SSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_SSD); | |
2502 | TSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_TSD); | |
2503 | Exname : constant Node_Id := Make_Defining_Identifier (Loc, Name_Exname); | |
2504 | No_Reg : constant Node_Id := Make_Defining_Identifier (Loc, Name_No_Reg); | |
952af0b9 | 2505 | |
343d35dc | 2506 | Generalized_Tag : constant Entity_Id := RTE (RE_Tag); |
2507 | Ancestor_Ifaces : Elist_Id; | |
2508 | AI : Elmt_Id; | |
2509 | Has_Dispatch_Table : Boolean := True; | |
2510 | I_Depth : Nat := 0; | |
2511 | ITable : Node_Id; | |
2512 | Iface_Table_Node : Node_Id; | |
2513 | Nb_Prim : Nat := 0; | |
2514 | Null_Parent_Tag : Boolean := False; | |
2515 | Num_Ifaces : Nat := 0; | |
2516 | Old_Tag1 : Node_Id; | |
2517 | Old_Tag2 : Node_Id; | |
2518 | Parent : Entity_Id; | |
2519 | Parent_Num_Ifaces : Nat := 0; | |
2520 | Remotely_Callable : Entity_Id; | |
2521 | RC_Offset_Node : Node_Id; | |
2522 | Size_Expr_Node : Node_Id; | |
2523 | Typ_Ifaces : Elist_Id; | |
2524 | TSD_Aggr_List : List_Id; | |
9dfe12ae | 2525 | |
76a1c25b | 2526 | begin |
2527 | if not RTE_Available (RE_Tag) then | |
2528 | Error_Msg_CRT ("tagged types", Typ); | |
2529 | return New_List; | |
ee6ba406 | 2530 | end if; |
2531 | ||
343d35dc | 2532 | -- Ensure that the unit System_Storage_Elements is loaded. This is |
2533 | -- required to properly expand the routines of Ada.Tags | |
2534 | ||
2535 | if not RTU_Loaded (System_Storage_Elements) | |
2536 | and then not Present (RTE (RE_Storage_Offset)) | |
2537 | then | |
2538 | raise Program_Error; | |
2539 | end if; | |
2540 | ||
2541 | if Ada_Version >= Ada_05 then | |
2542 | ||
2543 | -- Count the interface types of the parents | |
2544 | ||
2545 | Parent := Empty; | |
2546 | ||
2547 | if Typ /= Etype (Typ) then | |
2548 | Parent := Etype (Typ); | |
2549 | ||
2550 | elsif Is_Concurrent_Record_Type (Typ) then | |
2551 | Parent := Etype (First (Abstract_Interface_List (Typ))); | |
2552 | end if; | |
2553 | ||
2554 | if Present (Parent) then | |
2555 | Collect_Abstract_Interfaces (Parent, Ancestor_Ifaces); | |
68f95949 | 2556 | |
343d35dc | 2557 | AI := First_Elmt (Ancestor_Ifaces); |
2558 | while Present (AI) loop | |
2559 | Parent_Num_Ifaces := Parent_Num_Ifaces + 1; | |
2560 | Next_Elmt (AI); | |
2561 | end loop; | |
2562 | end if; | |
aad6babd | 2563 | |
343d35dc | 2564 | -- Count the additional interfaces implemented by Typ |
76a1c25b | 2565 | |
343d35dc | 2566 | Collect_Abstract_Interfaces (Typ, Typ_Ifaces); |
952af0b9 | 2567 | |
343d35dc | 2568 | AI := First_Elmt (Typ_Ifaces); |
af647dc7 | 2569 | while Present (AI) loop |
343d35dc | 2570 | Num_Ifaces := Num_Ifaces + 1; |
af647dc7 | 2571 | Next_Elmt (AI); |
2572 | end loop; | |
2573 | end if; | |
952af0b9 | 2574 | |
af647dc7 | 2575 | -- Count ancestors to compute the inheritance depth. For private |
2576 | -- extensions, always go to the full view in order to compute the | |
2577 | -- real inheritance depth. | |
76a1c25b | 2578 | |
af647dc7 | 2579 | declare |
2580 | Parent_Type : Entity_Id := Typ; | |
2581 | P : Entity_Id; | |
aad6babd | 2582 | |
af647dc7 | 2583 | begin |
2584 | I_Depth := 0; | |
2585 | loop | |
2586 | P := Etype (Parent_Type); | |
aad6babd | 2587 | |
af647dc7 | 2588 | if Is_Private_Type (P) then |
2589 | P := Full_View (Base_Type (P)); | |
2590 | end if; | |
aad6babd | 2591 | |
af647dc7 | 2592 | exit when P = Parent_Type; |
aad6babd | 2593 | |
af647dc7 | 2594 | I_Depth := I_Depth + 1; |
2595 | Parent_Type := P; | |
2596 | end loop; | |
2597 | end; | |
ee6ba406 | 2598 | |
343d35dc | 2599 | -- Calculate the number of primitives of the dispatch table and the |
2600 | -- size of the Type_Specific_Data record. | |
aad6babd | 2601 | |
343d35dc | 2602 | -- Abstract interfaces don't need the dispatch table. In addition, |
2603 | -- compiling with restriction No_Dispatching_Calls we do not generate | |
2604 | -- the dispatch table. | |
aad6babd | 2605 | |
343d35dc | 2606 | Has_Dispatch_Table := |
2607 | not Is_Interface (Typ) | |
2608 | and then not Restriction_Active (No_Dispatching_Calls); | |
aad6babd | 2609 | |
343d35dc | 2610 | if Has_Dispatch_Table then |
2611 | Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))); | |
76a1c25b | 2612 | end if; |
aad6babd | 2613 | |
2614 | -- Dispatch table and related entities are allocated statically | |
2615 | ||
76a1c25b | 2616 | Set_Ekind (DT, E_Variable); |
2617 | Set_Is_Statically_Allocated (DT); | |
aad6babd | 2618 | |
76a1c25b | 2619 | Set_Ekind (DT_Ptr, E_Variable); |
2620 | Set_Is_Statically_Allocated (DT_Ptr); | |
aad6babd | 2621 | |
af647dc7 | 2622 | if Num_Ifaces > 0 then |
952af0b9 | 2623 | Name_ITable := New_External_Name (Tname, 'I'); |
2624 | ITable := Make_Defining_Identifier (Loc, Name_ITable); | |
2625 | ||
2626 | Set_Ekind (ITable, E_Variable); | |
2627 | Set_Is_Statically_Allocated (ITable); | |
2628 | end if; | |
2629 | ||
76a1c25b | 2630 | Set_Ekind (SSD, E_Variable); |
2631 | Set_Is_Statically_Allocated (SSD); | |
aad6babd | 2632 | |
76a1c25b | 2633 | Set_Ekind (TSD, E_Variable); |
2634 | Set_Is_Statically_Allocated (TSD); | |
aad6babd | 2635 | |
76a1c25b | 2636 | Set_Ekind (Exname, E_Variable); |
2637 | Set_Is_Statically_Allocated (Exname); | |
2638 | ||
2639 | Set_Ekind (No_Reg, E_Variable); | |
2640 | Set_Is_Statically_Allocated (No_Reg); | |
2641 | ||
2642 | -- Generate code to create the storage for the Dispatch_Table object: | |
2643 | ||
343d35dc | 2644 | -- DT : Storage_Array (1 .. Size_Expr); |
76a1c25b | 2645 | -- for DT'Alignment use Address'Alignment |
aad6babd | 2646 | |
343d35dc | 2647 | -- Under No_Dispatching_Calls the size of the table is small just |
2648 | -- containing: | |
2649 | -- 1) the pointer to the TSD | |
2650 | -- 2) a dummy entry used as the Tag of the type (see a-tags.ads). | |
2651 | ||
2652 | if not Has_Dispatch_Table then | |
2653 | Size_Expr_Node := | |
2654 | New_Reference_To (RTE (RE_DT_Min_Prologue_Size), Loc); | |
2655 | ||
2656 | -- If the object has no primitives we ensure that the table will | |
2657 | -- have at least a dummy entry which will be used as the Tag. | |
2658 | ||
2659 | -- Size_Expr := DT_Prologue_Size + DT_Entry_Size | |
2660 | ||
2661 | elsif Nb_Prim = 0 then | |
2662 | Size_Expr_Node := | |
2663 | Make_Op_Add (Loc, | |
2664 | Left_Opnd => | |
2665 | New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), | |
2666 | Right_Opnd => | |
2667 | New_Reference_To (RTE (RE_DT_Entry_Size), Loc)); | |
2668 | ||
2669 | -- Common case. The dispatch table has space to save the pointers to | |
2670 | -- all the predefined primitives, the C++ ABI header of the DT, and | |
2671 | -- the pointers to the primitives of Typ. That is, | |
2672 | ||
2673 | -- Size_Expr := DT_Prologue_Size + nb_prim * DT_Entry_Size | |
2674 | ||
2675 | else | |
2676 | Size_Expr_Node := | |
2677 | Make_Op_Add (Loc, | |
2678 | Left_Opnd => | |
2679 | New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), | |
2680 | Right_Opnd => | |
2681 | Make_Op_Multiply (Loc, | |
2682 | Left_Opnd => | |
2683 | New_Reference_To (RTE (RE_DT_Entry_Size), Loc), | |
2684 | Right_Opnd => | |
2685 | Make_Integer_Literal (Loc, Nb_Prim))); | |
2686 | end if; | |
aad6babd | 2687 | |
2688 | Append_To (Result, | |
2689 | Make_Object_Declaration (Loc, | |
76a1c25b | 2690 | Defining_Identifier => DT, |
aad6babd | 2691 | Aliased_Present => True, |
2692 | Object_Definition => | |
2693 | Make_Subtype_Indication (Loc, | |
76a1c25b | 2694 | Subtype_Mark => New_Reference_To |
2695 | (RTE (RE_Storage_Array), Loc), | |
aad6babd | 2696 | Constraint => Make_Index_Or_Discriminant_Constraint (Loc, |
2697 | Constraints => New_List ( | |
2698 | Make_Range (Loc, | |
2699 | Low_Bound => Make_Integer_Literal (Loc, 1), | |
76a1c25b | 2700 | High_Bound => Size_Expr_Node)))))); |
aad6babd | 2701 | |
2702 | Append_To (Result, | |
2703 | Make_Attribute_Definition_Clause (Loc, | |
76a1c25b | 2704 | Name => New_Reference_To (DT, Loc), |
aad6babd | 2705 | Chars => Name_Alignment, |
2706 | Expression => | |
2707 | Make_Attribute_Reference (Loc, | |
2708 | Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), | |
2709 | Attribute_Name => Name_Alignment))); | |
2710 | ||
2711 | -- Generate code to create the pointer to the dispatch table | |
2712 | ||
76a1c25b | 2713 | -- DT_Ptr : Tag := Tag!(DT'Address); |
aad6babd | 2714 | |
76a1c25b | 2715 | -- According to the C++ ABI, the base of the vtable is located after a |
2716 | -- prologue containing Offset_To_Top, and Typeinfo_Ptr. Hence, we move | |
2717 | -- down the pointer to the real base of the vtable | |
aad6babd | 2718 | |
343d35dc | 2719 | if not Has_Dispatch_Table then |
2720 | Append_To (Result, | |
2721 | Make_Object_Declaration (Loc, | |
2722 | Defining_Identifier => DT_Ptr, | |
2723 | Constant_Present => True, | |
2724 | Object_Definition => New_Reference_To (Generalized_Tag, Loc), | |
2725 | Expression => | |
2726 | Unchecked_Convert_To (Generalized_Tag, | |
2727 | Make_Op_Add (Loc, | |
2728 | Left_Opnd => | |
2729 | Unchecked_Convert_To (RTE (RE_Storage_Offset), | |
2730 | Make_Attribute_Reference (Loc, | |
2731 | Prefix => New_Reference_To (DT, Loc), | |
2732 | Attribute_Name => Name_Address)), | |
2733 | Right_Opnd => | |
2734 | New_Reference_To (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))); | |
ee6ba406 | 2735 | |
343d35dc | 2736 | else |
2737 | Append_To (Result, | |
2738 | Make_Object_Declaration (Loc, | |
2739 | Defining_Identifier => DT_Ptr, | |
2740 | Constant_Present => True, | |
2741 | Object_Definition => New_Reference_To (Generalized_Tag, Loc), | |
2742 | Expression => | |
2743 | Unchecked_Convert_To (Generalized_Tag, | |
2744 | Make_Op_Add (Loc, | |
2745 | Left_Opnd => | |
2746 | Unchecked_Convert_To (RTE (RE_Storage_Offset), | |
2747 | Make_Attribute_Reference (Loc, | |
2748 | Prefix => New_Reference_To (DT, Loc), | |
2749 | Attribute_Name => Name_Address)), | |
2750 | Right_Opnd => | |
2751 | New_Reference_To (RTE (RE_DT_Prologue_Size), Loc))))); | |
2752 | end if; | |
d62940bf | 2753 | |
343d35dc | 2754 | -- Save the tag in the Access_Disp_Table attribute |
d62940bf | 2755 | |
68f95949 | 2756 | if No (Access_Disp_Table (Typ)) then |
76a1c25b | 2757 | Set_Access_Disp_Table (Typ, New_Elmt_List); |
d62940bf | 2758 | end if; |
2759 | ||
76a1c25b | 2760 | Prepend_Elmt (DT_Ptr, Access_Disp_Table (Typ)); |
d62940bf | 2761 | |
343d35dc | 2762 | -- Generate code to define the boolean that controls registration, in |
2763 | -- order to avoid multiple registrations for tagged types defined in | |
2764 | -- multiple-called scopes. | |
d62940bf | 2765 | |
76a1c25b | 2766 | Append_To (Result, |
2767 | Make_Object_Declaration (Loc, | |
343d35dc | 2768 | Defining_Identifier => No_Reg, |
2769 | Object_Definition => New_Reference_To (Standard_Boolean, Loc), | |
2770 | Expression => New_Reference_To (Standard_True, Loc))); | |
d62940bf | 2771 | |
68f95949 | 2772 | -- Generate: |
2773 | -- Set_Signature (DT_Ptr, Value); | |
2774 | ||
343d35dc | 2775 | if Has_Dispatch_Table |
2776 | and then RTE_Available (RE_Set_Signature) | |
2777 | then | |
af647dc7 | 2778 | if Is_Interface (Typ) then |
2779 | Append_To (Elab_Code, | |
2780 | Make_DT_Access_Action (Typ, | |
2781 | Action => Set_Signature, | |
2782 | Args => New_List ( | |
343d35dc | 2783 | New_Reference_To (DT_Ptr, Loc), |
af647dc7 | 2784 | New_Reference_To (RTE (RE_Abstract_Interface), Loc)))); |
68f95949 | 2785 | |
af647dc7 | 2786 | else |
2787 | Append_To (Elab_Code, | |
2788 | Make_DT_Access_Action (Typ, | |
2789 | Action => Set_Signature, | |
2790 | Args => New_List ( | |
343d35dc | 2791 | New_Reference_To (DT_Ptr, Loc), |
af647dc7 | 2792 | New_Reference_To (RTE (RE_Primary_DT), Loc)))); |
2793 | end if; | |
68f95949 | 2794 | end if; |
2795 | ||
343d35dc | 2796 | -- Generate: Exname : constant String := full_qualified_name (typ); |
2797 | -- The type itself may be an anonymous parent type, so use the first | |
2798 | -- subtype to have a user-recognizable name. | |
d62940bf | 2799 | |
343d35dc | 2800 | Append_To (Result, |
2801 | Make_Object_Declaration (Loc, | |
2802 | Defining_Identifier => Exname, | |
2803 | Constant_Present => True, | |
2804 | Object_Definition => New_Reference_To (Standard_String, Loc), | |
2805 | Expression => | |
2806 | Make_String_Literal (Loc, | |
2807 | Full_Qualified_Name (First_Subtype (Typ))))); | |
d62940bf | 2808 | |
343d35dc | 2809 | -- Calculate the value of the RC_Offset component. These are the |
2810 | -- valid valiues and their meaning: | |
2811 | -- >0: For simple types with controlled components is | |
2812 | -- type._record_controller'position | |
2813 | -- 0: For types with no controlled components | |
2814 | -- -1: For complex types with controlled components where the position | |
2815 | -- of the record controller is not statically computable but there | |
2816 | -- are controlled components at this level. The _Controller field | |
2817 | -- is available right after the _parent. | |
2818 | -- -2: There are no controlled components at this level. We need to | |
2819 | -- get the position from the parent. | |
952af0b9 | 2820 | |
343d35dc | 2821 | if Is_Interface (Typ) |
2822 | or else not Has_Controlled_Component (Typ) | |
2823 | then | |
2824 | RC_Offset_Node := Make_Integer_Literal (Loc, 0); | |
2825 | ||
2826 | elsif Etype (Typ) /= Typ | |
2827 | and then Has_Discriminants (Etype (Typ)) | |
2828 | then | |
2829 | if Has_New_Controlled_Component (Typ) then | |
2830 | RC_Offset_Node := Make_Integer_Literal (Loc, -1); | |
2831 | else | |
2832 | RC_Offset_Node := Make_Integer_Literal (Loc, -2); | |
68f95949 | 2833 | end if; |
343d35dc | 2834 | else |
2835 | RC_Offset_Node := | |
2836 | Make_Attribute_Reference (Loc, | |
2837 | Prefix => | |
2838 | Make_Selected_Component (Loc, | |
2839 | Prefix => New_Reference_To (Typ, Loc), | |
2840 | Selector_Name => | |
2841 | New_Reference_To (Controller_Component (Typ), Loc)), | |
2842 | Attribute_Name => Name_Position); | |
2843 | ||
2844 | -- This is not proper Ada code to use the attribute 'Position | |
2845 | -- on something else than an object but this is supported by | |
2846 | -- the back end (see comment on the Bit_Component attribute in | |
2847 | -- sem_attr). So we avoid semantic checking here. | |
2848 | ||
2849 | -- Is this documented in sinfo.ads??? it should be! | |
2850 | ||
2851 | Set_Analyzed (RC_Offset_Node); | |
2852 | Set_Etype (Prefix (RC_Offset_Node), RTE (RE_Record_Controller)); | |
2853 | Set_Etype (Prefix (Prefix (RC_Offset_Node)), Typ); | |
2854 | Set_Etype (Selector_Name (Prefix (RC_Offset_Node)), | |
2855 | RTE (RE_Record_Controller)); | |
2856 | Set_Etype (RC_Offset_Node, RTE (RE_Storage_Offset)); | |
2857 | end if; | |
952af0b9 | 2858 | |
343d35dc | 2859 | -- Set the pointer to the Interfaces_Table (if any). Otherwise the |
2860 | -- corresponding access component is set to null. The table of | |
2861 | -- interfaces is required for AI-405 | |
952af0b9 | 2862 | |
343d35dc | 2863 | if RTE_Record_Component_Available (RE_Ifaces_Table_Ptr) then |
2864 | if Num_Ifaces = 0 then | |
2865 | Iface_Table_Node := | |
2866 | New_Reference_To (RTE (RE_Null_Address), Loc); | |
952af0b9 | 2867 | |
343d35dc | 2868 | -- Generate the Interface_Table object. |
2869 | ||
2870 | else | |
2871 | Append_To (Result, | |
2872 | Make_Object_Declaration (Loc, | |
2873 | Defining_Identifier => ITable, | |
2874 | Aliased_Present => True, | |
2875 | Object_Definition => | |
2876 | Make_Subtype_Indication (Loc, | |
2877 | Subtype_Mark => New_Reference_To | |
2878 | (RTE (RE_Interface_Data), Loc), | |
2879 | Constraint => Make_Index_Or_Discriminant_Constraint (Loc, | |
2880 | Constraints => New_List ( | |
2881 | Make_Integer_Literal (Loc, | |
2882 | Num_Ifaces)))))); | |
2883 | ||
2884 | Iface_Table_Node := | |
2885 | Make_Attribute_Reference (Loc, | |
2886 | Prefix => New_Reference_To (ITable, Loc), | |
2887 | Attribute_Name => Name_Address); | |
2888 | end if; | |
952af0b9 | 2889 | end if; |
2890 | ||
343d35dc | 2891 | -- Generate: Set_Remotely_Callable (DT_Ptr, Status); where Status is |
2892 | -- described in E.4 (18) | |
d62940bf | 2893 | |
343d35dc | 2894 | Remotely_Callable := |
2895 | Boolean_Literals | |
2896 | (Is_Pure (Typ) | |
2897 | or else Is_Shared_Passive (Typ) | |
2898 | or else | |
2899 | ((Is_Remote_Types (Typ) | |
2900 | or else Is_Remote_Call_Interface (Typ)) | |
2901 | and then Original_View_In_Visible_Part (Typ)) | |
2902 | or else not Comes_From_Source (Typ)); | |
952af0b9 | 2903 | |
343d35dc | 2904 | -- Generate code to create the storage for the type specific data object |
2905 | -- with enough space to store the tags of the ancestors plus the tags | |
2906 | -- of all the implemented interfaces (as described in a-tags.adb). | |
2907 | ||
2908 | -- TSD : Type_Specific_Data (I_Depth) := | |
2909 | -- (Idepth => I_Depth, | |
2910 | -- Access_Level => Type_Access_Level (Typ), | |
2911 | -- Expanded_Name => Cstring_Ptr!(Exname'Address)) | |
2912 | -- [ External_Tag => Cstring_Ptr!(Exname'Address)) ] | |
2913 | -- RC_Offset => <<integer-value>>, | |
2914 | -- Remotely_Callable => <<boolean-value>> | |
2915 | -- [ Ifaces_Table_Ptr => <<access-value>> ] | |
2916 | -- others => <>); | |
2917 | -- for TSD'Alignment use Address'Alignment | |
2918 | ||
2919 | TSD_Aggr_List := New_List ( | |
2920 | Make_Component_Association (Loc, | |
2921 | Choices => New_List ( | |
2922 | New_Occurrence_Of (RTE_Record_Component (RE_Idepth), Loc)), | |
2923 | Expression => Make_Integer_Literal (Loc, I_Depth)), | |
2924 | ||
2925 | Make_Component_Association (Loc, | |
2926 | Choices => New_List ( | |
2927 | New_Occurrence_Of (RTE_Record_Component (RE_Access_Level), Loc)), | |
2928 | Expression => Make_Integer_Literal (Loc, Type_Access_Level (Typ))), | |
2929 | ||
2930 | Make_Component_Association (Loc, | |
2931 | Choices => New_List ( | |
2932 | New_Occurrence_Of | |
2933 | (RTE_Record_Component (RE_Expanded_Name), Loc)), | |
2934 | Expression => | |
2935 | Unchecked_Convert_To (RTE (RE_Cstring_Ptr), | |
2936 | Make_Attribute_Reference (Loc, | |
2937 | Prefix => New_Reference_To (Exname, Loc), | |
2938 | Attribute_Name => Name_Address)))); | |
2939 | ||
2940 | if not Has_External_Tag_Rep_Clause (Typ) then | |
2941 | ||
2942 | -- Should be the external name not the qualified name??? | |
2943 | ||
2944 | Append_To (TSD_Aggr_List, | |
2945 | Make_Component_Association (Loc, | |
2946 | Choices => New_List ( | |
2947 | New_Occurrence_Of | |
2948 | (RTE_Record_Component (RE_External_Tag), Loc)), | |
2949 | Expression => | |
2950 | Unchecked_Convert_To (RTE (RE_Cstring_Ptr), | |
2951 | Make_Attribute_Reference (Loc, | |
2952 | Prefix => New_Reference_To (Exname, Loc), | |
2953 | Attribute_Name => Name_Address)))); | |
2954 | end if; | |
2955 | ||
2956 | Append_List_To (TSD_Aggr_List, New_List ( | |
2957 | Make_Component_Association (Loc, | |
2958 | Choices => New_List ( | |
2959 | New_Occurrence_Of (RTE_Record_Component (RE_RC_Offset), Loc)), | |
2960 | Expression => RC_Offset_Node), | |
2961 | ||
2962 | Make_Component_Association (Loc, | |
2963 | Choices => New_List ( | |
2964 | New_Occurrence_Of | |
2965 | (RTE_Record_Component (RE_Remotely_Callable), Loc)), | |
2966 | Expression => New_Occurrence_Of (Remotely_Callable, Loc)))); | |
2967 | ||
2968 | if RTE_Record_Component_Available (RE_Ifaces_Table_Ptr) then | |
2969 | Append_To (TSD_Aggr_List, | |
2970 | Make_Component_Association (Loc, | |
2971 | Choices => New_List ( | |
2972 | New_Occurrence_Of | |
2973 | (RTE_Record_Component (RE_Ifaces_Table_Ptr), Loc)), | |
2974 | Expression => Iface_Table_Node)); | |
2975 | end if; | |
2976 | ||
2977 | Append_To (TSD_Aggr_List, | |
2978 | Make_Component_Association (Loc, | |
2979 | Choices => New_List (Make_Others_Choice (Loc)), | |
2980 | Expression => Empty, | |
2981 | Box_Present => True)); | |
2982 | ||
2983 | -- Save the expanded name in the dispatch table | |
2984 | ||
2985 | Append_To (Result, | |
2986 | Make_Object_Declaration (Loc, | |
2987 | Defining_Identifier => TSD, | |
2988 | Aliased_Present => True, | |
2989 | Object_Definition => | |
2990 | Make_Subtype_Indication (Loc, | |
2991 | Subtype_Mark => New_Reference_To ( | |
2992 | RTE (RE_Type_Specific_Data), Loc), | |
2993 | Constraint => | |
2994 | Make_Index_Or_Discriminant_Constraint (Loc, | |
2995 | Constraints => New_List ( | |
2996 | Make_Integer_Literal (Loc, I_Depth)))), | |
2997 | Expression => Make_Aggregate (Loc, | |
2998 | Component_Associations => TSD_Aggr_List))); | |
2999 | ||
3000 | Append_To (Result, | |
3001 | Make_Attribute_Definition_Clause (Loc, | |
3002 | Name => New_Reference_To (TSD, Loc), | |
3003 | Chars => Name_Alignment, | |
3004 | Expression => | |
3005 | Make_Attribute_Reference (Loc, | |
3006 | Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), | |
3007 | Attribute_Name => Name_Alignment))); | |
3008 | ||
3009 | -- Generate code to put the Address of the TSD in the dispatch table | |
3010 | ||
3011 | Append_To (Elab_Code, | |
3012 | Build_Set_TSD (Loc, | |
3013 | Tag_Node => New_Reference_To (DT_Ptr, Loc), | |
3014 | Value_Node => | |
3015 | Make_Attribute_Reference (Loc, | |
3016 | Prefix => New_Reference_To (TSD, Loc), | |
3017 | Attribute_Name => Name_Address))); | |
3018 | ||
3019 | -- Generate extra code required for synchronized interfaces | |
3020 | ||
3021 | if RTE_Available (RE_Set_Tagged_Kind) then | |
68f95949 | 3022 | if Ada_Version >= Ada_05 |
3023 | and then not Is_Interface (Typ) | |
343d35dc | 3024 | and then not Is_Abstract_Type (Typ) |
68f95949 | 3025 | and then not Is_Controlled (Typ) |
3026 | and then not Restriction_Active (No_Dispatching_Calls) | |
952af0b9 | 3027 | then |
68f95949 | 3028 | -- Generate: |
3029 | -- Set_Type_Kind (T'Tag, Type_Kind (Typ)); | |
952af0b9 | 3030 | |
3031 | Append_To (Elab_Code, | |
3032 | Make_DT_Access_Action (Typ, | |
68f95949 | 3033 | Action => Set_Tagged_Kind, |
952af0b9 | 3034 | Args => New_List ( |
68f95949 | 3035 | New_Reference_To (DT_Ptr, Loc), -- DTptr |
3036 | Tagged_Kind (Typ)))); -- Value | |
3037 | ||
3038 | -- Generate the Select Specific Data table for synchronized | |
3039 | -- types that implement a synchronized interface. The size | |
3040 | -- of the table is constrained by the number of non-predefined | |
3041 | -- primitive operations. | |
3042 | ||
343d35dc | 3043 | if Has_Dispatch_Table |
68f95949 | 3044 | and then Is_Concurrent_Record_Type (Typ) |
343d35dc | 3045 | and then Has_Abstract_Interfaces (Typ) |
68f95949 | 3046 | then |
343d35dc | 3047 | -- No need to generate this code if Nb_Prim = 0 ??? |
3048 | ||
68f95949 | 3049 | Append_To (Result, |
3050 | Make_Object_Declaration (Loc, | |
3051 | Defining_Identifier => SSD, | |
3052 | Aliased_Present => True, | |
3053 | Object_Definition => | |
3054 | Make_Subtype_Indication (Loc, | |
3055 | Subtype_Mark => New_Reference_To ( | |
3056 | RTE (RE_Select_Specific_Data), Loc), | |
3057 | Constraint => | |
3058 | Make_Index_Or_Discriminant_Constraint (Loc, | |
3059 | Constraints => New_List ( | |
3060 | Make_Integer_Literal (Loc, Nb_Prim)))))); | |
3061 | ||
3062 | -- Set the pointer to the Select Specific Data table in the TSD | |
3063 | ||
3064 | Append_To (Elab_Code, | |
3065 | Make_DT_Access_Action (Typ, | |
3066 | Action => Set_SSD, | |
3067 | Args => New_List ( | |
3068 | New_Reference_To (DT_Ptr, Loc), -- DTptr | |
3069 | Make_Attribute_Reference (Loc, -- Value | |
3070 | Prefix => New_Reference_To (SSD, Loc), | |
3071 | Attribute_Name => Name_Address)))); | |
3072 | end if; | |
952af0b9 | 3073 | end if; |
76a1c25b | 3074 | end if; |
d62940bf | 3075 | |
af647dc7 | 3076 | -- If the ancestor is a CPP_Class type we inherit the dispatch tables |
3077 | -- in the init proc, and we don't need to fill them in here. | |
d62940bf | 3078 | |
343d35dc | 3079 | if Is_CPP_Class (Etype (Typ)) then |
af647dc7 | 3080 | null; |
d62940bf | 3081 | |
af647dc7 | 3082 | -- Otherwise we fill in the dispatch tables here |
d62940bf | 3083 | |
af647dc7 | 3084 | else |
3085 | if Typ = Etype (Typ) | |
3086 | or else Is_CPP_Class (Etype (Typ)) | |
3087 | or else Is_Interface (Typ) | |
3088 | then | |
343d35dc | 3089 | Null_Parent_Tag := True; |
3090 | ||
af647dc7 | 3091 | Old_Tag1 := |
3092 | Unchecked_Convert_To (Generalized_Tag, | |
3093 | Make_Integer_Literal (Loc, 0)); | |
3094 | Old_Tag2 := | |
3095 | Unchecked_Convert_To (Generalized_Tag, | |
3096 | Make_Integer_Literal (Loc, 0)); | |
d62940bf | 3097 | |
af647dc7 | 3098 | else |
3099 | Old_Tag1 := | |
3100 | New_Reference_To | |
3101 | (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc); | |
3102 | Old_Tag2 := | |
3103 | New_Reference_To | |
3104 | (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc); | |
3105 | end if; | |
d62940bf | 3106 | |
af647dc7 | 3107 | if Typ /= Etype (Typ) |
3108 | and then not Is_Interface (Typ) | |
3109 | and then not Restriction_Active (No_Dispatching_Calls) | |
68f95949 | 3110 | then |
343d35dc | 3111 | -- Inherit the dispatch table |
d62940bf | 3112 | |
af647dc7 | 3113 | if not Is_Interface (Etype (Typ)) then |
3114 | if Restriction_Active (No_Dispatching_Calls) then | |
343d35dc | 3115 | null; |
3116 | ||
af647dc7 | 3117 | else |
343d35dc | 3118 | if not Null_Parent_Tag then |
3119 | declare | |
3120 | Nb_Prims : constant Int := | |
3121 | UI_To_Int (DT_Entry_Count | |
3122 | (First_Tag_Component (Etype (Typ)))); | |
3123 | begin | |
3124 | Append_To (Elab_Code, | |
3125 | Build_Inherit_Predefined_Prims (Loc, | |
3126 | Old_Tag_Node => Old_Tag1, | |
3127 | New_Tag_Node => | |
3128 | New_Reference_To (DT_Ptr, Loc))); | |
3129 | ||
3130 | if Nb_Prims /= 0 then | |
3131 | Append_To (Elab_Code, | |
3132 | Build_Inherit_Prims (Loc, | |
3133 | Old_Tag_Node => Old_Tag2, | |
3134 | New_Tag_Node => New_Reference_To (DT_Ptr, Loc), | |
3135 | Num_Prims => Nb_Prims)); | |
3136 | end if; | |
3137 | end; | |
3138 | end if; | |
af647dc7 | 3139 | end if; |
3140 | end if; | |
d62940bf | 3141 | |
af647dc7 | 3142 | -- Inherit the secondary dispatch tables of the ancestor |
d62940bf | 3143 | |
af647dc7 | 3144 | if not Restriction_Active (No_Dispatching_Calls) |
3145 | and then not Is_CPP_Class (Etype (Typ)) | |
3146 | then | |
3147 | declare | |
3148 | Sec_DT_Ancestor : Elmt_Id := | |
3149 | Next_Elmt | |
3150 | (First_Elmt | |
3151 | (Access_Disp_Table (Etype (Typ)))); | |
3152 | Sec_DT_Typ : Elmt_Id := | |
3153 | Next_Elmt | |
3154 | (First_Elmt | |
3155 | (Access_Disp_Table (Typ))); | |
3156 | ||
3157 | procedure Copy_Secondary_DTs (Typ : Entity_Id); | |
3158 | -- Local procedure required to climb through the ancestors | |
3159 | -- and copy the contents of all their secondary dispatch | |
3160 | -- tables. | |
3161 | ||
3162 | ------------------------ | |
3163 | -- Copy_Secondary_DTs -- | |
3164 | ------------------------ | |
3165 | ||
3166 | procedure Copy_Secondary_DTs (Typ : Entity_Id) is | |
3167 | E : Entity_Id; | |
3168 | Iface : Elmt_Id; | |
3169 | ||
3170 | begin | |
3171 | -- Climb to the ancestor (if any) handling private types | |
3172 | ||
3173 | if Present (Full_View (Etype (Typ))) then | |
3174 | if Full_View (Etype (Typ)) /= Typ then | |
3175 | Copy_Secondary_DTs (Full_View (Etype (Typ))); | |
3176 | end if; | |
d62940bf | 3177 | |
af647dc7 | 3178 | elsif Etype (Typ) /= Typ then |
3179 | Copy_Secondary_DTs (Etype (Typ)); | |
3180 | end if; | |
d62940bf | 3181 | |
af647dc7 | 3182 | if Present (Abstract_Interfaces (Typ)) |
3183 | and then not Is_Empty_Elmt_List | |
3184 | (Abstract_Interfaces (Typ)) | |
3185 | then | |
3186 | Iface := First_Elmt (Abstract_Interfaces (Typ)); | |
3187 | E := First_Entity (Typ); | |
3188 | while Present (E) | |
3189 | and then Present (Node (Sec_DT_Ancestor)) | |
3190 | loop | |
3191 | if Is_Tag (E) and then Chars (E) /= Name_uTag then | |
3192 | if not Is_Interface (Etype (Typ)) then | |
343d35dc | 3193 | |
3194 | -- Inherit the dispatch table | |
3195 | ||
3196 | declare | |
3197 | Num_Prims : constant Int := | |
3198 | UI_To_Int (DT_Entry_Count (E)); | |
3199 | begin | |
3200 | Append_To (Elab_Code, | |
3201 | Build_Inherit_Predefined_Prims (Loc, | |
3202 | Old_Tag_Node => | |
3203 | Unchecked_Convert_To (RTE (RE_Tag), | |
3204 | New_Reference_To | |
3205 | (Node (Sec_DT_Ancestor), Loc)), | |
3206 | New_Tag_Node => | |
3207 | Unchecked_Convert_To (RTE (RE_Tag), | |
3208 | New_Reference_To | |
3209 | (Node (Sec_DT_Typ), Loc)))); | |
3210 | ||
3211 | if Num_Prims /= 0 then | |
3212 | Append_To (Elab_Code, | |
3213 | Build_Inherit_Prims (Loc, | |
3214 | Old_Tag_Node => | |
3215 | Unchecked_Convert_To | |
3216 | (RTE (RE_Tag), | |
3217 | New_Reference_To | |
3218 | (Node (Sec_DT_Ancestor), | |
3219 | Loc)), | |
3220 | New_Tag_Node => | |
3221 | Unchecked_Convert_To | |
3222 | (RTE (RE_Tag), | |
3223 | New_Reference_To | |
3224 | (Node (Sec_DT_Typ), Loc)), | |
3225 | Num_Prims => Num_Prims)); | |
3226 | end if; | |
3227 | end; | |
af647dc7 | 3228 | end if; |
3229 | ||
3230 | Next_Elmt (Sec_DT_Ancestor); | |
3231 | Next_Elmt (Sec_DT_Typ); | |
3232 | Next_Elmt (Iface); | |
3233 | end if; | |
d62940bf | 3234 | |
af647dc7 | 3235 | Next_Entity (E); |
3236 | end loop; | |
3237 | end if; | |
3238 | end Copy_Secondary_DTs; | |
d62940bf | 3239 | |
af647dc7 | 3240 | begin |
3241 | if Present (Node (Sec_DT_Ancestor)) then | |
d62940bf | 3242 | |
af647dc7 | 3243 | -- Handle private types |
76a1c25b | 3244 | |
af647dc7 | 3245 | if Present (Full_View (Typ)) then |
3246 | Copy_Secondary_DTs (Full_View (Typ)); | |
3247 | else | |
3248 | Copy_Secondary_DTs (Typ); | |
3249 | end if; | |
76a1c25b | 3250 | end if; |
af647dc7 | 3251 | end; |
3252 | end if; | |
76a1c25b | 3253 | end if; |
d62940bf | 3254 | |
af647dc7 | 3255 | -- Generate: |
3256 | -- Inherit_TSD (parent'tag, DT_Ptr); | |
d62940bf | 3257 | |
af647dc7 | 3258 | if not Is_Interface (Typ) then |
343d35dc | 3259 | if Typ = Etype (Typ) |
3260 | or else Is_CPP_Class (Etype (Typ)) | |
76a1c25b | 3261 | then |
343d35dc | 3262 | -- New_TSD (DT_Ptr); |
d62940bf | 3263 | |
343d35dc | 3264 | Append_List_To (Elab_Code, |
3265 | Build_New_TSD (Loc, | |
3266 | New_Tag_Node => New_Reference_To (DT_Ptr, Loc))); | |
3267 | else | |
3268 | -- Inherit_TSD (parent'tag, DT_Ptr); | |
d62940bf | 3269 | |
343d35dc | 3270 | Append_To (Elab_Code, |
3271 | Build_Inherit_TSD (Loc, | |
3272 | Old_Tag_Node => | |
3273 | New_Reference_To | |
3274 | (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), | |
3275 | Loc), | |
3276 | New_Tag_Node => New_Reference_To (DT_Ptr, Loc), | |
3277 | I_Depth => I_Depth, | |
3278 | Parent_Num_Ifaces => Parent_Num_Ifaces)); | |
3279 | end if; | |
68f95949 | 3280 | end if; |
76a1c25b | 3281 | end if; |
d62940bf | 3282 | |
343d35dc | 3283 | if not Is_Interface (Typ) |
3284 | and then RTE_Available (RE_Set_Offset_To_Top) | |
3285 | then | |
3286 | -- Generate: | |
3287 | -- Set_Offset_To_Top (0, DT_Ptr, True, 0, null); | |
d62940bf | 3288 | |
76a1c25b | 3289 | Append_To (Elab_Code, |
343d35dc | 3290 | Make_Procedure_Call_Statement (Loc, |
3291 | Name => New_Reference_To (RTE (RE_Set_Offset_To_Top), Loc), | |
3292 | Parameter_Associations => New_List ( | |
3293 | New_Reference_To (RTE (RE_Null_Address), Loc), | |
3294 | New_Reference_To (DT_Ptr, Loc), | |
3295 | New_Occurrence_Of (Standard_True, Loc), | |
3296 | Make_Integer_Literal (Loc, Uint_0), | |
3297 | New_Reference_To (RTE (RE_Null_Address), Loc)))); | |
3298 | end if; | |
d62940bf | 3299 | |
343d35dc | 3300 | -- Generate code to register the Tag in the External_Tag hash table for |
3301 | -- the pure Ada type only. | |
d62940bf | 3302 | |
343d35dc | 3303 | -- Register_Tag (Dt_Ptr); |
d62940bf | 3304 | |
343d35dc | 3305 | -- Skip this if routine not available, or in No_Run_Time mode or Typ is |
3306 | -- an abstract interface type (because the table to register it is not | |
3307 | -- available in the abstract type but in types implementing this | |
3308 | -- interface) | |
d62940bf | 3309 | |
343d35dc | 3310 | if not Has_External_Tag_Rep_Clause (Typ) |
3311 | and then not No_Run_Time_Mode | |
3312 | and then RTE_Available (RE_Register_Tag) | |
3313 | and then Is_RTE (RTE (RE_Tag), RE_Tag) | |
3314 | and then not Is_Interface (Typ) | |
3315 | then | |
3316 | Append_To (Elab_Code, | |
3317 | Make_Procedure_Call_Statement (Loc, | |
3318 | Name => New_Reference_To (RTE (RE_Register_Tag), Loc), | |
3319 | Parameter_Associations => | |
3320 | New_List (New_Reference_To (DT_Ptr, Loc)))); | |
76a1c25b | 3321 | end if; |
d62940bf | 3322 | |
76a1c25b | 3323 | -- Generate: |
3324 | -- if No_Reg then | |
3325 | -- <elab_code> | |
3326 | -- No_Reg := False; | |
3327 | -- end if; | |
3328 | ||
3329 | Append_To (Elab_Code, | |
3330 | Make_Assignment_Statement (Loc, | |
3331 | Name => New_Reference_To (No_Reg, Loc), | |
3332 | Expression => New_Reference_To (Standard_False, Loc))); | |
3333 | ||
3334 | Append_To (Result, | |
3335 | Make_Implicit_If_Statement (Typ, | |
3336 | Condition => New_Reference_To (No_Reg, Loc), | |
3337 | Then_Statements => Elab_Code)); | |
3338 | ||
343d35dc | 3339 | -- Ada 2005 (AI-251): Register the tag of the interfaces into the table |
3340 | -- of interfaces. | |
d62940bf | 3341 | |
af647dc7 | 3342 | if Num_Ifaces > 0 then |
952af0b9 | 3343 | declare |
343d35dc | 3344 | Position : Nat; |
d62940bf | 3345 | |
952af0b9 | 3346 | begin |
3347 | -- If the parent is an interface we must generate code to register | |
3348 | -- all its interfaces; otherwise this code is not needed because | |
3349 | -- Inherit_TSD has already inherited such interfaces. | |
d62940bf | 3350 | |
343d35dc | 3351 | if Is_Concurrent_Record_Type (Typ) |
3352 | or else (Etype (Typ) /= Typ and then Is_Interface (Etype (Typ))) | |
af647dc7 | 3353 | then |
952af0b9 | 3354 | Position := 1; |
d62940bf | 3355 | |
af647dc7 | 3356 | AI := First_Elmt (Ancestor_Ifaces); |
952af0b9 | 3357 | while Present (AI) loop |
3358 | -- Generate: | |
3359 | -- Register_Interface (DT_Ptr, Interface'Tag); | |
3360 | ||
3361 | Append_To (Result, | |
3362 | Make_DT_Access_Action (Typ, | |
3363 | Action => Register_Interface_Tag, | |
3364 | Args => New_List ( | |
3365 | Node1 => New_Reference_To (DT_Ptr, Loc), | |
3366 | Node2 => New_Reference_To | |
3367 | (Node | |
3368 | (First_Elmt | |
3369 | (Access_Disp_Table (Node (AI)))), | |
3370 | Loc), | |
3371 | Node3 => Make_Integer_Literal (Loc, Position)))); | |
3372 | ||
3373 | Position := Position + 1; | |
3374 | Next_Elmt (AI); | |
3375 | end loop; | |
3376 | end if; | |
3377 | ||
3378 | -- Register the interfaces that are not implemented by the | |
3379 | -- ancestor | |
3380 | ||
af647dc7 | 3381 | AI := First_Elmt (Typ_Ifaces); |
952af0b9 | 3382 | |
af647dc7 | 3383 | -- Skip the interfaces implemented by the ancestor |
952af0b9 | 3384 | |
af647dc7 | 3385 | for Count in 1 .. Parent_Num_Ifaces loop |
3386 | Next_Elmt (AI); | |
3387 | end loop; | |
952af0b9 | 3388 | |
af647dc7 | 3389 | -- Register the additional interfaces |
952af0b9 | 3390 | |
af647dc7 | 3391 | Position := Parent_Num_Ifaces + 1; |
3392 | while Present (AI) loop | |
952af0b9 | 3393 | |
af647dc7 | 3394 | -- Generate: |
3395 | -- Register_Interface (DT_Ptr, Interface'Tag); | |
3396 | ||
3397 | if not Is_Interface (Typ) | |
3398 | or else Typ /= Node (AI) | |
3399 | then | |
952af0b9 | 3400 | Append_To (Result, |
3401 | Make_DT_Access_Action (Typ, | |
3402 | Action => Register_Interface_Tag, | |
3403 | Args => New_List ( | |
3404 | Node1 => New_Reference_To (DT_Ptr, Loc), | |
3405 | Node2 => New_Reference_To | |
3406 | (Node | |
3407 | (First_Elmt | |
3408 | (Access_Disp_Table (Node (AI)))), | |
3409 | Loc), | |
3410 | Node3 => Make_Integer_Literal (Loc, Position)))); | |
3411 | ||
3412 | Position := Position + 1; | |
af647dc7 | 3413 | end if; |
3414 | ||
3415 | Next_Elmt (AI); | |
3416 | end loop; | |
952af0b9 | 3417 | |
3418 | pragma Assert (Position = Num_Ifaces + 1); | |
3419 | end; | |
d62940bf | 3420 | end if; |
3421 | ||
76a1c25b | 3422 | return Result; |
3423 | end Make_DT; | |
d62940bf | 3424 | |
76a1c25b | 3425 | --------------------------- |
3426 | -- Make_DT_Access_Action -- | |
3427 | --------------------------- | |
d62940bf | 3428 | |
76a1c25b | 3429 | function Make_DT_Access_Action |
3430 | (Typ : Entity_Id; | |
3431 | Action : DT_Access_Action; | |
3432 | Args : List_Id) return Node_Id | |
d62940bf | 3433 | is |
76a1c25b | 3434 | Action_Name : constant Entity_Id := RTE (Ada_Actions (Action)); |
3435 | Loc : Source_Ptr; | |
d62940bf | 3436 | |
3437 | begin | |
76a1c25b | 3438 | if No (Args) then |
d62940bf | 3439 | |
76a1c25b | 3440 | -- This is a constant |
d62940bf | 3441 | |
76a1c25b | 3442 | return New_Reference_To (Action_Name, Sloc (Typ)); |
3443 | end if; | |
d62940bf | 3444 | |
76a1c25b | 3445 | pragma Assert (List_Length (Args) = Action_Nb_Arg (Action)); |
d62940bf | 3446 | |
76a1c25b | 3447 | Loc := Sloc (First (Args)); |
d62940bf | 3448 | |
76a1c25b | 3449 | if Action_Is_Proc (Action) then |
3450 | return | |
3451 | Make_Procedure_Call_Statement (Loc, | |
3452 | Name => New_Reference_To (Action_Name, Loc), | |
3453 | Parameter_Associations => Args); | |
d62940bf | 3454 | |
76a1c25b | 3455 | else |
3456 | return | |
3457 | Make_Function_Call (Loc, | |
3458 | Name => New_Reference_To (Action_Name, Loc), | |
3459 | Parameter_Associations => Args); | |
3460 | end if; | |
3461 | end Make_DT_Access_Action; | |
d62940bf | 3462 | |
76a1c25b | 3463 | ----------------------- |
3464 | -- Make_Secondary_DT -- | |
3465 | ----------------------- | |
d62940bf | 3466 | |
76a1c25b | 3467 | procedure Make_Secondary_DT |
3468 | (Typ : Entity_Id; | |
3469 | Ancestor_Typ : Entity_Id; | |
343d35dc | 3470 | Suffix_Index : Nat; |
76a1c25b | 3471 | Iface : Entity_Id; |
3472 | AI_Tag : Entity_Id; | |
3473 | Acc_Disp_Tables : in out Elist_Id; | |
3474 | Result : out List_Id) | |
3475 | is | |
3476 | Loc : constant Source_Ptr := Sloc (AI_Tag); | |
3477 | Generalized_Tag : constant Entity_Id := RTE (RE_Interface_Tag); | |
3478 | Name_DT : constant Name_Id := New_Internal_Name ('T'); | |
68f95949 | 3479 | Empty_DT : Boolean := False; |
76a1c25b | 3480 | Iface_DT : Node_Id; |
3481 | Iface_DT_Ptr : Node_Id; | |
3482 | Name_DT_Ptr : Name_Id; | |
343d35dc | 3483 | Nb_Prim : Nat; |
76a1c25b | 3484 | OSD : Entity_Id; |
3485 | Size_Expr_Node : Node_Id; | |
3486 | Tname : Name_Id; | |
d62940bf | 3487 | |
76a1c25b | 3488 | begin |
3489 | Result := New_List; | |
d62940bf | 3490 | |
76a1c25b | 3491 | -- Generate a unique external name associated with the secondary |
3492 | -- dispatch table. This external name will be used to declare an | |
3493 | -- access to this secondary dispatch table, value that will be used | |
3494 | -- for the elaboration of Typ's objects and also for the elaboration | |
3495 | -- of objects of any derivation of Typ that do not override any | |
3496 | -- primitive operation of Typ. | |
d62940bf | 3497 | |
76a1c25b | 3498 | Get_Secondary_DT_External_Name (Typ, Ancestor_Typ, Suffix_Index); |
d62940bf | 3499 | |
76a1c25b | 3500 | Tname := Name_Find; |
3501 | Name_DT_Ptr := New_External_Name (Tname, "P"); | |
3502 | Iface_DT := Make_Defining_Identifier (Loc, Name_DT); | |
3503 | Iface_DT_Ptr := Make_Defining_Identifier (Loc, Name_DT_Ptr); | |
d62940bf | 3504 | |
76a1c25b | 3505 | -- Dispatch table and related entities are allocated statically |
d62940bf | 3506 | |
76a1c25b | 3507 | Set_Ekind (Iface_DT, E_Variable); |
3508 | Set_Is_Statically_Allocated (Iface_DT); | |
d62940bf | 3509 | |
76a1c25b | 3510 | Set_Ekind (Iface_DT_Ptr, E_Variable); |
3511 | Set_Is_Statically_Allocated (Iface_DT_Ptr); | |
d62940bf | 3512 | |
76a1c25b | 3513 | -- Generate code to create the storage for the Dispatch_Table object. |
68f95949 | 3514 | -- If the number of primitives of Typ is 0 we reserve a dummy single |
3515 | -- entry for its DT because at run-time the pointer to this dummy entry | |
3516 | -- will be used as the tag. | |
d62940bf | 3517 | |
76a1c25b | 3518 | Nb_Prim := UI_To_Int (DT_Entry_Count (AI_Tag)); |
d62940bf | 3519 | |
68f95949 | 3520 | if Nb_Prim = 0 then |
3521 | Empty_DT := True; | |
3522 | Nb_Prim := 1; | |
76a1c25b | 3523 | end if; |
d62940bf | 3524 | |
76a1c25b | 3525 | -- DT : Storage_Array (1..DT_Prologue_Size+nb_prim*DT_Entry_Size); |
3526 | -- for DT'Alignment use Address'Alignment | |
d62940bf | 3527 | |
76a1c25b | 3528 | Size_Expr_Node := |
3529 | Make_Op_Add (Loc, | |
343d35dc | 3530 | Left_Opnd => |
3531 | New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), | |
76a1c25b | 3532 | Right_Opnd => |
3533 | Make_Op_Multiply (Loc, | |
3534 | Left_Opnd => | |
343d35dc | 3535 | New_Reference_To (RTE (RE_DT_Entry_Size), Loc), |
76a1c25b | 3536 | Right_Opnd => |
3537 | Make_Integer_Literal (Loc, Nb_Prim))); | |
3538 | ||
3539 | Append_To (Result, | |
3540 | Make_Object_Declaration (Loc, | |
3541 | Defining_Identifier => Iface_DT, | |
3542 | Aliased_Present => True, | |
3543 | Object_Definition => | |
3544 | Make_Subtype_Indication (Loc, | |
3545 | Subtype_Mark => New_Reference_To (RTE (RE_Storage_Array), Loc), | |
3546 | Constraint => Make_Index_Or_Discriminant_Constraint (Loc, | |
3547 | Constraints => New_List ( | |
3548 | Make_Range (Loc, | |
3549 | Low_Bound => Make_Integer_Literal (Loc, 1), | |
3550 | High_Bound => Size_Expr_Node)))))); | |
d62940bf | 3551 | |
76a1c25b | 3552 | Append_To (Result, |
3553 | Make_Attribute_Definition_Clause (Loc, | |
3554 | Name => New_Reference_To (Iface_DT, Loc), | |
3555 | Chars => Name_Alignment, | |
3556 | Expression => | |
3557 | Make_Attribute_Reference (Loc, | |
3558 | Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), | |
3559 | Attribute_Name => Name_Alignment))); | |
d62940bf | 3560 | |
76a1c25b | 3561 | -- Generate code to create the pointer to the dispatch table |
d62940bf | 3562 | |
76a1c25b | 3563 | -- Iface_DT_Ptr : Tag := Tag!(DT'Address); |
d62940bf | 3564 | |
76a1c25b | 3565 | -- According to the C++ ABI, the base of the vtable is located |
3566 | -- after the following prologue: Offset_To_Top, and Typeinfo_Ptr. | |
3567 | -- Hence, move the pointer down to the real base of the vtable. | |
d62940bf | 3568 | |
76a1c25b | 3569 | Append_To (Result, |
3570 | Make_Object_Declaration (Loc, | |
3571 | Defining_Identifier => Iface_DT_Ptr, | |
3572 | Constant_Present => True, | |
3573 | Object_Definition => New_Reference_To (Generalized_Tag, Loc), | |
3574 | Expression => | |
3575 | Unchecked_Convert_To (Generalized_Tag, | |
3576 | Make_Op_Add (Loc, | |
3577 | Left_Opnd => | |
3578 | Unchecked_Convert_To (RTE (RE_Storage_Offset), | |
3579 | Make_Attribute_Reference (Loc, | |
3580 | Prefix => New_Reference_To (Iface_DT, Loc), | |
3581 | Attribute_Name => Name_Address)), | |
3582 | Right_Opnd => | |
343d35dc | 3583 | New_Reference_To (RTE (RE_DT_Prologue_Size), Loc))))); |
d62940bf | 3584 | |
76a1c25b | 3585 | -- Note: Offset_To_Top will be initialized by the init subprogram |
d62940bf | 3586 | |
76a1c25b | 3587 | -- Set Access_Disp_Table field to be the dispatch table pointer |
d62940bf | 3588 | |
76a1c25b | 3589 | if not (Present (Acc_Disp_Tables)) then |
3590 | Acc_Disp_Tables := New_Elmt_List; | |
3591 | end if; | |
d62940bf | 3592 | |
76a1c25b | 3593 | Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables); |
d62940bf | 3594 | |
76a1c25b | 3595 | -- Step 1: Generate an Object Specific Data (OSD) table |
d62940bf | 3596 | |
76a1c25b | 3597 | OSD := Make_Defining_Identifier (Loc, New_Internal_Name ('I')); |
d62940bf | 3598 | |
68f95949 | 3599 | -- Nothing to do if configurable run time does not support the |
3600 | -- Object_Specific_Data entity. | |
3601 | ||
3602 | if not RTE_Available (RE_Object_Specific_Data) then | |
3603 | Error_Msg_CRT ("abstract interface types", Typ); | |
3604 | return; | |
3605 | end if; | |
3606 | ||
76a1c25b | 3607 | -- Generate: |
68f95949 | 3608 | -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims); |
76a1c25b | 3609 | -- where the constraint is used to allocate space for the |
3610 | -- non-predefined primitive operations only. | |
d62940bf | 3611 | |
76a1c25b | 3612 | Append_To (Result, |
3613 | Make_Object_Declaration (Loc, | |
3614 | Defining_Identifier => OSD, | |
3615 | Object_Definition => | |
3616 | Make_Subtype_Indication (Loc, | |
3617 | Subtype_Mark => New_Reference_To ( | |
3618 | RTE (RE_Object_Specific_Data), Loc), | |
3619 | Constraint => | |
3620 | Make_Index_Or_Discriminant_Constraint (Loc, | |
3621 | Constraints => New_List ( | |
68f95949 | 3622 | Make_Integer_Literal (Loc, Nb_Prim)))))); |
3623 | ||
3624 | Append_To (Result, | |
3625 | Make_DT_Access_Action (Typ, | |
3626 | Action => Set_Signature, | |
3627 | Args => New_List ( | |
3628 | Unchecked_Convert_To (RTE (RE_Tag), | |
3629 | New_Reference_To (Iface_DT_Ptr, Loc)), | |
3630 | New_Reference_To (RTE (RE_Secondary_DT), Loc)))); | |
d62940bf | 3631 | |
76a1c25b | 3632 | -- Generate: |
3633 | -- Ada.Tags.Set_OSD (Iface_DT_Ptr, OSD); | |
d62940bf | 3634 | |
76a1c25b | 3635 | Append_To (Result, |
3636 | Make_DT_Access_Action (Typ, | |
3637 | Action => Set_OSD, | |
3638 | Args => New_List ( | |
952af0b9 | 3639 | Unchecked_Convert_To (RTE (RE_Tag), |
3640 | New_Reference_To (Iface_DT_Ptr, Loc)), | |
76a1c25b | 3641 | Make_Attribute_Reference (Loc, |
3642 | Prefix => New_Reference_To (OSD, Loc), | |
3643 | Attribute_Name => Name_Address)))); | |
d62940bf | 3644 | |
952af0b9 | 3645 | if Ada_Version >= Ada_05 |
343d35dc | 3646 | and then not Is_Interface (Typ) |
3647 | and then not Is_Abstract_Type (Typ) | |
952af0b9 | 3648 | and then not Is_Controlled (Typ) |
68f95949 | 3649 | and then RTE_Available (RE_Set_Tagged_Kind) |
3650 | and then not Restriction_Active (No_Dispatching_Calls) | |
952af0b9 | 3651 | then |
3652 | -- Generate: | |
3653 | -- Set_Tagged_Kind (Iface'Tag, Tagged_Kind (Iface)); | |
3654 | ||
3655 | Append_To (Result, | |
3656 | Make_DT_Access_Action (Typ, | |
3657 | Action => Set_Tagged_Kind, | |
3658 | Args => New_List ( | |
3659 | Unchecked_Convert_To (RTE (RE_Tag), -- DTptr | |
3660 | New_Reference_To (Iface_DT_Ptr, Loc)), | |
3661 | Tagged_Kind (Typ)))); -- Value | |
3662 | ||
68f95949 | 3663 | if not Empty_DT |
3664 | and then Is_Concurrent_Record_Type (Typ) | |
343d35dc | 3665 | and then Has_Abstract_Interfaces (Typ) |
952af0b9 | 3666 | then |
3667 | declare | |
3668 | Prim : Entity_Id; | |
3669 | Prim_Alias : Entity_Id; | |
3670 | Prim_Elmt : Elmt_Id; | |
3671 | ||
3672 | begin | |
3673 | -- Step 2: Populate the OSD table | |
3674 | ||
3675 | Prim_Alias := Empty; | |
3676 | Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); | |
3677 | while Present (Prim_Elmt) loop | |
3678 | Prim := Node (Prim_Elmt); | |
3679 | ||
af647dc7 | 3680 | if Present (Abstract_Interface_Alias (Prim)) |
3681 | and then Find_Dispatching_Type | |
3682 | (Abstract_Interface_Alias (Prim)) = Iface | |
3683 | then | |
952af0b9 | 3684 | Prim_Alias := Abstract_Interface_Alias (Prim); |
952af0b9 | 3685 | |
952af0b9 | 3686 | -- Generate: |
3687 | -- Ada.Tags.Set_Offset_Index (Tag (Iface_DT_Ptr), | |
3688 | -- Secondary_DT_Pos, Primary_DT_pos); | |
3689 | ||
3690 | Append_To (Result, | |
3691 | Make_DT_Access_Action (Iface, | |
3692 | Action => Set_Offset_Index, | |
3693 | Args => New_List ( | |
3694 | Unchecked_Convert_To (RTE (RE_Tag), | |
3695 | New_Reference_To (Iface_DT_Ptr, Loc)), | |
3696 | Make_Integer_Literal (Loc, | |
3697 | DT_Position (Prim_Alias)), | |
3698 | Make_Integer_Literal (Loc, | |
af647dc7 | 3699 | DT_Position (Alias (Prim)))))); |
952af0b9 | 3700 | end if; |
3701 | ||
3702 | Next_Elmt (Prim_Elmt); | |
3703 | end loop; | |
3704 | end; | |
3705 | end if; | |
3706 | end if; | |
76a1c25b | 3707 | end Make_Secondary_DT; |
d62940bf | 3708 | |
76a1c25b | 3709 | ------------------------------------- |
3710 | -- Make_Select_Specific_Data_Table -- | |
3711 | ------------------------------------- | |
d62940bf | 3712 | |
76a1c25b | 3713 | function Make_Select_Specific_Data_Table |
3714 | (Typ : Entity_Id) return List_Id | |
3715 | is | |
3716 | Assignments : constant List_Id := New_List; | |
3717 | Loc : constant Source_Ptr := Sloc (Typ); | |
d62940bf | 3718 | |
68f95949 | 3719 | Conc_Typ : Entity_Id; |
3720 | Decls : List_Id; | |
3721 | DT_Ptr : Entity_Id; | |
3722 | Prim : Entity_Id; | |
3723 | Prim_Als : Entity_Id; | |
3724 | Prim_Elmt : Elmt_Id; | |
3725 | Prim_Pos : Uint; | |
343d35dc | 3726 | Nb_Prim : Nat := 0; |
d62940bf | 3727 | |
76a1c25b | 3728 | type Examined_Array is array (Int range <>) of Boolean; |
d62940bf | 3729 | |
76a1c25b | 3730 | function Find_Entry_Index (E : Entity_Id) return Uint; |
3731 | -- Given an entry, find its index in the visible declarations of the | |
3732 | -- corresponding concurrent type of Typ. | |
d62940bf | 3733 | |
76a1c25b | 3734 | ---------------------- |
3735 | -- Find_Entry_Index -- | |
3736 | ---------------------- | |
d62940bf | 3737 | |
76a1c25b | 3738 | function Find_Entry_Index (E : Entity_Id) return Uint is |
3739 | Index : Uint := Uint_1; | |
3740 | Subp_Decl : Entity_Id; | |
d62940bf | 3741 | |
76a1c25b | 3742 | begin |
3743 | if Present (Decls) | |
3744 | and then not Is_Empty_List (Decls) | |
3745 | then | |
3746 | Subp_Decl := First (Decls); | |
3747 | while Present (Subp_Decl) loop | |
3748 | if Nkind (Subp_Decl) = N_Entry_Declaration then | |
3749 | if Defining_Identifier (Subp_Decl) = E then | |
3750 | return Index; | |
3751 | end if; | |
d62940bf | 3752 | |
76a1c25b | 3753 | Index := Index + 1; |
3754 | end if; | |
d62940bf | 3755 | |
76a1c25b | 3756 | Next (Subp_Decl); |
3757 | end loop; | |
3758 | end if; | |
d62940bf | 3759 | |
76a1c25b | 3760 | return Uint_0; |
3761 | end Find_Entry_Index; | |
3762 | ||
3763 | -- Start of processing for Make_Select_Specific_Data_Table | |
3764 | ||
3765 | begin | |
68f95949 | 3766 | pragma Assert (not Restriction_Active (No_Dispatching_Calls)); |
3767 | ||
76a1c25b | 3768 | DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); |
d62940bf | 3769 | |
76a1c25b | 3770 | if Present (Corresponding_Concurrent_Type (Typ)) then |
3771 | Conc_Typ := Corresponding_Concurrent_Type (Typ); | |
3772 | ||
3773 | if Ekind (Conc_Typ) = E_Protected_Type then | |
3774 | Decls := Visible_Declarations (Protected_Definition ( | |
3775 | Parent (Conc_Typ))); | |
d62940bf | 3776 | else |
3777 | pragma Assert (Ekind (Conc_Typ) = E_Task_Type); | |
76a1c25b | 3778 | Decls := Visible_Declarations (Task_Definition ( |
3779 | Parent (Conc_Typ))); | |
3780 | end if; | |
3781 | end if; | |
d62940bf | 3782 | |
76a1c25b | 3783 | -- Count the non-predefined primitive operations |
d62940bf | 3784 | |
76a1c25b | 3785 | Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); |
3786 | while Present (Prim_Elmt) loop | |
af647dc7 | 3787 | Prim := Node (Prim_Elmt); |
3788 | ||
3789 | if not (Is_Predefined_Dispatching_Operation (Prim) | |
3790 | or else Is_Predefined_Dispatching_Alias (Prim)) | |
3791 | then | |
76a1c25b | 3792 | Nb_Prim := Nb_Prim + 1; |
3793 | end if; | |
d62940bf | 3794 | |
76a1c25b | 3795 | Next_Elmt (Prim_Elmt); |
3796 | end loop; | |
d62940bf | 3797 | |
76a1c25b | 3798 | declare |
68f95949 | 3799 | Examined : Examined_Array (1 .. Nb_Prim) := (others => False); |
d62940bf | 3800 | |
76a1c25b | 3801 | begin |
3802 | Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); | |
3803 | while Present (Prim_Elmt) loop | |
3804 | Prim := Node (Prim_Elmt); | |
d62940bf | 3805 | |
af647dc7 | 3806 | -- Look for primitive overriding an abstract interface subprogram |
d62940bf | 3807 | |
af647dc7 | 3808 | if Present (Abstract_Interface_Alias (Prim)) |
3809 | and then not Examined (UI_To_Int (DT_Position (Alias (Prim)))) | |
3810 | then | |
3811 | Prim_Pos := DT_Position (Alias (Prim)); | |
3812 | pragma Assert (UI_To_Int (Prim_Pos) <= Nb_Prim); | |
3813 | Examined (UI_To_Int (Prim_Pos)) := True; | |
d62940bf | 3814 | |
af647dc7 | 3815 | -- Set the primitive operation kind regardless of subprogram |
3816 | -- type. Generate: | |
3817 | -- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, <position>, <kind>); | |
d62940bf | 3818 | |
af647dc7 | 3819 | Append_To (Assignments, |
3820 | Make_DT_Access_Action (Typ, | |
3821 | Action => Set_Prim_Op_Kind, | |
3822 | Args => New_List ( | |
3823 | New_Reference_To (DT_Ptr, Loc), | |
3824 | Make_Integer_Literal (Loc, Prim_Pos), | |
3825 | Prim_Op_Kind (Alias (Prim), Typ)))); | |
68f95949 | 3826 | |
af647dc7 | 3827 | -- Retrieve the root of the alias chain |
68f95949 | 3828 | |
af647dc7 | 3829 | Prim_Als := Prim; |
3830 | while Present (Alias (Prim_Als)) loop | |
3831 | Prim_Als := Alias (Prim_Als); | |
3832 | end loop; | |
68f95949 | 3833 | |
af647dc7 | 3834 | -- In the case of an entry wrapper, set the entry index |
68f95949 | 3835 | |
af647dc7 | 3836 | if Ekind (Prim) = E_Procedure |
3837 | and then Is_Primitive_Wrapper (Prim_Als) | |
3838 | and then Ekind (Wrapped_Entity (Prim_Als)) = E_Entry | |
3839 | then | |
3840 | -- Generate: | |
3841 | -- Ada.Tags.Set_Entry_Index | |
3842 | -- (DT_Ptr, <position>, <index>); | |
68f95949 | 3843 | |
af647dc7 | 3844 | Append_To (Assignments, |
3845 | Make_DT_Access_Action (Typ, | |
3846 | Action => Set_Entry_Index, | |
3847 | Args => New_List ( | |
3848 | New_Reference_To (DT_Ptr, Loc), | |
3849 | Make_Integer_Literal (Loc, Prim_Pos), | |
3850 | Make_Integer_Literal (Loc, | |
3851 | Find_Entry_Index | |
3852 | (Wrapped_Entity (Prim_Als)))))); | |
76a1c25b | 3853 | end if; |
3854 | end if; | |
3855 | ||
76a1c25b | 3856 | Next_Elmt (Prim_Elmt); |
3857 | end loop; | |
3858 | end; | |
3859 | ||
3860 | return Assignments; | |
3861 | end Make_Select_Specific_Data_Table; | |
d62940bf | 3862 | |
ee6ba406 | 3863 | ----------------------------------- |
3864 | -- Original_View_In_Visible_Part -- | |
3865 | ----------------------------------- | |
3866 | ||
3867 | function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean is | |
3868 | Scop : constant Entity_Id := Scope (Typ); | |
3869 | ||
3870 | begin | |
3871 | -- The scope must be a package | |
3872 | ||
3873 | if Ekind (Scop) /= E_Package | |
3874 | and then Ekind (Scop) /= E_Generic_Package | |
3875 | then | |
3876 | return False; | |
3877 | end if; | |
3878 | ||
3879 | -- A type with a private declaration has a private view declared in | |
3880 | -- the visible part. | |
3881 | ||
3882 | if Has_Private_Declaration (Typ) then | |
3883 | return True; | |
3884 | end if; | |
3885 | ||
3886 | return List_Containing (Parent (Typ)) = | |
3887 | Visible_Declarations (Specification (Unit_Declaration_Node (Scop))); | |
3888 | end Original_View_In_Visible_Part; | |
3889 | ||
d62940bf | 3890 | ------------------ |
3891 | -- Prim_Op_Kind -- | |
3892 | ------------------ | |
3893 | ||
3894 | function Prim_Op_Kind | |
3895 | (Prim : Entity_Id; | |
3896 | Typ : Entity_Id) return Node_Id | |
3897 | is | |
3898 | Full_Typ : Entity_Id := Typ; | |
3899 | Loc : constant Source_Ptr := Sloc (Prim); | |
68f95949 | 3900 | Prim_Op : Entity_Id; |
d62940bf | 3901 | |
3902 | begin | |
3903 | -- Retrieve the original primitive operation | |
3904 | ||
68f95949 | 3905 | Prim_Op := Prim; |
d62940bf | 3906 | while Present (Alias (Prim_Op)) loop |
3907 | Prim_Op := Alias (Prim_Op); | |
3908 | end loop; | |
3909 | ||
3910 | if Ekind (Typ) = E_Record_Type | |
3911 | and then Present (Corresponding_Concurrent_Type (Typ)) | |
3912 | then | |
3913 | Full_Typ := Corresponding_Concurrent_Type (Typ); | |
3914 | end if; | |
3915 | ||
3916 | if Ekind (Prim_Op) = E_Function then | |
3917 | ||
3918 | -- Protected function | |
3919 | ||
3920 | if Ekind (Full_Typ) = E_Protected_Type then | |
3921 | return New_Reference_To (RTE (RE_POK_Protected_Function), Loc); | |
3922 | ||
76a1c25b | 3923 | -- Task function |
3924 | ||
3925 | elsif Ekind (Full_Typ) = E_Task_Type then | |
3926 | return New_Reference_To (RTE (RE_POK_Task_Function), Loc); | |
3927 | ||
d62940bf | 3928 | -- Regular function |
3929 | ||
3930 | else | |
3931 | return New_Reference_To (RTE (RE_POK_Function), Loc); | |
3932 | end if; | |
3933 | ||
3934 | else | |
3935 | pragma Assert (Ekind (Prim_Op) = E_Procedure); | |
3936 | ||
3937 | if Ekind (Full_Typ) = E_Protected_Type then | |
3938 | ||
3939 | -- Protected entry | |
3940 | ||
3941 | if Is_Primitive_Wrapper (Prim_Op) | |
3942 | and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry | |
3943 | then | |
3944 | return New_Reference_To (RTE (RE_POK_Protected_Entry), Loc); | |
3945 | ||
3946 | -- Protected procedure | |
3947 | ||
3948 | else | |
3949 | return New_Reference_To (RTE (RE_POK_Protected_Procedure), Loc); | |
3950 | end if; | |
3951 | ||
3952 | elsif Ekind (Full_Typ) = E_Task_Type then | |
3953 | ||
3954 | -- Task entry | |
3955 | ||
3956 | if Is_Primitive_Wrapper (Prim_Op) | |
3957 | and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry | |
3958 | then | |
3959 | return New_Reference_To (RTE (RE_POK_Task_Entry), Loc); | |
3960 | ||
3961 | -- Task "procedure". These are the internally Expander-generated | |
3962 | -- procedures (task body for instance). | |
3963 | ||
3964 | else | |
3965 | return New_Reference_To (RTE (RE_POK_Task_Procedure), Loc); | |
3966 | end if; | |
3967 | ||
3968 | -- Regular procedure | |
3969 | ||
3970 | else | |
3971 | return New_Reference_To (RTE (RE_POK_Procedure), Loc); | |
3972 | end if; | |
3973 | end if; | |
3974 | end Prim_Op_Kind; | |
3975 | ||
ee6ba406 | 3976 | ------------------------- |
3977 | -- Set_All_DT_Position -- | |
3978 | ------------------------- | |
3979 | ||
3980 | procedure Set_All_DT_Position (Typ : Entity_Id) is | |
ee6ba406 | 3981 | |
aad6babd | 3982 | procedure Validate_Position (Prim : Entity_Id); |
3983 | -- Check that the position assignated to Prim is completely safe | |
3984 | -- (it has not been assigned to a previously defined primitive | |
3985 | -- operation of Typ) | |
3986 | ||
3987 | ----------------------- | |
3988 | -- Validate_Position -- | |
3989 | ----------------------- | |
3990 | ||
3991 | procedure Validate_Position (Prim : Entity_Id) is | |
af647dc7 | 3992 | Op_Elmt : Elmt_Id; |
3993 | Op : Entity_Id; | |
d62940bf | 3994 | |
aad6babd | 3995 | begin |
af647dc7 | 3996 | -- Aliased primitives are safe |
3997 | ||
3998 | if Present (Alias (Prim)) then | |
3999 | return; | |
4000 | end if; | |
4001 | ||
4002 | Op_Elmt := First_Elmt (Primitive_Operations (Typ)); | |
4003 | while Present (Op_Elmt) loop | |
4004 | Op := Node (Op_Elmt); | |
4005 | ||
4006 | -- No need to check against itself | |
4007 | ||
4008 | if Op = Prim then | |
4009 | null; | |
4010 | ||
aad6babd | 4011 | -- Primitive operations covering abstract interfaces are |
4012 | -- allocated later | |
4013 | ||
af647dc7 | 4014 | elsif Present (Abstract_Interface_Alias (Op)) then |
aad6babd | 4015 | null; |
4016 | ||
68f95949 | 4017 | -- Predefined dispatching operations are completely safe. They |
4018 | -- are allocated at fixed positions in a separate table. | |
aad6babd | 4019 | |
af647dc7 | 4020 | elsif Is_Predefined_Dispatching_Operation (Op) |
4021 | or else Is_Predefined_Dispatching_Alias (Op) | |
4022 | then | |
aad6babd | 4023 | null; |
ee6ba406 | 4024 | |
aad6babd | 4025 | -- Aliased subprograms are safe |
4026 | ||
af647dc7 | 4027 | elsif Present (Alias (Op)) then |
aad6babd | 4028 | null; |
4029 | ||
af647dc7 | 4030 | elsif DT_Position (Op) = DT_Position (Prim) |
4031 | and then not Is_Predefined_Dispatching_Operation (Op) | |
4032 | and then not Is_Predefined_Dispatching_Operation (Prim) | |
4033 | and then not Is_Predefined_Dispatching_Alias (Op) | |
4034 | and then not Is_Predefined_Dispatching_Alias (Prim) | |
4035 | then | |
d62940bf | 4036 | |
4037 | -- Handle aliased subprograms | |
4038 | ||
4039 | declare | |
4040 | Op_1 : Entity_Id; | |
4041 | Op_2 : Entity_Id; | |
4042 | ||
4043 | begin | |
af647dc7 | 4044 | Op_1 := Op; |
d62940bf | 4045 | loop |
4046 | if Present (Overridden_Operation (Op_1)) then | |
4047 | Op_1 := Overridden_Operation (Op_1); | |
4048 | elsif Present (Alias (Op_1)) then | |
4049 | Op_1 := Alias (Op_1); | |
4050 | else | |
4051 | exit; | |
4052 | end if; | |
4053 | end loop; | |
4054 | ||
4055 | Op_2 := Prim; | |
4056 | loop | |
4057 | if Present (Overridden_Operation (Op_2)) then | |
4058 | Op_2 := Overridden_Operation (Op_2); | |
4059 | elsif Present (Alias (Op_2)) then | |
4060 | Op_2 := Alias (Op_2); | |
4061 | else | |
4062 | exit; | |
4063 | end if; | |
4064 | end loop; | |
4065 | ||
4066 | if Op_1 /= Op_2 then | |
4067 | raise Program_Error; | |
4068 | end if; | |
4069 | end; | |
aad6babd | 4070 | end if; |
4071 | ||
af647dc7 | 4072 | Next_Elmt (Op_Elmt); |
aad6babd | 4073 | end loop; |
4074 | end Validate_Position; | |
4075 | ||
af647dc7 | 4076 | -- Local variables |
4077 | ||
4078 | Parent_Typ : constant Entity_Id := Etype (Typ); | |
af647dc7 | 4079 | First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ)); |
4080 | The_Tag : constant Entity_Id := First_Tag_Component (Typ); | |
4081 | ||
4082 | Adjusted : Boolean := False; | |
4083 | Finalized : Boolean := False; | |
4084 | ||
343d35dc | 4085 | Count_Prim : Nat; |
4086 | DT_Length : Nat; | |
4087 | Nb_Prim : Nat; | |
af647dc7 | 4088 | Prim : Entity_Id; |
4089 | Prim_Elmt : Elmt_Id; | |
4090 | ||
aad6babd | 4091 | -- Start of processing for Set_All_DT_Position |
4092 | ||
4093 | begin | |
343d35dc | 4094 | -- Set the DT_Position for each primitive operation. Perform some |
4095 | -- sanity checks to avoid to build completely inconsistant dispatch | |
4096 | -- tables. | |
ee6ba406 | 4097 | |
343d35dc | 4098 | -- First stage: Set the DTC entity of all the primitive operations |
4099 | -- This is required to properly read the DT_Position attribute in | |
4100 | -- the latter stages. | |
ee6ba406 | 4101 | |
343d35dc | 4102 | Prim_Elmt := First_Prim; |
4103 | Count_Prim := 0; | |
4104 | while Present (Prim_Elmt) loop | |
4105 | Prim := Node (Prim_Elmt); | |
ee6ba406 | 4106 | |
343d35dc | 4107 | -- Predefined primitives have a separate dispatch table |
ee6ba406 | 4108 | |
343d35dc | 4109 | if not (Is_Predefined_Dispatching_Operation (Prim) |
4110 | or else Is_Predefined_Dispatching_Alias (Prim)) | |
4111 | then | |
4112 | Count_Prim := Count_Prim + 1; | |
4113 | end if; | |
ee6ba406 | 4114 | |
343d35dc | 4115 | -- Ada 2005 (AI-251) |
ee6ba406 | 4116 | |
343d35dc | 4117 | if Present (Abstract_Interface_Alias (Prim)) |
4118 | and then Is_Interface | |
4119 | (Find_Dispatching_Type | |
4120 | (Abstract_Interface_Alias (Prim))) | |
4121 | then | |
4122 | Set_DTC_Entity (Prim, | |
4123 | Find_Interface_Tag | |
4124 | (T => Typ, | |
4125 | Iface => Find_Dispatching_Type | |
4126 | (Abstract_Interface_Alias (Prim)))); | |
4127 | else | |
4128 | Set_DTC_Entity (Prim, The_Tag); | |
4129 | end if; | |
ee6ba406 | 4130 | |
343d35dc | 4131 | -- Clear any previous value of the DT_Position attribute. In this |
4132 | -- way we ensure that the final position of all the primitives is | |
4133 | -- stablished by the following stages of this algorithm. | |
ee6ba406 | 4134 | |
343d35dc | 4135 | Set_DT_Position (Prim, No_Uint); |
ee6ba406 | 4136 | |
343d35dc | 4137 | Next_Elmt (Prim_Elmt); |
4138 | end loop; | |
ee6ba406 | 4139 | |
343d35dc | 4140 | declare |
4141 | Fixed_Prim : array (Int range 0 .. Count_Prim) of Boolean | |
4142 | := (others => False); | |
4143 | E : Entity_Id; | |
ee6ba406 | 4144 | |
343d35dc | 4145 | procedure Set_Fixed_Prim (Pos : Nat); |
4146 | -- Sets to true an element of the Fixed_Prim table to indicate | |
4147 | -- that this entry of the dispatch table of Typ is occupied. | |
ee6ba406 | 4148 | |
343d35dc | 4149 | -------------------- |
4150 | -- Set_Fixed_Prim -- | |
4151 | -------------------- | |
ee6ba406 | 4152 | |
343d35dc | 4153 | procedure Set_Fixed_Prim (Pos : Nat) is |
ee6ba406 | 4154 | begin |
343d35dc | 4155 | pragma Assert (Pos >= 0 and then Pos <= Count_Prim); |
4156 | Fixed_Prim (Pos) := True; | |
4157 | exception | |
4158 | when Constraint_Error => | |
4159 | raise Program_Error; | |
4160 | end Set_Fixed_Prim; | |
ee6ba406 | 4161 | |
343d35dc | 4162 | begin |
4163 | -- Second stage: Register fixed entries | |
ee6ba406 | 4164 | |
343d35dc | 4165 | Nb_Prim := 0; |
4166 | Prim_Elmt := First_Prim; | |
4167 | while Present (Prim_Elmt) loop | |
4168 | Prim := Node (Prim_Elmt); | |
ee6ba406 | 4169 | |
343d35dc | 4170 | -- Predefined primitives have a separate table and all its |
4171 | -- entries are at predefined fixed positions. | |
ee6ba406 | 4172 | |
343d35dc | 4173 | if Is_Predefined_Dispatching_Operation (Prim) then |
4174 | Set_DT_Position (Prim, Default_Prim_Op_Position (Prim)); | |
ee6ba406 | 4175 | |
343d35dc | 4176 | elsif Is_Predefined_Dispatching_Alias (Prim) then |
4177 | E := Alias (Prim); | |
4178 | while Present (Alias (E)) loop | |
4179 | E := Alias (E); | |
4180 | end loop; | |
d62940bf | 4181 | |
343d35dc | 4182 | Set_DT_Position (Prim, Default_Prim_Op_Position (E)); |
d62940bf | 4183 | |
343d35dc | 4184 | -- Overriding primitives of ancestor abstract interfaces |
ee6ba406 | 4185 | |
343d35dc | 4186 | elsif Present (Abstract_Interface_Alias (Prim)) |
4187 | and then Is_Parent | |
4188 | (Find_Dispatching_Type | |
4189 | (Abstract_Interface_Alias (Prim)), | |
4190 | Typ) | |
4191 | then | |
4192 | pragma Assert (DT_Position (Prim) = No_Uint | |
4193 | and then Present (DTC_Entity | |
4194 | (Abstract_Interface_Alias (Prim)))); | |
ee6ba406 | 4195 | |
343d35dc | 4196 | E := Abstract_Interface_Alias (Prim); |
4197 | Set_DT_Position (Prim, DT_Position (E)); | |
aad6babd | 4198 | |
343d35dc | 4199 | pragma Assert |
4200 | (DT_Position (Alias (Prim)) = No_Uint | |
4201 | or else DT_Position (Alias (Prim)) = DT_Position (E)); | |
4202 | Set_DT_Position (Alias (Prim), DT_Position (E)); | |
4203 | Set_Fixed_Prim (UI_To_Int (DT_Position (Prim))); | |
af647dc7 | 4204 | |
343d35dc | 4205 | -- Overriding primitives must use the same entry as the |
4206 | -- overriden primitive | |
af647dc7 | 4207 | |
343d35dc | 4208 | elsif not Present (Abstract_Interface_Alias (Prim)) |
4209 | and then Present (Alias (Prim)) | |
4210 | and then Find_Dispatching_Type (Alias (Prim)) /= Typ | |
4211 | and then Is_Parent | |
4212 | (Find_Dispatching_Type (Alias (Prim)), Typ) | |
4213 | and then Present (DTC_Entity (Alias (Prim))) | |
af647dc7 | 4214 | then |
343d35dc | 4215 | E := Alias (Prim); |
4216 | Set_DT_Position (Prim, DT_Position (E)); | |
aad6babd | 4217 | |
343d35dc | 4218 | if not Is_Predefined_Dispatching_Alias (E) then |
4219 | Set_Fixed_Prim (UI_To_Int (DT_Position (E))); | |
4220 | end if; | |
9dfe12ae | 4221 | end if; |
ee6ba406 | 4222 | |
aad6babd | 4223 | Next_Elmt (Prim_Elmt); |
4224 | end loop; | |
4225 | ||
343d35dc | 4226 | -- Third stage: Fix the position of all the new primitives |
4227 | -- Entries associated with primitives covering interfaces | |
4228 | -- are handled in a latter round. | |
aad6babd | 4229 | |
343d35dc | 4230 | Prim_Elmt := First_Prim; |
4231 | while Present (Prim_Elmt) loop | |
4232 | Prim := Node (Prim_Elmt); | |
aad6babd | 4233 | |
343d35dc | 4234 | -- Skip primitives previously set entries |
aad6babd | 4235 | |
343d35dc | 4236 | if DT_Position (Prim) /= No_Uint then |
4237 | null; | |
aad6babd | 4238 | |
343d35dc | 4239 | -- Primitives covering interface primitives are handled later |
aad6babd | 4240 | |
343d35dc | 4241 | elsif Present (Abstract_Interface_Alias (Prim)) then |
4242 | null; | |
aad6babd | 4243 | |
343d35dc | 4244 | else |
4245 | -- Take the next available position in the DT | |
aad6babd | 4246 | |
343d35dc | 4247 | loop |
4248 | Nb_Prim := Nb_Prim + 1; | |
4249 | pragma Assert (Nb_Prim <= Count_Prim); | |
4250 | exit when not Fixed_Prim (Nb_Prim); | |
4251 | end loop; | |
aad6babd | 4252 | |
343d35dc | 4253 | Set_DT_Position (Prim, UI_From_Int (Nb_Prim)); |
4254 | Set_Fixed_Prim (Nb_Prim); | |
4255 | end if; | |
aad6babd | 4256 | |
343d35dc | 4257 | Next_Elmt (Prim_Elmt); |
4258 | end loop; | |
4259 | end; | |
aad6babd | 4260 | |
343d35dc | 4261 | -- Fourth stage: Complete the decoration of primitives covering |
4262 | -- interfaces (that is, propagate the DT_Position attribute | |
4263 | -- from the aliased primitive) | |
aad6babd | 4264 | |
343d35dc | 4265 | Prim_Elmt := First_Prim; |
4266 | while Present (Prim_Elmt) loop | |
4267 | Prim := Node (Prim_Elmt); | |
aad6babd | 4268 | |
343d35dc | 4269 | if DT_Position (Prim) = No_Uint |
4270 | and then Present (Abstract_Interface_Alias (Prim)) | |
4271 | then | |
4272 | pragma Assert (Present (Alias (Prim)) | |
4273 | and then Find_Dispatching_Type (Alias (Prim)) = Typ); | |
aad6babd | 4274 | |
343d35dc | 4275 | -- Check if this entry will be placed in the primary DT |
aad6babd | 4276 | |
343d35dc | 4277 | if Is_Parent (Find_Dispatching_Type |
4278 | (Abstract_Interface_Alias (Prim)), | |
4279 | Typ) | |
ee6ba406 | 4280 | then |
343d35dc | 4281 | pragma Assert (DT_Position (Alias (Prim)) /= No_Uint); |
4282 | Set_DT_Position (Prim, DT_Position (Alias (Prim))); | |
aad6babd | 4283 | |
343d35dc | 4284 | -- Otherwise it will be placed in the secondary DT |
aad6babd | 4285 | |
343d35dc | 4286 | else |
4287 | pragma Assert | |
4288 | (DT_Position (Abstract_Interface_Alias (Prim)) /= No_Uint); | |
4289 | Set_DT_Position (Prim, | |
4290 | DT_Position (Abstract_Interface_Alias (Prim))); | |
aad6babd | 4291 | end if; |
343d35dc | 4292 | end if; |
aad6babd | 4293 | |
343d35dc | 4294 | Next_Elmt (Prim_Elmt); |
4295 | end loop; | |
d62940bf | 4296 | |
343d35dc | 4297 | -- Generate listing showing the contents of the dispatch tables. |
4298 | -- This action is done before some further static checks because | |
4299 | -- in case of critical errors caused by a wrong dispatch table | |
4300 | -- we need to see the contents of such table. | |
d62940bf | 4301 | |
343d35dc | 4302 | if Debug_Flag_ZZ then |
4303 | Write_DT (Typ); | |
4304 | end if; | |
aad6babd | 4305 | |
343d35dc | 4306 | -- Final stage: Ensure that the table is correct plus some further |
4307 | -- verifications concerning the primitives. | |
aad6babd | 4308 | |
343d35dc | 4309 | Prim_Elmt := First_Prim; |
4310 | DT_Length := 0; | |
4311 | while Present (Prim_Elmt) loop | |
4312 | Prim := Node (Prim_Elmt); | |
aad6babd | 4313 | |
343d35dc | 4314 | -- At this point all the primitives MUST have a position |
4315 | -- in the dispatch table | |
aad6babd | 4316 | |
343d35dc | 4317 | if DT_Position (Prim) = No_Uint then |
4318 | raise Program_Error; | |
4319 | end if; | |
aad6babd | 4320 | |
343d35dc | 4321 | -- Calculate real size of the dispatch table |
aad6babd | 4322 | |
343d35dc | 4323 | if not (Is_Predefined_Dispatching_Operation (Prim) |
4324 | or else Is_Predefined_Dispatching_Alias (Prim)) | |
4325 | and then UI_To_Int (DT_Position (Prim)) > DT_Length | |
4326 | then | |
4327 | DT_Length := UI_To_Int (DT_Position (Prim)); | |
4328 | end if; | |
aad6babd | 4329 | |
343d35dc | 4330 | -- Ensure that the asignated position to non-predefined |
4331 | -- dispatching operations in the dispatch table is correct. | |
aad6babd | 4332 | |
343d35dc | 4333 | if not (Is_Predefined_Dispatching_Operation (Prim) |
4334 | or else Is_Predefined_Dispatching_Alias (Prim)) | |
4335 | then | |
4336 | Validate_Position (Prim); | |
4337 | end if; | |
ee6ba406 | 4338 | |
343d35dc | 4339 | if Chars (Prim) = Name_Finalize then |
4340 | Finalized := True; | |
4341 | end if; | |
ee6ba406 | 4342 | |
343d35dc | 4343 | if Chars (Prim) = Name_Adjust then |
4344 | Adjusted := True; | |
4345 | end if; | |
af647dc7 | 4346 | |
343d35dc | 4347 | -- An abstract operation cannot be declared in the private part |
4348 | -- for a visible abstract type, because it could never be over- | |
4349 | -- ridden. For explicit declarations this is checked at the | |
4350 | -- point of declaration, but for inherited operations it must | |
4351 | -- be done when building the dispatch table. | |
4352 | ||
4353 | -- Ada 2005 (AI-251): Hidden entities associated with abstract | |
4354 | -- interface primitives are not taken into account because the | |
4355 | -- check is done with the aliased primitive. | |
4356 | ||
4357 | if Is_Abstract_Type (Typ) | |
4358 | and then Is_Abstract_Subprogram (Prim) | |
4359 | and then Present (Alias (Prim)) | |
4360 | and then not Present (Abstract_Interface_Alias (Prim)) | |
4361 | and then Is_Derived_Type (Typ) | |
4362 | and then In_Private_Part (Current_Scope) | |
4363 | and then | |
4364 | List_Containing (Parent (Prim)) = | |
4365 | Private_Declarations | |
4366 | (Specification (Unit_Declaration_Node (Current_Scope))) | |
4367 | and then Original_View_In_Visible_Part (Typ) | |
4368 | then | |
4369 | -- We exclude Input and Output stream operations because | |
4370 | -- Limited_Controlled inherits useless Input and Output | |
4371 | -- stream operations from Root_Controlled, which can | |
4372 | -- never be overridden. | |
ee6ba406 | 4373 | |
343d35dc | 4374 | if not Is_TSS (Prim, TSS_Stream_Input) |
4375 | and then | |
4376 | not Is_TSS (Prim, TSS_Stream_Output) | |
ee6ba406 | 4377 | then |
343d35dc | 4378 | Error_Msg_NE |
4379 | ("abstract inherited private operation&" & | |
4380 | " must be overridden ('R'M 3.9.3(10))", | |
4381 | Parent (Typ), Prim); | |
ee6ba406 | 4382 | end if; |
343d35dc | 4383 | end if; |
aad6babd | 4384 | |
343d35dc | 4385 | Next_Elmt (Prim_Elmt); |
4386 | end loop; | |
ee6ba406 | 4387 | |
343d35dc | 4388 | -- Additional check |
aad6babd | 4389 | |
343d35dc | 4390 | if Is_Controlled (Typ) then |
4391 | if not Finalized then | |
4392 | Error_Msg_N | |
4393 | ("controlled type has no explicit Finalize method?", Typ); | |
ee6ba406 | 4394 | |
343d35dc | 4395 | elsif not Adjusted then |
4396 | Error_Msg_N | |
4397 | ("controlled type has no explicit Adjust method?", Typ); | |
ee6ba406 | 4398 | end if; |
343d35dc | 4399 | end if; |
ee6ba406 | 4400 | |
343d35dc | 4401 | -- Set the final size of the Dispatch Table |
aad6babd | 4402 | |
343d35dc | 4403 | Set_DT_Entry_Count (The_Tag, UI_From_Int (DT_Length)); |
ee6ba406 | 4404 | |
343d35dc | 4405 | -- The derived type must have at least as many components as its |
4406 | -- parent (for root types, the Etype points back to itself | |
4407 | -- and the test should not fail) | |
ee6ba406 | 4408 | |
343d35dc | 4409 | -- This test fails compiling the partial view of a tagged type |
4410 | -- derived from an interface which defines the overriding subprogram | |
4411 | -- in the private part. This needs further investigation??? | |
aad6babd | 4412 | |
343d35dc | 4413 | if not Has_Private_Declaration (Typ) then |
4414 | pragma Assert ( | |
4415 | DT_Entry_Count (The_Tag) >= | |
4416 | DT_Entry_Count (First_Tag_Component (Parent_Typ))); | |
4417 | null; | |
aad6babd | 4418 | end if; |
ee6ba406 | 4419 | end Set_All_DT_Position; |
4420 | ||
4421 | ----------------------------- | |
4422 | -- Set_Default_Constructor -- | |
4423 | ----------------------------- | |
4424 | ||
4425 | procedure Set_Default_Constructor (Typ : Entity_Id) is | |
4426 | Loc : Source_Ptr; | |
4427 | Init : Entity_Id; | |
4428 | Param : Entity_Id; | |
ee6ba406 | 4429 | E : Entity_Id; |
4430 | ||
4431 | begin | |
4432 | -- Look for the default constructor entity. For now only the | |
4433 | -- default constructor has the flag Is_Constructor. | |
4434 | ||
4435 | E := Next_Entity (Typ); | |
4436 | while Present (E) | |
4437 | and then (Ekind (E) /= E_Function or else not Is_Constructor (E)) | |
4438 | loop | |
4439 | Next_Entity (E); | |
4440 | end loop; | |
4441 | ||
4442 | -- Create the init procedure | |
4443 | ||
4444 | if Present (E) then | |
4445 | Loc := Sloc (E); | |
9dfe12ae | 4446 | Init := Make_Defining_Identifier (Loc, Make_Init_Proc_Name (Typ)); |
ee6ba406 | 4447 | Param := Make_Defining_Identifier (Loc, Name_X); |
9dfe12ae | 4448 | |
4449 | Discard_Node ( | |
ee6ba406 | 4450 | Make_Subprogram_Declaration (Loc, |
4451 | Make_Procedure_Specification (Loc, | |
4452 | Defining_Unit_Name => Init, | |
4453 | Parameter_Specifications => New_List ( | |
4454 | Make_Parameter_Specification (Loc, | |
4455 | Defining_Identifier => Param, | |
9dfe12ae | 4456 | Parameter_Type => New_Reference_To (Typ, Loc)))))); |
ee6ba406 | 4457 | |
4458 | Set_Init_Proc (Typ, Init); | |
9dfe12ae | 4459 | Set_Is_Imported (Init); |
ee6ba406 | 4460 | Set_Interface_Name (Init, Interface_Name (E)); |
9dfe12ae | 4461 | Set_Convention (Init, Convention_C); |
4462 | Set_Is_Public (Init); | |
ee6ba406 | 4463 | Set_Has_Completion (Init); |
4464 | ||
9dfe12ae | 4465 | -- If there are no constructors, mark the type as abstract since we |
ee6ba406 | 4466 | -- won't be able to declare objects of that type. |
4467 | ||
4468 | else | |
343d35dc | 4469 | Set_Is_Abstract_Type (Typ); |
ee6ba406 | 4470 | end if; |
4471 | end Set_Default_Constructor; | |
4472 | ||
952af0b9 | 4473 | ----------------- |
4474 | -- Tagged_Kind -- | |
4475 | ----------------- | |
4476 | ||
4477 | function Tagged_Kind (T : Entity_Id) return Node_Id is | |
4478 | Conc_Typ : Entity_Id; | |
4479 | Loc : constant Source_Ptr := Sloc (T); | |
4480 | ||
4481 | begin | |
68f95949 | 4482 | pragma Assert |
4483 | (Is_Tagged_Type (T) and then RTE_Available (RE_Tagged_Kind)); | |
952af0b9 | 4484 | |
4485 | -- Abstract kinds | |
4486 | ||
343d35dc | 4487 | if Is_Abstract_Type (T) then |
952af0b9 | 4488 | if Is_Limited_Record (T) then |
4489 | return New_Reference_To (RTE (RE_TK_Abstract_Limited_Tagged), Loc); | |
4490 | else | |
4491 | return New_Reference_To (RTE (RE_TK_Abstract_Tagged), Loc); | |
4492 | end if; | |
4493 | ||
4494 | -- Concurrent kinds | |
4495 | ||
4496 | elsif Is_Concurrent_Record_Type (T) then | |
4497 | Conc_Typ := Corresponding_Concurrent_Type (T); | |
4498 | ||
4499 | if Ekind (Conc_Typ) = E_Protected_Type then | |
4500 | return New_Reference_To (RTE (RE_TK_Protected), Loc); | |
4501 | else | |
4502 | pragma Assert (Ekind (Conc_Typ) = E_Task_Type); | |
4503 | return New_Reference_To (RTE (RE_TK_Task), Loc); | |
4504 | end if; | |
4505 | ||
4506 | -- Regular tagged kinds | |
4507 | ||
4508 | else | |
4509 | if Is_Limited_Record (T) then | |
4510 | return New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc); | |
4511 | else | |
4512 | return New_Reference_To (RTE (RE_TK_Tagged), Loc); | |
4513 | end if; | |
4514 | end if; | |
4515 | end Tagged_Kind; | |
4516 | ||
aad6babd | 4517 | -------------- |
4518 | -- Write_DT -- | |
4519 | -------------- | |
4520 | ||
4521 | procedure Write_DT (Typ : Entity_Id) is | |
4522 | Elmt : Elmt_Id; | |
4523 | Prim : Node_Id; | |
4524 | ||
4525 | begin | |
4526 | -- Protect this procedure against wrong usage. Required because it will | |
4527 | -- be used directly from GDB | |
4528 | ||
4529 | if not (Typ in First_Node_Id .. Last_Node_Id) | |
4530 | or else not Is_Tagged_Type (Typ) | |
4531 | then | |
d62940bf | 4532 | Write_Str ("wrong usage: Write_DT must be used with tagged types"); |
aad6babd | 4533 | Write_Eol; |
4534 | return; | |
4535 | end if; | |
4536 | ||
4537 | Write_Int (Int (Typ)); | |
4538 | Write_Str (": "); | |
4539 | Write_Name (Chars (Typ)); | |
4540 | ||
4541 | if Is_Interface (Typ) then | |
4542 | Write_Str (" is interface"); | |
4543 | end if; | |
4544 | ||
4545 | Write_Eol; | |
4546 | ||
4547 | Elmt := First_Elmt (Primitive_Operations (Typ)); | |
4548 | while Present (Elmt) loop | |
4549 | Prim := Node (Elmt); | |
4550 | Write_Str (" - "); | |
4551 | ||
4552 | -- Indicate if this primitive will be allocated in the primary | |
4553 | -- dispatch table or in a secondary dispatch table associated | |
4554 | -- with an abstract interface type | |
4555 | ||
4556 | if Present (DTC_Entity (Prim)) then | |
4557 | if Etype (DTC_Entity (Prim)) = RTE (RE_Tag) then | |
4558 | Write_Str ("[P] "); | |
4559 | else | |
4560 | Write_Str ("[s] "); | |
4561 | end if; | |
4562 | end if; | |
4563 | ||
4564 | -- Output the node of this primitive operation and its name | |
4565 | ||
4566 | Write_Int (Int (Prim)); | |
4567 | Write_Str (": "); | |
68f95949 | 4568 | |
4569 | if Is_Predefined_Dispatching_Operation (Prim) then | |
4570 | Write_Str ("(predefined) "); | |
4571 | end if; | |
4572 | ||
aad6babd | 4573 | Write_Name (Chars (Prim)); |
4574 | ||
4575 | -- Indicate if this primitive has an aliased primitive | |
4576 | ||
4577 | if Present (Alias (Prim)) then | |
4578 | Write_Str (" (alias = "); | |
4579 | Write_Int (Int (Alias (Prim))); | |
4580 | ||
4581 | -- If the DTC_Entity attribute is already set we can also output | |
4582 | -- the name of the interface covered by this primitive (if any) | |
4583 | ||
4584 | if Present (DTC_Entity (Alias (Prim))) | |
4585 | and then Is_Interface (Scope (DTC_Entity (Alias (Prim)))) | |
4586 | then | |
4587 | Write_Str (" from interface "); | |
4588 | Write_Name (Chars (Scope (DTC_Entity (Alias (Prim))))); | |
4589 | end if; | |
4590 | ||
4591 | if Present (Abstract_Interface_Alias (Prim)) then | |
4592 | Write_Str (", AI_Alias of "); | |
4593 | Write_Name (Chars (Scope (DTC_Entity | |
4594 | (Abstract_Interface_Alias (Prim))))); | |
4595 | Write_Char (':'); | |
4596 | Write_Int (Int (Abstract_Interface_Alias (Prim))); | |
4597 | end if; | |
4598 | ||
4599 | Write_Str (")"); | |
4600 | end if; | |
4601 | ||
4602 | -- Display the final position of this primitive in its associated | |
4603 | -- (primary or secondary) dispatch table | |
4604 | ||
4605 | if Present (DTC_Entity (Prim)) | |
4606 | and then DT_Position (Prim) /= No_Uint | |
4607 | then | |
4608 | Write_Str (" at #"); | |
4609 | Write_Int (UI_To_Int (DT_Position (Prim))); | |
4610 | end if; | |
4611 | ||
343d35dc | 4612 | if Is_Abstract_Subprogram (Prim) then |
aad6babd | 4613 | Write_Str (" is abstract;"); |
af647dc7 | 4614 | |
4615 | -- Check if this is a null primitive | |
4616 | ||
4617 | elsif Comes_From_Source (Prim) | |
4618 | and then Ekind (Prim) = E_Procedure | |
4619 | and then Null_Present (Parent (Prim)) | |
4620 | then | |
4621 | Write_Str (" is null;"); | |
aad6babd | 4622 | end if; |
4623 | ||
4624 | Write_Eol; | |
4625 | ||
4626 | Next_Elmt (Elmt); | |
4627 | end loop; | |
4628 | end Write_DT; | |
4629 | ||
ee6ba406 | 4630 | end Exp_Disp; |