2011-06-29 François Dumont <francois.cppdevs@free.fr>
[official-gcc.git] / gcc / ada / exp_atag.adb
blob7ed2a3f5f840beb54fd26071fa5c6ad71310fab1
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ A T A G --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2006-2010, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with Atree; use Atree;
27 with Einfo; use Einfo;
28 with Elists; use Elists;
29 with Exp_Disp; use Exp_Disp;
30 with Exp_Util; use Exp_Util;
31 with Namet; use Namet;
32 with Nlists; use Nlists;
33 with Nmake; use Nmake;
34 with Rtsfind; use Rtsfind;
35 with Sinfo; use Sinfo;
36 with Sem_Aux; use Sem_Aux;
37 with Sem_Disp; use Sem_Disp;
38 with Sem_Util; use Sem_Util;
39 with Stand; use Stand;
40 with Snames; use Snames;
41 with Tbuild; use Tbuild;
43 package body Exp_Atag is
45 -----------------------
46 -- Local Subprograms --
47 -----------------------
49 function Build_DT
50 (Loc : Source_Ptr;
51 Tag_Node : Node_Id) return Node_Id;
52 -- Build code that displaces the Tag to reference the base of the wrapper
53 -- record
55 -- Generates:
56 -- To_Dispatch_Table_Ptr
57 -- (To_Address (Tag_Node) - Tag_Node.Prims_Ptr'Position);
59 function Build_TSD
60 (Loc : Source_Ptr;
61 Tag_Node_Addr : Node_Id) return Node_Id;
62 -- Build code that retrieves the address of the record containing the Type
63 -- Specific Data generated by GNAT.
65 -- Generate: To_Type_Specific_Data_Ptr
66 -- (To_Addr_Ptr (Tag_Node_Addr - Typeinfo_Offset).all);
68 ------------------------------------------------
69 -- Build_Common_Dispatching_Select_Statements --
70 ------------------------------------------------
72 procedure Build_Common_Dispatching_Select_Statements
73 (Loc : Source_Ptr;
74 DT_Ptr : Entity_Id;
75 Stmts : List_Id)
77 begin
78 -- Generate:
79 -- C := get_prim_op_kind (tag! (<type>VP), S);
81 -- where C is the out parameter capturing the call kind and S is the
82 -- dispatch table slot number.
84 Append_To (Stmts,
85 Make_Assignment_Statement (Loc,
86 Name => Make_Identifier (Loc, Name_uC),
87 Expression =>
88 Make_Function_Call (Loc,
89 Name => New_Occurrence_Of (RTE (RE_Get_Prim_Op_Kind), Loc),
90 Parameter_Associations => New_List (
91 Unchecked_Convert_To (RTE (RE_Tag),
92 New_Reference_To (DT_Ptr, Loc)),
93 Make_Identifier (Loc, Name_uS)))));
95 -- Generate:
97 -- if C = POK_Procedure
98 -- or else C = POK_Protected_Procedure
99 -- or else C = POK_Task_Procedure;
100 -- then
101 -- F := True;
102 -- return;
104 -- where F is the out parameter capturing the status of a potential
105 -- entry call.
107 Append_To (Stmts,
108 Make_If_Statement (Loc,
110 Condition =>
111 Make_Or_Else (Loc,
112 Left_Opnd =>
113 Make_Op_Eq (Loc,
114 Left_Opnd => Make_Identifier (Loc, Name_uC),
115 Right_Opnd =>
116 New_Reference_To (RTE (RE_POK_Procedure), Loc)),
117 Right_Opnd =>
118 Make_Or_Else (Loc,
119 Left_Opnd =>
120 Make_Op_Eq (Loc,
121 Left_Opnd => Make_Identifier (Loc, Name_uC),
122 Right_Opnd =>
123 New_Reference_To
124 (RTE (RE_POK_Protected_Procedure), Loc)),
125 Right_Opnd =>
126 Make_Op_Eq (Loc,
127 Left_Opnd => Make_Identifier (Loc, Name_uC),
128 Right_Opnd =>
129 New_Reference_To
130 (RTE (RE_POK_Task_Procedure), Loc)))),
132 Then_Statements =>
133 New_List (
134 Make_Assignment_Statement (Loc,
135 Name => Make_Identifier (Loc, Name_uF),
136 Expression => New_Reference_To (Standard_True, Loc)),
137 Make_Simple_Return_Statement (Loc))));
138 end Build_Common_Dispatching_Select_Statements;
140 -------------------------
141 -- Build_CW_Membership --
142 -------------------------
144 procedure Build_CW_Membership
145 (Loc : Source_Ptr;
146 Obj_Tag_Node : in out Node_Id;
147 Typ_Tag_Node : Node_Id;
148 Related_Nod : Node_Id;
149 New_Node : out Node_Id)
151 Tag_Addr : constant Entity_Id := Make_Temporary (Loc, 'D', Obj_Tag_Node);
152 Obj_TSD : constant Entity_Id := Make_Temporary (Loc, 'D');
153 Typ_TSD : constant Entity_Id := Make_Temporary (Loc, 'D');
154 Index : constant Entity_Id := Make_Temporary (Loc, 'D');
156 begin
157 -- Generate:
159 -- Tag_Addr : constant Tag := Address!(Obj_Tag);
160 -- Obj_TSD : constant Type_Specific_Data_Ptr
161 -- := Build_TSD (Tag_Addr);
162 -- Typ_TSD : constant Type_Specific_Data_Ptr
163 -- := Build_TSD (Address!(Typ_Tag));
164 -- Index : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth
165 -- Index > 0 and then Obj_TSD.Tags_Table (Index) = Typ'Tag
167 Insert_Action (Related_Nod,
168 Make_Object_Declaration (Loc,
169 Defining_Identifier => Tag_Addr,
170 Constant_Present => True,
171 Object_Definition => New_Reference_To (RTE (RE_Address), Loc),
172 Expression => Unchecked_Convert_To
173 (RTE (RE_Address), Obj_Tag_Node)));
175 -- Unchecked_Convert_To relocates Obj_Tag_Node and therefore we must
176 -- update it.
178 Obj_Tag_Node := Expression (Expression (Parent (Tag_Addr)));
180 Insert_Action (Related_Nod,
181 Make_Object_Declaration (Loc,
182 Defining_Identifier => Obj_TSD,
183 Constant_Present => True,
184 Object_Definition => New_Reference_To
185 (RTE (RE_Type_Specific_Data_Ptr), Loc),
186 Expression => Build_TSD (Loc, New_Reference_To (Tag_Addr, Loc))));
188 Insert_Action (Related_Nod,
189 Make_Object_Declaration (Loc,
190 Defining_Identifier => Typ_TSD,
191 Constant_Present => True,
192 Object_Definition => New_Reference_To
193 (RTE (RE_Type_Specific_Data_Ptr), Loc),
194 Expression => Build_TSD (Loc,
195 Unchecked_Convert_To (RTE (RE_Address),
196 Typ_Tag_Node))));
198 Insert_Action (Related_Nod,
199 Make_Object_Declaration (Loc,
200 Defining_Identifier => Index,
201 Constant_Present => True,
202 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
203 Expression =>
204 Make_Op_Subtract (Loc,
205 Left_Opnd =>
206 Make_Selected_Component (Loc,
207 Prefix => New_Reference_To (Obj_TSD, Loc),
208 Selector_Name =>
209 New_Reference_To
210 (RTE_Record_Component (RE_Idepth), Loc)),
212 Right_Opnd =>
213 Make_Selected_Component (Loc,
214 Prefix => New_Reference_To (Typ_TSD, Loc),
215 Selector_Name =>
216 New_Reference_To
217 (RTE_Record_Component (RE_Idepth), Loc)))));
219 New_Node :=
220 Make_And_Then (Loc,
221 Left_Opnd =>
222 Make_Op_Ge (Loc,
223 Left_Opnd => New_Occurrence_Of (Index, Loc),
224 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
226 Right_Opnd =>
227 Make_Op_Eq (Loc,
228 Left_Opnd =>
229 Make_Indexed_Component (Loc,
230 Prefix =>
231 Make_Selected_Component (Loc,
232 Prefix => New_Reference_To (Obj_TSD, Loc),
233 Selector_Name =>
234 New_Reference_To
235 (RTE_Record_Component (RE_Tags_Table), Loc)),
236 Expressions =>
237 New_List (New_Occurrence_Of (Index, Loc))),
239 Right_Opnd => Typ_Tag_Node));
240 end Build_CW_Membership;
242 --------------
243 -- Build_DT --
244 --------------
246 function Build_DT
247 (Loc : Source_Ptr;
248 Tag_Node : Node_Id) return Node_Id
250 begin
251 return
252 Make_Function_Call (Loc,
253 Name => New_Reference_To (RTE (RE_DT), Loc),
254 Parameter_Associations => New_List (
255 Unchecked_Convert_To (RTE (RE_Tag), Tag_Node)));
256 end Build_DT;
258 ----------------------------
259 -- Build_Get_Access_Level --
260 ----------------------------
262 function Build_Get_Access_Level
263 (Loc : Source_Ptr;
264 Tag_Node : Node_Id) return Node_Id
266 begin
267 return
268 Make_Selected_Component (Loc,
269 Prefix =>
270 Build_TSD (Loc,
271 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
272 Selector_Name =>
273 New_Reference_To
274 (RTE_Record_Component (RE_Access_Level), Loc));
275 end Build_Get_Access_Level;
277 ------------------------------------------
278 -- Build_Get_Predefined_Prim_Op_Address --
279 ------------------------------------------
281 procedure Build_Get_Predefined_Prim_Op_Address
282 (Loc : Source_Ptr;
283 Position : Uint;
284 Tag_Node : in out Node_Id;
285 New_Node : out Node_Id)
287 Ctrl_Tag : Node_Id;
289 begin
290 Ctrl_Tag := Unchecked_Convert_To (RTE (RE_Address), Tag_Node);
292 -- Unchecked_Convert_To relocates the controlling tag node and therefore
293 -- we must update it.
295 Tag_Node := Expression (Ctrl_Tag);
297 -- Build code that retrieves the address of the dispatch table
298 -- containing the predefined Ada primitives:
300 -- Generate:
301 -- To_Predef_Prims_Table_Ptr
302 -- (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all);
304 New_Node :=
305 Make_Indexed_Component (Loc,
306 Prefix =>
307 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
308 Make_Explicit_Dereference (Loc,
309 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
310 Make_Function_Call (Loc,
311 Name =>
312 Make_Expanded_Name (Loc,
313 Chars => Name_Op_Subtract,
314 Prefix =>
315 New_Reference_To
316 (RTU_Entity (System_Storage_Elements), Loc),
317 Selector_Name =>
318 Make_Identifier (Loc, Name_Op_Subtract)),
319 Parameter_Associations => New_List (
320 Ctrl_Tag,
321 New_Reference_To
322 (RTE (RE_DT_Predef_Prims_Offset), Loc)))))),
323 Expressions =>
324 New_List (Make_Integer_Literal (Loc, Position)));
325 end Build_Get_Predefined_Prim_Op_Address;
327 -----------------------------
328 -- Build_Inherit_CPP_Prims --
329 -----------------------------
331 function Build_Inherit_CPP_Prims (Typ : Entity_Id) return List_Id is
332 Loc : constant Source_Ptr := Sloc (Typ);
333 CPP_Nb_Prims : constant Nat := CPP_Num_Prims (Typ);
334 CPP_Table : array (1 .. CPP_Nb_Prims) of Boolean := (others => False);
335 CPP_Typ : constant Entity_Id := Enclosing_CPP_Parent (Typ);
336 Result : constant List_Id := New_List;
337 Parent_Typ : constant Entity_Id := Etype (Typ);
338 E : Entity_Id;
339 Elmt : Elmt_Id;
340 Parent_Tag : Entity_Id;
341 Prim : Entity_Id;
342 Prim_Pos : Nat;
343 Typ_Tag : Entity_Id;
345 begin
346 pragma Assert (not Is_CPP_Class (Typ));
348 -- No code needed if this type has no primitives inherited from C++
350 if CPP_Nb_Prims = 0 then
351 return Result;
352 end if;
354 -- Stage 1: Inherit and override C++ slots of the primary dispatch table
356 -- Generate:
357 -- Typ'Tag (Prim_Pos) := Prim'Unrestricted_Access;
359 Parent_Tag := Node (First_Elmt (Access_Disp_Table (Parent_Typ)));
360 Typ_Tag := Node (First_Elmt (Access_Disp_Table (Typ)));
362 Elmt := First_Elmt (Primitive_Operations (Typ));
363 while Present (Elmt) loop
364 Prim := Node (Elmt);
365 E := Ultimate_Alias (Prim);
366 Prim_Pos := UI_To_Int (DT_Position (E));
368 -- Skip predefined, abstract, and eliminated primitives. Skip also
369 -- primitives not located in the C++ part of the dispatch table.
371 if not Is_Predefined_Dispatching_Operation (Prim)
372 and then not Is_Predefined_Dispatching_Operation (E)
373 and then not Present (Interface_Alias (Prim))
374 and then not Is_Abstract_Subprogram (E)
375 and then not Is_Eliminated (E)
376 and then Prim_Pos <= CPP_Nb_Prims
377 and then Find_Dispatching_Type (E) = Typ
378 then
379 -- Remember that this slot is used
381 pragma Assert (CPP_Table (Prim_Pos) = False);
382 CPP_Table (Prim_Pos) := True;
384 Append_To (Result,
385 Make_Assignment_Statement (Loc,
386 Name =>
387 Make_Indexed_Component (Loc,
388 Prefix =>
389 Make_Explicit_Dereference (Loc,
390 Unchecked_Convert_To
391 (Node (Last_Elmt (Access_Disp_Table (Typ))),
392 New_Reference_To (Typ_Tag, Loc))),
393 Expressions =>
394 New_List (Make_Integer_Literal (Loc, Prim_Pos))),
396 Expression =>
397 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
398 Make_Attribute_Reference (Loc,
399 Prefix => New_Reference_To (E, Loc),
400 Attribute_Name => Name_Unrestricted_Access))));
401 end if;
403 Next_Elmt (Elmt);
404 end loop;
406 -- If all primitives have been overridden then there is no need to copy
407 -- from Typ's parent its dispatch table. Otherwise, if some primitive is
408 -- inherited from the parent we copy only the C++ part of the dispatch
409 -- table from the parent before the assignments that initialize the
410 -- overridden primitives.
412 -- Generate:
414 -- type CPP_TypG is array (1 .. CPP_Nb_Prims) ofd Prim_Ptr;
415 -- type CPP_TypH is access CPP_TypG;
416 -- CPP_TypG!(Typ_Tag).all := CPP_TypG!(Parent_Tag).all;
418 -- Note: There is no need to duplicate the declarations of CPP_TypG and
419 -- CPP_TypH because, for expansion of dispatching calls, these
420 -- entities are stored in the last elements of Access_Disp_Table.
422 for J in CPP_Table'Range loop
423 if not CPP_Table (J) then
424 Prepend_To (Result,
425 Make_Assignment_Statement (Loc,
426 Name =>
427 Make_Explicit_Dereference (Loc,
428 Unchecked_Convert_To
429 (Node (Last_Elmt (Access_Disp_Table (CPP_Typ))),
430 New_Reference_To (Typ_Tag, Loc))),
431 Expression =>
432 Make_Explicit_Dereference (Loc,
433 Unchecked_Convert_To
434 (Node (Last_Elmt (Access_Disp_Table (CPP_Typ))),
435 New_Reference_To (Parent_Tag, Loc)))));
436 exit;
437 end if;
438 end loop;
440 -- Stage 2: Inherit and override C++ slots of secondary dispatch tables
442 declare
443 Iface : Entity_Id;
444 Iface_Nb_Prims : Nat;
445 Parent_Ifaces_List : Elist_Id;
446 Parent_Ifaces_Comp_List : Elist_Id;
447 Parent_Ifaces_Tag_List : Elist_Id;
448 Parent_Iface_Tag_Elmt : Elmt_Id;
449 Typ_Ifaces_List : Elist_Id;
450 Typ_Ifaces_Comp_List : Elist_Id;
451 Typ_Ifaces_Tag_List : Elist_Id;
452 Typ_Iface_Tag_Elmt : Elmt_Id;
454 begin
455 Collect_Interfaces_Info
456 (T => Parent_Typ,
457 Ifaces_List => Parent_Ifaces_List,
458 Components_List => Parent_Ifaces_Comp_List,
459 Tags_List => Parent_Ifaces_Tag_List);
461 Collect_Interfaces_Info
462 (T => Typ,
463 Ifaces_List => Typ_Ifaces_List,
464 Components_List => Typ_Ifaces_Comp_List,
465 Tags_List => Typ_Ifaces_Tag_List);
467 Parent_Iface_Tag_Elmt := First_Elmt (Parent_Ifaces_Tag_List);
468 Typ_Iface_Tag_Elmt := First_Elmt (Typ_Ifaces_Tag_List);
469 while Present (Parent_Iface_Tag_Elmt) loop
470 Parent_Tag := Node (Parent_Iface_Tag_Elmt);
471 Typ_Tag := Node (Typ_Iface_Tag_Elmt);
473 pragma Assert
474 (Related_Type (Parent_Tag) = Related_Type (Typ_Tag));
475 Iface := Related_Type (Parent_Tag);
477 Iface_Nb_Prims :=
478 UI_To_Int (DT_Entry_Count (First_Tag_Component (Iface)));
480 if Iface_Nb_Prims > 0 then
482 -- Update slots of overridden primitives
484 declare
485 Last_Nod : constant Node_Id := Last (Result);
486 Nb_Prims : constant Nat := UI_To_Int
487 (DT_Entry_Count
488 (First_Tag_Component (Iface)));
489 Elmt : Elmt_Id;
490 Prim : Entity_Id;
491 E : Entity_Id;
492 Prim_Pos : Nat;
494 Prims_Table : array (1 .. Nb_Prims) of Boolean;
496 begin
497 Prims_Table := (others => False);
499 Elmt := First_Elmt (Primitive_Operations (Typ));
500 while Present (Elmt) loop
501 Prim := Node (Elmt);
502 E := Ultimate_Alias (Prim);
504 if not Is_Predefined_Dispatching_Operation (Prim)
505 and then Present (Interface_Alias (Prim))
506 and then Find_Dispatching_Type (Interface_Alias (Prim))
507 = Iface
508 and then not Is_Abstract_Subprogram (E)
509 and then not Is_Eliminated (E)
510 and then Find_Dispatching_Type (E) = Typ
511 then
512 Prim_Pos := UI_To_Int (DT_Position (Prim));
514 -- Remember that this slot is already initialized
516 pragma Assert (Prims_Table (Prim_Pos) = False);
517 Prims_Table (Prim_Pos) := True;
519 Append_To (Result,
520 Make_Assignment_Statement (Loc,
521 Name =>
522 Make_Indexed_Component (Loc,
523 Prefix =>
524 Make_Explicit_Dereference (Loc,
525 Unchecked_Convert_To
526 (Node
527 (Last_Elmt
528 (Access_Disp_Table (Iface))),
529 New_Reference_To (Typ_Tag, Loc))),
530 Expressions =>
531 New_List
532 (Make_Integer_Literal (Loc, Prim_Pos))),
534 Expression =>
535 Unchecked_Convert_To (RTE (RE_Prim_Ptr),
536 Make_Attribute_Reference (Loc,
537 Prefix => New_Reference_To (E, Loc),
538 Attribute_Name =>
539 Name_Unrestricted_Access))));
540 end if;
542 Next_Elmt (Elmt);
543 end loop;
545 -- Check if all primitives from the parent have been
546 -- overridden (to avoid copying the whole secondary
547 -- table from the parent).
549 -- IfaceG!(Typ_Sec_Tag).all := IfaceG!(Parent_Sec_Tag).all;
551 for J in Prims_Table'Range loop
552 if not Prims_Table (J) then
553 Insert_After (Last_Nod,
554 Make_Assignment_Statement (Loc,
555 Name =>
556 Make_Explicit_Dereference (Loc,
557 Unchecked_Convert_To
558 (Node (Last_Elmt (Access_Disp_Table (Iface))),
559 New_Reference_To (Typ_Tag, Loc))),
560 Expression =>
561 Make_Explicit_Dereference (Loc,
562 Unchecked_Convert_To
563 (Node (Last_Elmt (Access_Disp_Table (Iface))),
564 New_Reference_To (Parent_Tag, Loc)))));
565 exit;
566 end if;
567 end loop;
568 end;
569 end if;
571 Next_Elmt (Typ_Iface_Tag_Elmt);
572 Next_Elmt (Parent_Iface_Tag_Elmt);
573 end loop;
574 end;
576 return Result;
577 end Build_Inherit_CPP_Prims;
579 -------------------------
580 -- Build_Inherit_Prims --
581 -------------------------
583 function Build_Inherit_Prims
584 (Loc : Source_Ptr;
585 Typ : Entity_Id;
586 Old_Tag_Node : Node_Id;
587 New_Tag_Node : Node_Id;
588 Num_Prims : Nat) return Node_Id
590 begin
591 if RTE_Available (RE_DT) then
592 return
593 Make_Assignment_Statement (Loc,
594 Name =>
595 Make_Slice (Loc,
596 Prefix =>
597 Make_Selected_Component (Loc,
598 Prefix =>
599 Build_DT (Loc, New_Tag_Node),
600 Selector_Name =>
601 New_Reference_To
602 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
603 Discrete_Range =>
604 Make_Range (Loc,
605 Low_Bound => Make_Integer_Literal (Loc, 1),
606 High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
608 Expression =>
609 Make_Slice (Loc,
610 Prefix =>
611 Make_Selected_Component (Loc,
612 Prefix =>
613 Build_DT (Loc, Old_Tag_Node),
614 Selector_Name =>
615 New_Reference_To
616 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
617 Discrete_Range =>
618 Make_Range (Loc,
619 Low_Bound => Make_Integer_Literal (Loc, 1),
620 High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
621 else
622 return
623 Make_Assignment_Statement (Loc,
624 Name =>
625 Make_Slice (Loc,
626 Prefix =>
627 Unchecked_Convert_To
628 (Node (Last_Elmt (Access_Disp_Table (Typ))),
629 New_Tag_Node),
630 Discrete_Range =>
631 Make_Range (Loc,
632 Low_Bound => Make_Integer_Literal (Loc, 1),
633 High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
635 Expression =>
636 Make_Slice (Loc,
637 Prefix =>
638 Unchecked_Convert_To
639 (Node (Last_Elmt (Access_Disp_Table (Typ))),
640 Old_Tag_Node),
641 Discrete_Range =>
642 Make_Range (Loc,
643 Low_Bound => Make_Integer_Literal (Loc, 1),
644 High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
645 end if;
646 end Build_Inherit_Prims;
648 -------------------------------
649 -- Build_Get_Prim_Op_Address --
650 -------------------------------
652 procedure Build_Get_Prim_Op_Address
653 (Loc : Source_Ptr;
654 Typ : Entity_Id;
655 Position : Uint;
656 Tag_Node : in out Node_Id;
657 New_Node : out Node_Id)
659 New_Prefix : Node_Id;
661 begin
662 pragma Assert
663 (Position <= DT_Entry_Count (First_Tag_Component (Typ)));
665 -- At the end of the Access_Disp_Table list we have the type
666 -- declaration required to convert the tag into a pointer to
667 -- the prims_ptr table (see Freeze_Record_Type).
669 New_Prefix :=
670 Unchecked_Convert_To
671 (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node);
673 -- Unchecked_Convert_To relocates the controlling tag node and therefore
674 -- we must update it.
676 Tag_Node := Expression (New_Prefix);
678 New_Node :=
679 Make_Indexed_Component (Loc,
680 Prefix => New_Prefix,
681 Expressions => New_List (Make_Integer_Literal (Loc, Position)));
682 end Build_Get_Prim_Op_Address;
684 -----------------------------
685 -- Build_Get_Transportable --
686 -----------------------------
688 function Build_Get_Transportable
689 (Loc : Source_Ptr;
690 Tag_Node : Node_Id) return Node_Id
692 begin
693 return
694 Make_Selected_Component (Loc,
695 Prefix =>
696 Build_TSD (Loc,
697 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
698 Selector_Name =>
699 New_Reference_To
700 (RTE_Record_Component (RE_Transportable), Loc));
701 end Build_Get_Transportable;
703 ------------------------------------
704 -- Build_Inherit_Predefined_Prims --
705 ------------------------------------
707 function Build_Inherit_Predefined_Prims
708 (Loc : Source_Ptr;
709 Old_Tag_Node : Node_Id;
710 New_Tag_Node : Node_Id) return Node_Id
712 begin
713 return
714 Make_Assignment_Statement (Loc,
715 Name =>
716 Make_Slice (Loc,
717 Prefix =>
718 Make_Explicit_Dereference (Loc,
719 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
720 Make_Explicit_Dereference (Loc,
721 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
722 New_Tag_Node)))),
723 Discrete_Range => Make_Range (Loc,
724 Make_Integer_Literal (Loc, Uint_1),
725 New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))),
727 Expression =>
728 Make_Slice (Loc,
729 Prefix =>
730 Make_Explicit_Dereference (Loc,
731 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
732 Make_Explicit_Dereference (Loc,
733 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
734 Old_Tag_Node)))),
735 Discrete_Range =>
736 Make_Range (Loc,
737 Make_Integer_Literal (Loc, 1),
738 New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))));
739 end Build_Inherit_Predefined_Prims;
741 -------------------------
742 -- Build_Offset_To_Top --
743 -------------------------
745 function Build_Offset_To_Top
746 (Loc : Source_Ptr;
747 This_Node : Node_Id) return Node_Id
749 Tag_Node : Node_Id;
751 begin
752 Tag_Node :=
753 Make_Explicit_Dereference (Loc,
754 Unchecked_Convert_To (RTE (RE_Tag_Ptr), This_Node));
756 return
757 Make_Explicit_Dereference (Loc,
758 Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
759 Make_Function_Call (Loc,
760 Name =>
761 Make_Expanded_Name (Loc,
762 Chars => Name_Op_Subtract,
763 Prefix =>
764 New_Reference_To
765 (RTU_Entity (System_Storage_Elements), Loc),
766 Selector_Name => Make_Identifier (Loc, Name_Op_Subtract)),
767 Parameter_Associations => New_List (
768 Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
769 New_Reference_To
770 (RTE (RE_DT_Offset_To_Top_Offset), Loc)))));
771 end Build_Offset_To_Top;
773 ------------------------------------------
774 -- Build_Set_Predefined_Prim_Op_Address --
775 ------------------------------------------
777 function Build_Set_Predefined_Prim_Op_Address
778 (Loc : Source_Ptr;
779 Tag_Node : Node_Id;
780 Position : Uint;
781 Address_Node : Node_Id) return Node_Id
783 begin
784 return
785 Make_Assignment_Statement (Loc,
786 Name =>
787 Make_Indexed_Component (Loc,
788 Prefix =>
789 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
790 Make_Explicit_Dereference (Loc,
791 Unchecked_Convert_To (RTE (RE_Addr_Ptr), Tag_Node))),
792 Expressions =>
793 New_List (Make_Integer_Literal (Loc, Position))),
795 Expression => Address_Node);
796 end Build_Set_Predefined_Prim_Op_Address;
798 -------------------------------
799 -- Build_Set_Prim_Op_Address --
800 -------------------------------
802 function Build_Set_Prim_Op_Address
803 (Loc : Source_Ptr;
804 Typ : Entity_Id;
805 Tag_Node : Node_Id;
806 Position : Uint;
807 Address_Node : Node_Id) return Node_Id
809 Ctrl_Tag : Node_Id := Tag_Node;
810 New_Node : Node_Id;
812 begin
813 Build_Get_Prim_Op_Address (Loc, Typ, Position, Ctrl_Tag, New_Node);
815 return
816 Make_Assignment_Statement (Loc,
817 Name => New_Node,
818 Expression => Address_Node);
819 end Build_Set_Prim_Op_Address;
821 -----------------------------
822 -- Build_Set_Size_Function --
823 -----------------------------
825 function Build_Set_Size_Function
826 (Loc : Source_Ptr;
827 Tag_Node : Node_Id;
828 Size_Func : Entity_Id) return Node_Id is
829 begin
830 pragma Assert (Chars (Size_Func) = Name_uSize
831 and then RTE_Record_Component_Available (RE_Size_Func));
832 return
833 Make_Assignment_Statement (Loc,
834 Name =>
835 Make_Selected_Component (Loc,
836 Prefix =>
837 Build_TSD (Loc,
838 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
839 Selector_Name =>
840 New_Reference_To
841 (RTE_Record_Component (RE_Size_Func), Loc)),
842 Expression =>
843 Unchecked_Convert_To (RTE (RE_Size_Ptr),
844 Make_Attribute_Reference (Loc,
845 Prefix => New_Reference_To (Size_Func, Loc),
846 Attribute_Name => Name_Unrestricted_Access)));
847 end Build_Set_Size_Function;
849 ------------------------------------
850 -- Build_Set_Static_Offset_To_Top --
851 ------------------------------------
853 function Build_Set_Static_Offset_To_Top
854 (Loc : Source_Ptr;
855 Iface_Tag : Node_Id;
856 Offset_Value : Node_Id) return Node_Id is
857 begin
858 return
859 Make_Assignment_Statement (Loc,
860 Make_Explicit_Dereference (Loc,
861 Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
862 Make_Function_Call (Loc,
863 Name =>
864 Make_Expanded_Name (Loc,
865 Chars => Name_Op_Subtract,
866 Prefix =>
867 New_Reference_To
868 (RTU_Entity (System_Storage_Elements), Loc),
869 Selector_Name => Make_Identifier (Loc, Name_Op_Subtract)),
870 Parameter_Associations => New_List (
871 Unchecked_Convert_To (RTE (RE_Address), Iface_Tag),
872 New_Reference_To
873 (RTE (RE_DT_Offset_To_Top_Offset), Loc))))),
874 Offset_Value);
875 end Build_Set_Static_Offset_To_Top;
877 ---------------
878 -- Build_TSD --
879 ---------------
881 function Build_TSD
882 (Loc : Source_Ptr;
883 Tag_Node_Addr : Node_Id) return Node_Id is
884 begin
885 return
886 Unchecked_Convert_To (RTE (RE_Type_Specific_Data_Ptr),
887 Make_Explicit_Dereference (Loc,
888 Prefix => Unchecked_Convert_To (RTE (RE_Addr_Ptr),
889 Make_Function_Call (Loc,
890 Name =>
891 Make_Expanded_Name (Loc,
892 Chars => Name_Op_Subtract,
893 Prefix =>
894 New_Reference_To
895 (RTU_Entity (System_Storage_Elements), Loc),
896 Selector_Name => Make_Identifier (Loc, Name_Op_Subtract)),
898 Parameter_Associations => New_List (
899 Tag_Node_Addr,
900 New_Reference_To
901 (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))));
902 end Build_TSD;
904 end Exp_Atag;