OSDN Git Service

2004-04-19 Arnaud Charlet <charlet@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_dist.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             S E M _ D I S T                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2004, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Atree;    use Atree;
28 with Casing;   use Casing;
29 with Einfo;    use Einfo;
30 with Errout;   use Errout;
31 with Exp_Dist; use Exp_Dist;
32 with Exp_Tss;  use Exp_Tss;
33 with Nlists;   use Nlists;
34 with Nmake;    use Nmake;
35 with Namet;    use Namet;
36 with Opt;      use Opt;
37 with Rtsfind;  use Rtsfind;
38 with Sem;      use Sem;
39 with Sem_Res;  use Sem_Res;
40 with Sem_Util; use Sem_Util;
41 with Sinfo;    use Sinfo;
42 with Snames;   use Snames;
43 with Stand;    use Stand;
44 with Stringt;  use Stringt;
45 with Tbuild;   use Tbuild;
46 with Uname;    use Uname;
47
48 package body Sem_Dist is
49
50    -----------------------
51    -- Local Subprograms --
52    -----------------------
53
54    procedure RAS_E_Dereference (Pref : Node_Id);
55    --  Handles explicit dereference of Remote Access to Subprograms.
56
57    function Full_Qualified_Name (E : Entity_Id) return String_Id;
58    --  returns the full qualified name of the entity in lower case.
59
60    -------------------------
61    -- Add_Stub_Constructs --
62    -------------------------
63
64    procedure Add_Stub_Constructs (N : Node_Id) is
65       U    : constant Node_Id := Unit (N);
66       Spec : Entity_Id        := Empty;
67       Exp  : Node_Id          := U;         --  Unit that will be expanded
68
69    begin
70       pragma Assert (Distribution_Stub_Mode /= No_Stubs);
71
72       if Nkind (U) = N_Package_Declaration then
73          Spec := Defining_Entity (Specification (U));
74
75       elsif Nkind (U) = N_Package_Body then
76          Spec := Corresponding_Spec (U);
77
78       else pragma Assert (Nkind (U) = N_Package_Instantiation);
79          Exp  := Instance_Spec (U);
80          Spec := Defining_Entity (Specification (Exp));
81       end if;
82
83       pragma Assert (Is_Shared_Passive (Spec)
84         or else Is_Remote_Call_Interface (Spec));
85
86       if Distribution_Stub_Mode = Generate_Caller_Stub_Body then
87
88          if Is_Shared_Passive (Spec) then
89             null;
90          elsif Nkind (U) = N_Package_Body then
91             Error_Msg_N
92               ("Specification file expected from command line", U);
93          else
94             Expand_Calling_Stubs_Bodies (Exp);
95          end if;
96
97       else
98
99          if Is_Shared_Passive (Spec) then
100             Build_Passive_Partition_Stub (Exp);
101          else
102             Expand_Receiving_Stubs_Bodies (Exp);
103          end if;
104
105       end if;
106    end Add_Stub_Constructs;
107
108    -------------------------
109    -- Full_Qualified_Name --
110    -------------------------
111
112    function Full_Qualified_Name (E : Entity_Id) return String_Id is
113       Ent         : Entity_Id := E;
114       Parent_Name : String_Id := No_String;
115
116    begin
117       --  Deals properly with child units
118
119       if Nkind (Ent) = N_Defining_Program_Unit_Name then
120          Ent := Defining_Identifier (Ent);
121       end if;
122
123       --  Compute recursively the qualification. Only "Standard" has no scope.
124
125       if Present (Scope (Scope (Ent))) then
126          Parent_Name := Full_Qualified_Name (Scope (Ent));
127       end if;
128
129       --  Every entity should have a name except some expanded blocks
130       --  don't bother about those.
131
132       if Chars (Ent) = No_Name then
133          return Parent_Name;
134       end if;
135
136       --  Add a period between Name and qualification
137
138       if Parent_Name /= No_String then
139          Start_String (Parent_Name);
140          Store_String_Char (Get_Char_Code ('.'));
141
142       else
143          Start_String;
144       end if;
145
146       --  Generates the entity name in upper case
147
148       Get_Name_String (Chars (Ent));
149       Set_Casing (All_Lower_Case);
150       Store_String_Chars (Name_Buffer (1 .. Name_Len));
151       return End_String;
152    end Full_Qualified_Name;
153
154    ------------------------
155    -- Is_All_Remote_Call --
156    ------------------------
157
158    function Is_All_Remote_Call (N : Node_Id) return Boolean is
159       Par : Node_Id;
160
161    begin
162       if (Nkind (N) = N_Function_Call
163               or else Nkind (N) = N_Procedure_Call_Statement)
164         and then Nkind (Name (N)) in N_Has_Entity
165         and then Is_Remote_Call_Interface (Entity (Name (N)))
166         and then Has_All_Calls_Remote (Scope (Entity (Name (N))))
167         and then Comes_From_Source (N)
168       then
169          Par := Parent (Entity (Name (N)));
170
171          while Present (Par)
172            and then (Nkind (Par) /= N_Package_Specification
173                        or else Is_Wrapper_Package (Defining_Entity (Par)))
174          loop
175             Par := Parent (Par);
176          end loop;
177
178          if Present (Par) then
179             return
180               not Scope_Within_Or_Same (Current_Scope, Defining_Entity (Par));
181          else
182             return False;
183          end if;
184       else
185          return False;
186       end if;
187    end Is_All_Remote_Call;
188
189    ------------------------------------
190    -- Package_Specification_Of_Scope --
191    ------------------------------------
192
193    function Package_Specification_Of_Scope (E : Entity_Id) return Node_Id is
194       N : Node_Id := Parent (E);
195    begin
196       while Nkind (N) /= N_Package_Specification loop
197          N := Parent (N);
198       end loop;
199
200       return N;
201    end Package_Specification_Of_Scope;
202
203    --------------------------
204    -- Process_Partition_ID --
205    --------------------------
206
207    procedure Process_Partition_Id (N : Node_Id) is
208       Loc            : constant Source_Ptr := Sloc (N);
209       Ety            : Entity_Id;
210       Get_Pt_Id      : Node_Id;
211       Get_Pt_Id_Call : Node_Id;
212       Prefix_String  : String_Id;
213       Typ            : constant Entity_Id := Etype (N);
214
215    begin
216       Ety := Entity (Prefix (N));
217
218       --  In case prefix is not a library unit entity, get the entity
219       --  of library unit.
220
221       while (Present (Scope (Ety))
222         and then Scope (Ety) /= Standard_Standard)
223         and not Is_Child_Unit (Ety)
224       loop
225          Ety := Scope (Ety);
226       end loop;
227
228       --  Retrieve the proper function to call.
229
230       if Is_Remote_Call_Interface (Ety) then
231          Get_Pt_Id := New_Occurrence_Of
232            (RTE (RE_Get_Active_Partition_Id), Loc);
233
234       elsif Is_Shared_Passive (Ety) then
235          Get_Pt_Id := New_Occurrence_Of
236            (RTE (RE_Get_Passive_Partition_Id), Loc);
237
238       else
239          Get_Pt_Id := New_Occurrence_Of
240            (RTE (RE_Get_Local_Partition_Id), Loc);
241       end if;
242
243       --  Get and store the String_Id corresponding to the name of the
244       --  library unit whose Partition_Id is needed
245
246       Get_Unit_Name_String (Get_Unit_Name (Unit_Declaration_Node (Ety)));
247
248       --  Remove seven last character ("(spec)" or " (body)").
249       --  (this is a bit nasty, should have interface for this ???)
250
251       Name_Len := Name_Len - 7;
252
253       Start_String;
254       Store_String_Chars (Name_Buffer (1 .. Name_Len));
255       Prefix_String := End_String;
256
257       --  Build the function call which will replace the attribute
258
259       if Is_Remote_Call_Interface (Ety)
260         or else Is_Shared_Passive (Ety)
261       then
262          Get_Pt_Id_Call :=
263            Make_Function_Call (Loc,
264              Name => Get_Pt_Id,
265              Parameter_Associations =>
266                New_List (Make_String_Literal (Loc, Prefix_String)));
267
268       else
269          Get_Pt_Id_Call := Make_Function_Call (Loc, Get_Pt_Id);
270
271       end if;
272
273       --  Replace the attribute node by a conversion of the function call
274       --  to the target type.
275
276       Rewrite (N, Convert_To (Typ, Get_Pt_Id_Call));
277       Analyze_And_Resolve (N, Typ);
278    end Process_Partition_Id;
279
280    ----------------------------------
281    -- Process_Remote_AST_Attribute --
282    ----------------------------------
283
284    procedure Process_Remote_AST_Attribute
285      (N        : Node_Id;
286       New_Type : Entity_Id)
287    is
288       Loc                   : constant Source_Ptr := Sloc (N);
289       Remote_Subp           : Entity_Id;
290       Tick_Access_Conv_Call : Node_Id;
291       Remote_Subp_Decl      : Node_Id;
292       RS_Pkg_Specif         : Node_Id;
293       RS_Pkg_E              : Entity_Id;
294       RAS_Type              : Entity_Id;
295       Async_E               : Entity_Id;
296       Attribute_Subp        : Entity_Id;
297       Parameter             : Node_Id;
298
299    begin
300       --  Check if we have to expand the access attribute
301
302       Remote_Subp := Entity (Prefix (N));
303
304       if not Expander_Active then
305          return;
306
307       elsif Ekind (New_Type) = E_Record_Type then
308          RAS_Type := New_Type;
309
310       else
311          --  If the remote type has not been constructed yet, create
312          --  it and its attributes now.
313
314          Attribute_Subp := TSS (New_Type, TSS_RAS_Access);
315
316          if No (Attribute_Subp) then
317             Add_RAST_Features (Parent (New_Type));
318          end if;
319
320          RAS_Type := Equivalent_Type (New_Type);
321       end if;
322
323       Attribute_Subp := TSS (RAS_Type, TSS_RAS_Access);
324       Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
325
326       if Nkind (Remote_Subp_Decl) = N_Subprogram_Body then
327          Remote_Subp := Corresponding_Spec (Remote_Subp_Decl);
328          Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
329       end if;
330
331       RS_Pkg_Specif := Parent (Remote_Subp_Decl);
332       RS_Pkg_E := Defining_Entity (RS_Pkg_Specif);
333
334       if Ekind (Remote_Subp) = E_Procedure
335         and then Is_Asynchronous (Remote_Subp)
336       then
337          Async_E := Standard_True;
338       else
339          Async_E := Standard_False;
340       end if;
341
342       Parameter := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
343
344       Tick_Access_Conv_Call :=
345         Make_Function_Call (Loc,
346           Name => New_Occurrence_Of (Attribute_Subp, Loc),
347           Parameter_Associations =>
348             New_List (
349               Parameter,
350               Make_String_Literal (Loc, Full_Qualified_Name (RS_Pkg_E)),
351               Build_Subprogram_Id (Loc, Remote_Subp),
352               New_Occurrence_Of (Async_E, Loc)));
353
354       Rewrite (N, Tick_Access_Conv_Call);
355       Analyze_And_Resolve (N, RAS_Type);
356    end Process_Remote_AST_Attribute;
357
358    ------------------------------------
359    -- Process_Remote_AST_Declaration --
360    ------------------------------------
361
362    procedure Process_Remote_AST_Declaration (N : Node_Id) is
363       Loc           : constant Source_Ptr := Sloc (N);
364       User_Type     : constant Node_Id := Defining_Identifier (N);
365       Fat_Type      : constant Entity_Id :=
366                         Make_Defining_Identifier
367                           (Loc, Chars (User_Type));
368       New_Type_Decl : Node_Id;
369
370    begin
371       --  We add a record type declaration for the equivalent fat pointer type
372
373       New_Type_Decl :=
374         Make_Full_Type_Declaration (Loc,
375           Defining_Identifier => Fat_Type,
376           Type_Definition =>
377             Make_Record_Definition (Loc,
378               Component_List =>
379                 Make_Component_List (Loc,
380                   Component_Items => New_List (
381
382                     Make_Component_Declaration (Loc,
383                       Defining_Identifier =>
384                         Make_Defining_Identifier (Loc,
385                           Chars => Name_Ras),
386                       Component_Definition =>
387                         Make_Component_Definition (Loc,
388                           Aliased_Present    => False,
389                           Subtype_Indication =>
390                             New_Occurrence_Of (RTE (RE_Unsigned_64), Loc))),
391
392                     Make_Component_Declaration (Loc,
393                       Defining_Identifier =>
394                         Make_Defining_Identifier (Loc,
395                           Chars => Name_Origin),
396                       Component_Definition =>
397                         Make_Component_Definition (Loc,
398                           Aliased_Present    => False,
399                           Subtype_Indication =>
400                             New_Reference_To (Standard_Integer, Loc))),
401
402                     Make_Component_Declaration (Loc,
403                       Defining_Identifier =>
404                         Make_Defining_Identifier (Loc,
405                           Chars => Name_Receiver),
406                       Component_Definition =>
407                         Make_Component_Definition (Loc,
408                           Aliased_Present    => False,
409                           Subtype_Indication =>
410                             New_Reference_To (RTE (RE_Unsigned_64), Loc))),
411
412                     Make_Component_Declaration (Loc,
413                       Defining_Identifier =>
414                         Make_Defining_Identifier (Loc,
415                           Chars => Name_Subp_Id),
416                       Component_Definition =>
417                         Make_Component_Definition (Loc,
418                           Aliased_Present    => False,
419                           Subtype_Indication =>
420                             New_Reference_To (Standard_Natural, Loc))),
421
422                     Make_Component_Declaration (Loc,
423                       Defining_Identifier =>
424                         Make_Defining_Identifier (Loc,
425                           Chars => Name_Async),
426                       Component_Definition =>
427                         Make_Component_Definition (Loc,
428                           Aliased_Present    => False,
429                           Subtype_Indication =>
430                             New_Reference_To (Standard_Boolean, Loc)))))));
431
432       Insert_After (N, New_Type_Decl);
433       Set_Equivalent_Type (User_Type, Fat_Type);
434       Set_Corresponding_Remote_Type (Fat_Type, User_Type);
435
436       --  The reason we suppress the initialization procedure is that we know
437       --  that no initialization is required (even if Initialize_Scalars mode
438       --  is active), and there are order of elaboration problems if we do try
439       --  to generate an init proc for this created record type.
440
441       Set_Suppress_Init_Proc (Fat_Type);
442
443       if Expander_Active then
444          Add_RAST_Features (Parent (User_Type));
445       end if;
446    end Process_Remote_AST_Declaration;
447
448    -----------------------
449    -- RAS_E_Dereference --
450    -----------------------
451
452    procedure RAS_E_Dereference (Pref : Node_Id) is
453       Loc             : constant Source_Ptr := Sloc (Pref);
454       Call_Node       : Node_Id;
455       New_Type        : constant Entity_Id := Etype (Pref);
456       RAS             : constant Entity_Id :=
457                           Corresponding_Remote_Type (New_Type);
458       RAS_Decl        : constant Node_Id   := Parent (RAS);
459       Explicit_Deref  : constant Node_Id   := Parent (Pref);
460       Deref_Subp_Call : constant Node_Id   := Parent (Explicit_Deref);
461       Deref_Proc      : Entity_Id;
462       Params          : List_Id;
463
464    begin
465       if Nkind (Deref_Subp_Call) = N_Procedure_Call_Statement then
466          Params := Parameter_Associations (Deref_Subp_Call);
467
468          if Present (Params) then
469             Prepend (Pref, Params);
470          else
471             Params := New_List (Pref);
472          end if;
473
474       elsif Nkind (Deref_Subp_Call) = N_Indexed_Component then
475
476          Params := Expressions (Deref_Subp_Call);
477
478          if Present (Params) then
479             Prepend (Pref, Params);
480          else
481             Params := New_List (Pref);
482          end if;
483
484       else
485          --  Context is not a call.
486
487          return;
488       end if;
489
490       Deref_Proc := TSS (New_Type, TSS_RAS_Dereference);
491
492       if not Expander_Active then
493          return;
494
495       elsif No (Deref_Proc) then
496          Add_RAST_Features (RAS_Decl);
497          Deref_Proc := TSS (New_Type, TSS_RAS_Dereference);
498       end if;
499
500       if Ekind (Deref_Proc) = E_Function then
501          Call_Node :=
502            Make_Function_Call (Loc,
503               Name => New_Occurrence_Of (Deref_Proc, Loc),
504               Parameter_Associations => Params);
505
506       else
507          Call_Node :=
508            Make_Procedure_Call_Statement (Loc,
509               Name => New_Occurrence_Of (Deref_Proc, Loc),
510               Parameter_Associations => Params);
511       end if;
512
513       Rewrite (Deref_Subp_Call, Call_Node);
514       Analyze (Deref_Subp_Call);
515    end RAS_E_Dereference;
516
517    ------------------------------
518    -- Remote_AST_E_Dereference --
519    ------------------------------
520
521    function Remote_AST_E_Dereference (P : Node_Id) return Boolean
522    is
523       ET : constant Entity_Id  := Etype (P);
524
525    begin
526       --  Perform the changes only on original dereferences, and only if
527       --  we are generating code.
528
529       if Comes_From_Source (P)
530         and then Is_Record_Type (ET)
531         and then (Is_Remote_Call_Interface (ET)
532                    or else Is_Remote_Types (ET))
533         and then Present (Corresponding_Remote_Type (ET))
534         and then (Nkind (Parent (Parent (P))) = N_Procedure_Call_Statement
535                    or else Nkind (Parent (Parent (P))) = N_Indexed_Component)
536         and then Expander_Active
537       then
538          RAS_E_Dereference (P);
539          return True;
540       else
541          return False;
542       end if;
543    end Remote_AST_E_Dereference;
544
545    ------------------------------
546    -- Remote_AST_I_Dereference --
547    ------------------------------
548
549    function Remote_AST_I_Dereference (P : Node_Id) return Boolean
550    is
551       ET     : constant Entity_Id  := Etype (P);
552       Deref  : Node_Id;
553    begin
554
555       if Comes_From_Source (P)
556         and then (Is_Remote_Call_Interface (ET)
557                    or else Is_Remote_Types (ET))
558         and then Present (Corresponding_Remote_Type (ET))
559         and then Ekind (Entity (P)) /= E_Function
560       then
561          Deref :=
562            Make_Explicit_Dereference (Sloc (P),
563              Prefix => Relocate_Node (P));
564          Rewrite (P, Deref);
565          Set_Etype (P, ET);
566          RAS_E_Dereference (Prefix (P));
567          return True;
568       end if;
569
570       return False;
571    end Remote_AST_I_Dereference;
572
573    ---------------------------
574    -- Remote_AST_Null_Value --
575    ---------------------------
576
577    function Remote_AST_Null_Value
578      (N    : Node_Id;
579       Typ  : Entity_Id)
580       return Boolean
581    is
582       Loc         : constant Source_Ptr := Sloc (N);
583       Target_Type : Entity_Id;
584
585    begin
586       if not Expander_Active then
587          return False;
588
589       elsif Ekind (Typ) = E_Access_Subprogram_Type
590         and then (Is_Remote_Call_Interface (Typ)
591                     or else Is_Remote_Types (Typ))
592         and then Comes_From_Source (N)
593         and then Expander_Active
594       then
595          --  Any null that comes from source and is of the RAS type must
596          --  be expanded, except if expansion is not active (nothing
597          --  gets expanded into the equivalent record type).
598
599          Target_Type := Equivalent_Type (Typ);
600
601       elsif Ekind (Typ) = E_Record_Type
602         and then Present (Corresponding_Remote_Type (Typ))
603       then
604          --  This is a record type representing a RAS type, this must be
605          --  expanded.
606
607          Target_Type := Typ;
608
609       else
610          --  We do not have to handle this case
611
612          return False;
613
614       end if;
615
616       Rewrite (N,
617         Make_Aggregate (Loc,
618           Expressions => New_List (
619             Make_Integer_Literal (Loc, 0),                  -- Ras
620             Make_Integer_Literal (Loc, 0),                  -- Origin
621             Make_Integer_Literal (Loc, 0),                  -- Receiver
622             Make_Integer_Literal (Loc, 0),                  -- Subp_Id
623             New_Occurrence_Of (Standard_False, Loc))));     -- Asyn
624       Analyze_And_Resolve (N, Target_Type);
625       return True;
626    end Remote_AST_Null_Value;
627
628 end Sem_Dist;