OSDN Git Service

PR 33870
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_atag.adb
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-2007, 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 ------------------------------------------------------------------------------
25
26 with Einfo;    use Einfo;
27 with Elists;   use Elists;
28 with Exp_Util; use Exp_Util;
29 with Nlists;   use Nlists;
30 with Nmake;    use Nmake;
31 with Rtsfind;  use Rtsfind;
32 with Sem_Util; use Sem_Util;
33 with Stand;    use Stand;
34 with Snames;   use Snames;
35 with Tbuild;   use Tbuild;
36
37 package body Exp_Atag is
38
39    -----------------------
40    -- Local Subprograms --
41    -----------------------
42
43    function Build_DT
44      (Loc      : Source_Ptr;
45       Tag_Node : Node_Id) return Node_Id;
46    --  Build code that displaces the Tag to reference the base of the wrapper
47    --  record
48    --
49    --  Generates:
50    --    To_Dispatch_Table_Ptr
51    --      (To_Address (Tag_Node) - Tag_Node.Prims_Ptr'Position);
52
53    function Build_TSD (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id;
54    --  Build code that retrieves the address of the record containing the Type
55    --  Specific Data generated by GNAT.
56    --
57    --  Generate: To_Type_Specific_Data_Ptr
58    --              (To_Addr_Ptr (To_Address (Tag) - Typeinfo_Offset).all);
59
60    function Build_Predef_Prims
61      (Loc      : Source_Ptr;
62       Tag_Node : Node_Id) return Node_Id;
63    --  Build code that retrieves the address of the dispatch table containing
64    --  the predefined Ada primitives:
65    --
66    --  Generate: To_Predef_Prims_Table_Ptr
67    --              (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all);
68
69    ------------------------------------------------
70    -- Build_Common_Dispatching_Select_Statements --
71    ------------------------------------------------
72
73    procedure Build_Common_Dispatching_Select_Statements
74      (Loc    : Source_Ptr;
75       DT_Ptr : Entity_Id;
76       Stmts  : List_Id)
77    is
78    begin
79       --  Generate:
80       --    C := get_prim_op_kind (tag! (<type>VP), S);
81
82       --  where C is the out parameter capturing the call kind and S is the
83       --  dispatch table slot number.
84
85       Append_To (Stmts,
86         Make_Assignment_Statement (Loc,
87           Name =>
88             Make_Identifier (Loc, Name_uC),
89           Expression =>
90             Make_Function_Call (Loc,
91               Name => New_Occurrence_Of (RTE (RE_Get_Prim_Op_Kind), Loc),
92               Parameter_Associations => New_List (
93                 Unchecked_Convert_To (RTE (RE_Tag),
94                   New_Reference_To (DT_Ptr, Loc)),
95                 Make_Identifier (Loc, Name_uS)))));
96
97       --  Generate:
98
99       --    if C = POK_Procedure
100       --      or else C = POK_Protected_Procedure
101       --      or else C = POK_Task_Procedure;
102       --    then
103       --       F := True;
104       --       return;
105
106       --  where F is the out parameter capturing the status of a potential
107       --  entry call.
108
109       Append_To (Stmts,
110         Make_If_Statement (Loc,
111
112           Condition =>
113             Make_Or_Else (Loc,
114               Left_Opnd =>
115                 Make_Op_Eq (Loc,
116                   Left_Opnd =>
117                     Make_Identifier (Loc, Name_uC),
118                   Right_Opnd =>
119                     New_Reference_To (RTE (RE_POK_Procedure), Loc)),
120               Right_Opnd =>
121                 Make_Or_Else (Loc,
122                   Left_Opnd =>
123                     Make_Op_Eq (Loc,
124                       Left_Opnd =>
125                         Make_Identifier (Loc, Name_uC),
126                       Right_Opnd =>
127                         New_Reference_To (RTE (
128                           RE_POK_Protected_Procedure), Loc)),
129                   Right_Opnd =>
130                     Make_Op_Eq (Loc,
131                       Left_Opnd =>
132                         Make_Identifier (Loc, Name_uC),
133                       Right_Opnd =>
134                         New_Reference_To (RTE (
135                           RE_POK_Task_Procedure), Loc)))),
136
137           Then_Statements =>
138             New_List (
139               Make_Assignment_Statement (Loc,
140                 Name       => Make_Identifier (Loc, Name_uF),
141                 Expression => New_Reference_To (Standard_True, Loc)),
142               Make_Simple_Return_Statement (Loc))));
143    end Build_Common_Dispatching_Select_Statements;
144
145    -------------------------
146    -- Build_CW_Membership --
147    -------------------------
148
149    function Build_CW_Membership
150      (Loc          : Source_Ptr;
151       Obj_Tag_Node : Node_Id;
152       Typ_Tag_Node : Node_Id) return Node_Id
153    is
154       function Build_Pos return Node_Id;
155       --  Generate TSD (Obj_Tag).Idepth - TSD (Typ_Tag).Idepth;
156
157       function Build_Pos return Node_Id is
158       begin
159          return
160             Make_Op_Subtract (Loc,
161               Left_Opnd =>
162                 Make_Selected_Component (Loc,
163                   Prefix => Build_TSD (Loc, Duplicate_Subexpr (Obj_Tag_Node)),
164                   Selector_Name =>
165                     New_Reference_To (RTE_Record_Component (RE_Idepth), Loc)),
166
167               Right_Opnd =>
168                 Make_Selected_Component (Loc,
169                   Prefix => Build_TSD (Loc, Duplicate_Subexpr (Typ_Tag_Node)),
170                   Selector_Name =>
171                     New_Reference_To (RTE_Record_Component (RE_Idepth), Loc)));
172       end Build_Pos;
173
174    --  Start of processing for Build_CW_Membership
175
176    begin
177       return
178         Make_And_Then (Loc,
179           Left_Opnd =>
180             Make_Op_Ge (Loc,
181               Left_Opnd  => Build_Pos,
182               Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
183
184           Right_Opnd =>
185             Make_Op_Eq (Loc,
186               Left_Opnd =>
187                 Make_Indexed_Component (Loc,
188                   Prefix =>
189                     Make_Selected_Component (Loc,
190                       Prefix => Build_TSD (Loc, Obj_Tag_Node),
191                       Selector_Name =>
192                         New_Reference_To
193                           (RTE_Record_Component (RE_Tags_Table), Loc)),
194                   Expressions =>
195                     New_List (Build_Pos)),
196
197               Right_Opnd => Typ_Tag_Node));
198    end Build_CW_Membership;
199
200    --------------
201    -- Build_DT --
202    --------------
203
204    function Build_DT
205      (Loc      : Source_Ptr;
206       Tag_Node : Node_Id) return Node_Id is
207    begin
208       return
209         Make_Function_Call (Loc,
210           Name => New_Reference_To (RTE (RE_DT), Loc),
211           Parameter_Associations => New_List (
212             Unchecked_Convert_To (RTE (RE_Tag), Tag_Node)));
213    end Build_DT;
214
215    ----------------------------
216    -- Build_Get_Access_Level --
217    ----------------------------
218
219    function Build_Get_Access_Level
220      (Loc      : Source_Ptr;
221       Tag_Node : Node_Id) return Node_Id
222    is
223    begin
224       return
225         Make_Selected_Component (Loc,
226           Prefix => Build_TSD (Loc, Tag_Node),
227           Selector_Name =>
228             New_Reference_To
229               (RTE_Record_Component (RE_Access_Level), Loc));
230    end Build_Get_Access_Level;
231
232    ------------------------------------------
233    -- Build_Get_Predefined_Prim_Op_Address --
234    ------------------------------------------
235
236    function Build_Get_Predefined_Prim_Op_Address
237      (Loc      : Source_Ptr;
238       Tag_Node : Node_Id;
239       Position : Uint) return Node_Id
240    is
241    begin
242       return
243         Make_Indexed_Component (Loc,
244           Prefix =>
245             Build_Predef_Prims (Loc, Tag_Node),
246           Expressions =>
247             New_List (Make_Integer_Literal (Loc, Position)));
248    end Build_Get_Predefined_Prim_Op_Address;
249
250    -------------------------
251    -- Build_Inherit_Prims --
252    -------------------------
253
254    function Build_Inherit_Prims
255      (Loc          : Source_Ptr;
256       Typ          : Entity_Id;
257       Old_Tag_Node : Node_Id;
258       New_Tag_Node : Node_Id;
259       Num_Prims    : Nat) return Node_Id
260    is
261    begin
262       if RTE_Available (RE_DT) then
263          return
264            Make_Assignment_Statement (Loc,
265              Name =>
266                Make_Slice (Loc,
267                  Prefix =>
268                    Make_Selected_Component (Loc,
269                      Prefix =>
270                        Build_DT (Loc, New_Tag_Node),
271                      Selector_Name =>
272                        New_Reference_To
273                          (RTE_Record_Component (RE_Prims_Ptr), Loc)),
274                  Discrete_Range =>
275                    Make_Range (Loc,
276                    Low_Bound  => Make_Integer_Literal (Loc, 1),
277                    High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
278
279              Expression =>
280                Make_Slice (Loc,
281                  Prefix =>
282                    Make_Selected_Component (Loc,
283                      Prefix =>
284                        Build_DT (Loc, Old_Tag_Node),
285                      Selector_Name =>
286                        New_Reference_To
287                          (RTE_Record_Component (RE_Prims_Ptr), Loc)),
288                  Discrete_Range =>
289                    Make_Range (Loc,
290                      Low_Bound  => Make_Integer_Literal (Loc, 1),
291                      High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
292       else
293          return
294            Make_Assignment_Statement (Loc,
295              Name =>
296                Make_Slice (Loc,
297                  Prefix =>
298                    Unchecked_Convert_To
299                      (Node (Last_Elmt (Access_Disp_Table (Typ))),
300                       New_Tag_Node),
301                  Discrete_Range =>
302                    Make_Range (Loc,
303                    Low_Bound  => Make_Integer_Literal (Loc, 1),
304                    High_Bound => Make_Integer_Literal (Loc, Num_Prims))),
305
306              Expression =>
307                Make_Slice (Loc,
308                  Prefix =>
309                    Unchecked_Convert_To
310                      (Node (Last_Elmt (Access_Disp_Table (Typ))),
311                       Old_Tag_Node),
312                  Discrete_Range =>
313                    Make_Range (Loc,
314                      Low_Bound  => Make_Integer_Literal (Loc, 1),
315                      High_Bound => Make_Integer_Literal (Loc, Num_Prims))));
316       end if;
317    end Build_Inherit_Prims;
318
319    -------------------------------
320    -- Build_Get_Prim_Op_Address --
321    -------------------------------
322
323    function Build_Get_Prim_Op_Address
324      (Loc      : Source_Ptr;
325       Typ      : Entity_Id;
326       Tag_Node : Node_Id;
327       Position : Uint) return Node_Id
328    is
329    begin
330       pragma Assert
331         (Position <= DT_Entry_Count (First_Tag_Component (Typ)));
332
333       --  At the end of the Access_Disp_Table list we have the type
334       --  declaration required to convert the tag into a pointer to
335       --  the prims_ptr table (see Freeze_Record_Type).
336
337       return
338         Make_Indexed_Component (Loc,
339           Prefix =>
340             Unchecked_Convert_To
341               (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node),
342           Expressions => New_List (Make_Integer_Literal (Loc, Position)));
343    end Build_Get_Prim_Op_Address;
344
345    -----------------------------
346    -- Build_Get_Transportable --
347    -----------------------------
348
349    function Build_Get_Transportable
350      (Loc      : Source_Ptr;
351       Tag_Node : Node_Id) return Node_Id
352    is
353    begin
354       return
355         Make_Selected_Component (Loc,
356           Prefix => Build_TSD (Loc, Tag_Node),
357           Selector_Name =>
358             New_Reference_To
359               (RTE_Record_Component (RE_Transportable), Loc));
360    end Build_Get_Transportable;
361
362    ------------------------------------
363    -- Build_Inherit_Predefined_Prims --
364    ------------------------------------
365
366    function Build_Inherit_Predefined_Prims
367      (Loc          : Source_Ptr;
368       Old_Tag_Node : Node_Id;
369       New_Tag_Node : Node_Id) return Node_Id
370    is
371    begin
372       if RTE_Available (RE_DT) then
373          return
374            Make_Assignment_Statement (Loc,
375              Name =>
376                Make_Slice (Loc,
377                  Prefix =>
378                    Make_Explicit_Dereference (Loc,
379                      Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
380                        Make_Selected_Component (Loc,
381                          Prefix =>
382                            Build_DT (Loc, New_Tag_Node),
383                          Selector_Name =>
384                            New_Reference_To
385                              (RTE_Record_Component (RE_Predef_Prims), Loc)))),
386                  Discrete_Range => Make_Range (Loc,
387                    Make_Integer_Literal (Loc, Uint_1),
388                    New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))),
389
390              Expression =>
391                Make_Slice (Loc,
392                  Prefix =>
393                    Make_Explicit_Dereference (Loc,
394                      Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
395                        Make_Selected_Component (Loc,
396                          Prefix =>
397                            Build_DT (Loc, Old_Tag_Node),
398                          Selector_Name =>
399                            New_Reference_To
400                              (RTE_Record_Component (RE_Predef_Prims), Loc)))),
401
402                  Discrete_Range =>
403                    Make_Range (Loc,
404                      Low_Bound  => Make_Integer_Literal (Loc, 1),
405                      High_Bound =>
406                        New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))));
407       else
408          return
409            Make_Assignment_Statement (Loc,
410              Name =>
411                Make_Slice (Loc,
412                  Prefix =>
413                    Make_Explicit_Dereference (Loc,
414                      Build_Predef_Prims (Loc, New_Tag_Node)),
415                  Discrete_Range => Make_Range (Loc,
416                    Make_Integer_Literal (Loc, Uint_1),
417                    New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))),
418
419              Expression =>
420                Make_Slice (Loc,
421                  Prefix =>
422                    Make_Explicit_Dereference (Loc,
423                      Build_Predef_Prims (Loc, Old_Tag_Node)),
424                  Discrete_Range =>
425                    Make_Range (Loc,
426                      Low_Bound  => Make_Integer_Literal (Loc, 1),
427                      High_Bound =>
428                        New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))));
429       end if;
430    end Build_Inherit_Predefined_Prims;
431
432    ------------------------
433    -- Build_Predef_Prims --
434    ------------------------
435
436    function Build_Predef_Prims
437      (Loc      : Source_Ptr;
438       Tag_Node : Node_Id) return Node_Id
439    is
440    begin
441       return
442         Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
443           Make_Explicit_Dereference (Loc,
444             Unchecked_Convert_To (RTE (RE_Addr_Ptr),
445               Make_Function_Call (Loc,
446                 Name =>
447                   Make_Expanded_Name (Loc,
448                     Chars => Name_Op_Subtract,
449                     Prefix =>
450                       New_Reference_To
451                         (RTU_Entity (System_Storage_Elements), Loc),
452                     Selector_Name =>
453                       Make_Identifier (Loc,
454                         Chars => Name_Op_Subtract)),
455
456                 Parameter_Associations => New_List (
457                   Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
458                   New_Reference_To (RTE (RE_DT_Predef_Prims_Offset),
459                                     Loc))))));
460    end Build_Predef_Prims;
461
462    ------------------------------------------
463    -- Build_Set_Predefined_Prim_Op_Address --
464    ------------------------------------------
465
466    function Build_Set_Predefined_Prim_Op_Address
467      (Loc          : Source_Ptr;
468       Tag_Node     : Node_Id;
469       Position     : Uint;
470       Address_Node : Node_Id) return Node_Id
471    is
472    begin
473       return
474          Make_Assignment_Statement (Loc,
475            Name       => Build_Get_Predefined_Prim_Op_Address (Loc,
476                            Tag_Node, Position),
477            Expression => Address_Node);
478    end Build_Set_Predefined_Prim_Op_Address;
479
480    -------------------------------
481    -- Build_Set_Prim_Op_Address --
482    -------------------------------
483
484    function Build_Set_Prim_Op_Address
485      (Loc          : Source_Ptr;
486       Typ          : Entity_Id;
487       Tag_Node     : Node_Id;
488       Position     : Uint;
489       Address_Node : Node_Id) return Node_Id
490    is
491    begin
492       return
493         Make_Assignment_Statement (Loc,
494           Name       => Build_Get_Prim_Op_Address
495                           (Loc, Typ, Tag_Node, Position),
496           Expression => Address_Node);
497    end Build_Set_Prim_Op_Address;
498
499    ---------------
500    -- Build_TSD --
501    ---------------
502
503    function Build_TSD (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id is
504    begin
505       return
506         Unchecked_Convert_To (RTE (RE_Type_Specific_Data_Ptr),
507           Make_Explicit_Dereference (Loc,
508             Prefix => Unchecked_Convert_To (RTE (RE_Addr_Ptr),
509               Make_Function_Call (Loc,
510                 Name =>
511                   Make_Expanded_Name (Loc,
512                     Chars => Name_Op_Subtract,
513                     Prefix =>
514                       New_Reference_To
515                         (RTU_Entity (System_Storage_Elements), Loc),
516                     Selector_Name =>
517                       Make_Identifier (Loc,
518                         Chars => Name_Op_Subtract)),
519
520                 Parameter_Associations => New_List (
521                   Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
522                     New_Reference_To
523                       (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))));
524    end Build_TSD;
525
526 end Exp_Atag;