2010-07-27 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc/alias-decl.git] / gcc / ada / exp_atag.adb
blob23a9202c3728da5d5d242af8af65e9b4eb40bc07
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-2009, 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_Util; use Exp_Util;
30 with Namet; use Namet;
31 with Nlists; use Nlists;
32 with Nmake; use Nmake;
33 with Rtsfind; use Rtsfind;
34 with Sinfo; use Sinfo;
35 with Sem_Aux; use Sem_Aux;
36 with Sem_Util; use Sem_Util;
37 with Stand; use Stand;
38 with Snames; use Snames;
39 with Tbuild; use Tbuild;
41 package body Exp_Atag is
43 -----------------------
44 -- Local Subprograms --
45 -----------------------
47 function Build_DT
48 (Loc : Source_Ptr;
49 Tag_Node : Node_Id) return Node_Id;
50 -- Build code that displaces the Tag to reference the base of the wrapper
51 -- record
53 -- Generates:
54 -- To_Dispatch_Table_Ptr
55 -- (To_Address (Tag_Node) - Tag_Node.Prims_Ptr'Position);
57 function Build_TSD
58 (Loc : Source_Ptr;
59 Tag_Node_Addr : Node_Id) return Node_Id;
60 -- Build code that retrieves the address of the record containing the Type
61 -- Specific Data generated by GNAT.
63 -- Generate: To_Type_Specific_Data_Ptr
64 -- (To_Addr_Ptr (Tag_Node_Addr - Typeinfo_Offset).all);
66 ------------------------------------------------
67 -- Build_Common_Dispatching_Select_Statements --
68 ------------------------------------------------
70 procedure Build_Common_Dispatching_Select_Statements
71 (Loc : Source_Ptr;
72 DT_Ptr : Entity_Id;
73 Stmts : List_Id)
75 begin
76 -- Generate:
77 -- C := get_prim_op_kind (tag! (<type>VP), S);
79 -- where C is the out parameter capturing the call kind and S is the
80 -- dispatch table slot number.
82 Append_To (Stmts,
83 Make_Assignment_Statement (Loc,
84 Name =>
85 Make_Identifier (Loc, Name_uC),
86 Expression =>
87 Make_Function_Call (Loc,
88 Name => New_Occurrence_Of (RTE (RE_Get_Prim_Op_Kind), Loc),
89 Parameter_Associations => New_List (
90 Unchecked_Convert_To (RTE (RE_Tag),
91 New_Reference_To (DT_Ptr, Loc)),
92 Make_Identifier (Loc, Name_uS)))));
94 -- Generate:
96 -- if C = POK_Procedure
97 -- or else C = POK_Protected_Procedure
98 -- or else C = POK_Task_Procedure;
99 -- then
100 -- F := True;
101 -- return;
103 -- where F is the out parameter capturing the status of a potential
104 -- entry call.
106 Append_To (Stmts,
107 Make_If_Statement (Loc,
109 Condition =>
110 Make_Or_Else (Loc,
111 Left_Opnd =>
112 Make_Op_Eq (Loc,
113 Left_Opnd =>
114 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 =>
122 Make_Identifier (Loc, Name_uC),
123 Right_Opnd =>
124 New_Reference_To (RTE (
125 RE_POK_Protected_Procedure), Loc)),
126 Right_Opnd =>
127 Make_Op_Eq (Loc,
128 Left_Opnd =>
129 Make_Identifier (Loc, Name_uC),
130 Right_Opnd =>
131 New_Reference_To (RTE (
132 RE_POK_Task_Procedure), Loc)))),
134 Then_Statements =>
135 New_List (
136 Make_Assignment_Statement (Loc,
137 Name => Make_Identifier (Loc, Name_uF),
138 Expression => New_Reference_To (Standard_True, Loc)),
139 Make_Simple_Return_Statement (Loc))));
140 end Build_Common_Dispatching_Select_Statements;
142 -------------------------
143 -- Build_CW_Membership --
144 -------------------------
146 procedure Build_CW_Membership
147 (Loc : Source_Ptr;
148 Obj_Tag_Node : in out Node_Id;
149 Typ_Tag_Node : Node_Id;
150 Related_Nod : Node_Id;
151 New_Node : out Node_Id)
153 Tag_Addr : constant Entity_Id := Make_Temporary (Loc, 'D', Obj_Tag_Node);
154 Obj_TSD : constant Entity_Id := Make_Temporary (Loc, 'D');
155 Typ_TSD : constant Entity_Id := Make_Temporary (Loc, 'D');
156 Index : constant Entity_Id := Make_Temporary (Loc, 'D');
158 begin
159 -- Generate:
161 -- Tag_Addr : constant Tag := Address!(Obj_Tag);
162 -- Obj_TSD : constant Type_Specific_Data_Ptr
163 -- := Build_TSD (Tag_Addr);
164 -- Typ_TSD : constant Type_Specific_Data_Ptr
165 -- := Build_TSD (Address!(Typ_Tag));
166 -- Index : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth
167 -- Index > 0 and then Obj_TSD.Tags_Table (Index) = Typ'Tag
169 Insert_Action (Related_Nod,
170 Make_Object_Declaration (Loc,
171 Defining_Identifier => Tag_Addr,
172 Constant_Present => True,
173 Object_Definition => New_Reference_To (RTE (RE_Address), Loc),
174 Expression => Unchecked_Convert_To
175 (RTE (RE_Address), Obj_Tag_Node)));
177 -- Unchecked_Convert_To relocates Obj_Tag_Node and therefore we must
178 -- update it.
180 Obj_Tag_Node := Expression (Expression (Parent (Tag_Addr)));
182 Insert_Action (Related_Nod,
183 Make_Object_Declaration (Loc,
184 Defining_Identifier => Obj_TSD,
185 Constant_Present => True,
186 Object_Definition => New_Reference_To
187 (RTE (RE_Type_Specific_Data_Ptr), Loc),
188 Expression => Build_TSD (Loc, New_Reference_To (Tag_Addr, Loc))));
190 Insert_Action (Related_Nod,
191 Make_Object_Declaration (Loc,
192 Defining_Identifier => Typ_TSD,
193 Constant_Present => True,
194 Object_Definition => New_Reference_To
195 (RTE (RE_Type_Specific_Data_Ptr), Loc),
196 Expression => Build_TSD (Loc,
197 Unchecked_Convert_To (RTE (RE_Address),
198 Typ_Tag_Node))));
200 Insert_Action (Related_Nod,
201 Make_Object_Declaration (Loc,
202 Defining_Identifier => Index,
203 Constant_Present => True,
204 Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
205 Expression =>
206 Make_Op_Subtract (Loc,
207 Left_Opnd =>
208 Make_Selected_Component (Loc,
209 Prefix => New_Reference_To (Obj_TSD, Loc),
210 Selector_Name =>
211 New_Reference_To
212 (RTE_Record_Component (RE_Idepth), Loc)),
214 Right_Opnd =>
215 Make_Selected_Component (Loc,
216 Prefix => New_Reference_To (Typ_TSD, Loc),
217 Selector_Name =>
218 New_Reference_To
219 (RTE_Record_Component (RE_Idepth), Loc)))));
221 New_Node :=
222 Make_And_Then (Loc,
223 Left_Opnd =>
224 Make_Op_Ge (Loc,
225 Left_Opnd => New_Occurrence_Of (Index, Loc),
226 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
228 Right_Opnd =>
229 Make_Op_Eq (Loc,
230 Left_Opnd =>
231 Make_Indexed_Component (Loc,
232 Prefix =>
233 Make_Selected_Component (Loc,
234 Prefix => New_Reference_To (Obj_TSD, Loc),
235 Selector_Name =>
236 New_Reference_To
237 (RTE_Record_Component (RE_Tags_Table), Loc)),
238 Expressions =>
239 New_List (New_Occurrence_Of (Index, Loc))),
241 Right_Opnd => Typ_Tag_Node));
242 end Build_CW_Membership;
244 --------------
245 -- Build_DT --
246 --------------
248 function Build_DT
249 (Loc : Source_Ptr;
250 Tag_Node : Node_Id) return Node_Id
252 begin
253 return
254 Make_Function_Call (Loc,
255 Name => New_Reference_To (RTE (RE_DT), Loc),
256 Parameter_Associations => New_List (
257 Unchecked_Convert_To (RTE (RE_Tag), Tag_Node)));
258 end Build_DT;
260 ----------------------------
261 -- Build_Get_Access_Level --
262 ----------------------------
264 function Build_Get_Access_Level
265 (Loc : Source_Ptr;
266 Tag_Node : Node_Id) return Node_Id
268 begin
269 return
270 Make_Selected_Component (Loc,
271 Prefix =>
272 Build_TSD (Loc,
273 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
274 Selector_Name =>
275 New_Reference_To
276 (RTE_Record_Component (RE_Access_Level), Loc));
277 end Build_Get_Access_Level;
279 ------------------------------------------
280 -- Build_Get_Predefined_Prim_Op_Address --
281 ------------------------------------------
283 procedure Build_Get_Predefined_Prim_Op_Address
284 (Loc : Source_Ptr;
285 Position : Uint;
286 Tag_Node : in out Node_Id;
287 New_Node : out Node_Id)
289 Ctrl_Tag : Node_Id;
291 begin
292 Ctrl_Tag := Unchecked_Convert_To (RTE (RE_Address), Tag_Node);
294 -- Unchecked_Convert_To relocates the controlling tag node and therefore
295 -- we must update it.
297 Tag_Node := Expression (Ctrl_Tag);
299 -- Build code that retrieves the address of the dispatch table
300 -- containing the predefined Ada primitives:
302 -- Generate:
303 -- To_Predef_Prims_Table_Ptr
304 -- (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all);
306 New_Node :=
307 Make_Indexed_Component (Loc,
308 Prefix =>
309 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
310 Make_Explicit_Dereference (Loc,
311 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
312 Make_Function_Call (Loc,
313 Name =>
314 Make_Expanded_Name (Loc,
315 Chars => Name_Op_Subtract,
316 Prefix =>
317 New_Reference_To
318 (RTU_Entity (System_Storage_Elements), Loc),
319 Selector_Name =>
320 Make_Identifier (Loc,
321 Chars => Name_Op_Subtract)),
322 Parameter_Associations => New_List (
323 Ctrl_Tag,
324 New_Reference_To (RTE (RE_DT_Predef_Prims_Offset),
325 Loc)))))),
326 Expressions =>
327 New_List (Make_Integer_Literal (Loc, Position)));
328 end Build_Get_Predefined_Prim_Op_Address;
330 -------------------------
331 -- Build_Inherit_Prims --
332 -------------------------
334 function Build_Inherit_Prims
335 (Loc : Source_Ptr;
336 Typ : Entity_Id;
337 Old_Tag_Node : Node_Id;
338 New_Tag_Node : Node_Id;
339 Num_Prims : Nat) return Node_Id
341 begin
342 if RTE_Available (RE_DT) then
343 return
344 Make_Assignment_Statement (Loc,
345 Name =>
346 Make_Slice (Loc,
347 Prefix =>
348 Make_Selected_Component (Loc,
349 Prefix =>
350 Build_DT (Loc, New_Tag_Node),
351 Selector_Name =>
352 New_Reference_To
353 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
354 Discrete_Range =>
355 Make_Range (Loc,
356 Low_Bound => Make_Integer_Literal (Loc, 1),
357 High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
359 Expression =>
360 Make_Slice (Loc,
361 Prefix =>
362 Make_Selected_Component (Loc,
363 Prefix =>
364 Build_DT (Loc, Old_Tag_Node),
365 Selector_Name =>
366 New_Reference_To
367 (RTE_Record_Component (RE_Prims_Ptr), Loc)),
368 Discrete_Range =>
369 Make_Range (Loc,
370 Low_Bound => Make_Integer_Literal (Loc, 1),
371 High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
372 else
373 return
374 Make_Assignment_Statement (Loc,
375 Name =>
376 Make_Slice (Loc,
377 Prefix =>
378 Unchecked_Convert_To
379 (Node (Last_Elmt (Access_Disp_Table (Typ))),
380 New_Tag_Node),
381 Discrete_Range =>
382 Make_Range (Loc,
383 Low_Bound => Make_Integer_Literal (Loc, 1),
384 High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
386 Expression =>
387 Make_Slice (Loc,
388 Prefix =>
389 Unchecked_Convert_To
390 (Node (Last_Elmt (Access_Disp_Table (Typ))),
391 Old_Tag_Node),
392 Discrete_Range =>
393 Make_Range (Loc,
394 Low_Bound => Make_Integer_Literal (Loc, 1),
395 High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
396 end if;
397 end Build_Inherit_Prims;
399 -------------------------------
400 -- Build_Get_Prim_Op_Address --
401 -------------------------------
403 procedure Build_Get_Prim_Op_Address
404 (Loc : Source_Ptr;
405 Typ : Entity_Id;
406 Position : Uint;
407 Tag_Node : in out Node_Id;
408 New_Node : out Node_Id)
410 New_Prefix : Node_Id;
412 begin
413 pragma Assert
414 (Position <= DT_Entry_Count (First_Tag_Component (Typ)));
416 -- At the end of the Access_Disp_Table list we have the type
417 -- declaration required to convert the tag into a pointer to
418 -- the prims_ptr table (see Freeze_Record_Type).
420 New_Prefix :=
421 Unchecked_Convert_To
422 (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node);
424 -- Unchecked_Convert_To relocates the controlling tag node and therefore
425 -- we must update it.
427 Tag_Node := Expression (New_Prefix);
429 New_Node :=
430 Make_Indexed_Component (Loc,
431 Prefix => New_Prefix,
432 Expressions => New_List (Make_Integer_Literal (Loc, Position)));
433 end Build_Get_Prim_Op_Address;
435 -----------------------------
436 -- Build_Get_Transportable --
437 -----------------------------
439 function Build_Get_Transportable
440 (Loc : Source_Ptr;
441 Tag_Node : Node_Id) return Node_Id
443 begin
444 return
445 Make_Selected_Component (Loc,
446 Prefix =>
447 Build_TSD (Loc,
448 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
449 Selector_Name =>
450 New_Reference_To
451 (RTE_Record_Component (RE_Transportable), Loc));
452 end Build_Get_Transportable;
454 ------------------------------------
455 -- Build_Inherit_Predefined_Prims --
456 ------------------------------------
458 function Build_Inherit_Predefined_Prims
459 (Loc : Source_Ptr;
460 Old_Tag_Node : Node_Id;
461 New_Tag_Node : Node_Id) return Node_Id
463 begin
464 return
465 Make_Assignment_Statement (Loc,
466 Name =>
467 Make_Slice (Loc,
468 Prefix =>
469 Make_Explicit_Dereference (Loc,
470 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
471 Make_Explicit_Dereference (Loc,
472 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
473 New_Tag_Node)))),
474 Discrete_Range => Make_Range (Loc,
475 Make_Integer_Literal (Loc, Uint_1),
476 New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))),
478 Expression =>
479 Make_Slice (Loc,
480 Prefix =>
481 Make_Explicit_Dereference (Loc,
482 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
483 Make_Explicit_Dereference (Loc,
484 Unchecked_Convert_To (RTE (RE_Addr_Ptr),
485 Old_Tag_Node)))),
486 Discrete_Range =>
487 Make_Range (Loc,
488 Make_Integer_Literal (Loc, 1),
489 New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))));
490 end Build_Inherit_Predefined_Prims;
492 -------------------------
493 -- Build_Offset_To_Top --
494 -------------------------
496 function Build_Offset_To_Top
497 (Loc : Source_Ptr;
498 This_Node : Node_Id) return Node_Id
500 Tag_Node : Node_Id;
502 begin
503 Tag_Node :=
504 Make_Explicit_Dereference (Loc,
505 Unchecked_Convert_To (RTE (RE_Tag_Ptr), This_Node));
507 return
508 Make_Explicit_Dereference (Loc,
509 Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
510 Make_Function_Call (Loc,
511 Name =>
512 Make_Expanded_Name (Loc,
513 Chars => Name_Op_Subtract,
514 Prefix => New_Reference_To
515 (RTU_Entity (System_Storage_Elements), Loc),
516 Selector_Name => Make_Identifier (Loc,
517 Chars => Name_Op_Subtract)),
518 Parameter_Associations => New_List (
519 Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
520 New_Reference_To (RTE (RE_DT_Offset_To_Top_Offset),
521 Loc)))));
522 end Build_Offset_To_Top;
524 ------------------------------------------
525 -- Build_Set_Predefined_Prim_Op_Address --
526 ------------------------------------------
528 function Build_Set_Predefined_Prim_Op_Address
529 (Loc : Source_Ptr;
530 Tag_Node : Node_Id;
531 Position : Uint;
532 Address_Node : Node_Id) return Node_Id
534 begin
535 return
536 Make_Assignment_Statement (Loc,
537 Name =>
538 Make_Indexed_Component (Loc,
539 Prefix =>
540 Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
541 Make_Explicit_Dereference (Loc,
542 Unchecked_Convert_To (RTE (RE_Addr_Ptr), Tag_Node))),
543 Expressions =>
544 New_List (Make_Integer_Literal (Loc, Position))),
546 Expression => Address_Node);
547 end Build_Set_Predefined_Prim_Op_Address;
549 -------------------------------
550 -- Build_Set_Prim_Op_Address --
551 -------------------------------
553 function Build_Set_Prim_Op_Address
554 (Loc : Source_Ptr;
555 Typ : Entity_Id;
556 Tag_Node : Node_Id;
557 Position : Uint;
558 Address_Node : Node_Id) return Node_Id
560 Ctrl_Tag : Node_Id := Tag_Node;
561 New_Node : Node_Id;
563 begin
564 Build_Get_Prim_Op_Address (Loc, Typ, Position, Ctrl_Tag, New_Node);
566 return
567 Make_Assignment_Statement (Loc,
568 Name => New_Node,
569 Expression => Address_Node);
570 end Build_Set_Prim_Op_Address;
572 -----------------------------
573 -- Build_Set_Size_Function --
574 -----------------------------
576 function Build_Set_Size_Function
577 (Loc : Source_Ptr;
578 Tag_Node : Node_Id;
579 Size_Func : Entity_Id) return Node_Id is
580 begin
581 pragma Assert (Chars (Size_Func) = Name_uSize
582 and then RTE_Record_Component_Available (RE_Size_Func));
583 return
584 Make_Assignment_Statement (Loc,
585 Name =>
586 Make_Selected_Component (Loc,
587 Prefix =>
588 Build_TSD (Loc,
589 Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
590 Selector_Name =>
591 New_Reference_To
592 (RTE_Record_Component (RE_Size_Func), Loc)),
593 Expression =>
594 Unchecked_Convert_To (RTE (RE_Size_Ptr),
595 Make_Attribute_Reference (Loc,
596 Prefix => New_Reference_To (Size_Func, Loc),
597 Attribute_Name => Name_Unrestricted_Access)));
598 end Build_Set_Size_Function;
600 ------------------------------------
601 -- Build_Set_Static_Offset_To_Top --
602 ------------------------------------
604 function Build_Set_Static_Offset_To_Top
605 (Loc : Source_Ptr;
606 Iface_Tag : Node_Id;
607 Offset_Value : Node_Id) return Node_Id is
608 begin
609 return
610 Make_Assignment_Statement (Loc,
611 Make_Explicit_Dereference (Loc,
612 Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
613 Make_Function_Call (Loc,
614 Name =>
615 Make_Expanded_Name (Loc,
616 Chars => Name_Op_Subtract,
617 Prefix => New_Reference_To
618 (RTU_Entity (System_Storage_Elements), Loc),
619 Selector_Name => Make_Identifier (Loc,
620 Chars => Name_Op_Subtract)),
621 Parameter_Associations => New_List (
622 Unchecked_Convert_To (RTE (RE_Address), Iface_Tag),
623 New_Reference_To (RTE (RE_DT_Offset_To_Top_Offset),
624 Loc))))),
625 Offset_Value);
626 end Build_Set_Static_Offset_To_Top;
628 ---------------
629 -- Build_TSD --
630 ---------------
632 function Build_TSD
633 (Loc : Source_Ptr;
634 Tag_Node_Addr : Node_Id) return Node_Id is
635 begin
636 return
637 Unchecked_Convert_To (RTE (RE_Type_Specific_Data_Ptr),
638 Make_Explicit_Dereference (Loc,
639 Prefix => Unchecked_Convert_To (RTE (RE_Addr_Ptr),
640 Make_Function_Call (Loc,
641 Name =>
642 Make_Expanded_Name (Loc,
643 Chars => Name_Op_Subtract,
644 Prefix =>
645 New_Reference_To
646 (RTU_Entity (System_Storage_Elements), Loc),
647 Selector_Name =>
648 Make_Identifier (Loc,
649 Chars => Name_Op_Subtract)),
651 Parameter_Associations => New_List (
652 Tag_Node_Addr,
653 New_Reference_To
654 (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))));
655 end Build_TSD;
657 end Exp_Atag;