OSDN Git Service

2004-04-08 Joel Sherrill <joel@oarcorp.com>
[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    -- Get_Subprogram_Id --
156    -----------------------
157
158    function Get_Subprogram_Id (E : Entity_Id) return Int is
159       Current_Declaration : Node_Id;
160       Result              : Int := 0;
161
162    begin
163       pragma Assert
164         (Is_Remote_Call_Interface (Scope (E))
165            and then
166              (Nkind (Parent (E)) = N_Procedure_Specification
167                 or else
168               Nkind (Parent (E)) = N_Function_Specification));
169
170       Current_Declaration :=
171         First (Visible_Declarations
172           (Package_Specification_Of_Scope (Scope (E))));
173
174       while Current_Declaration /= Empty loop
175          if Nkind (Current_Declaration) = N_Subprogram_Declaration
176            and then Comes_From_Source (Current_Declaration)
177          then
178             if Defining_Unit_Name
179                  (Specification (Current_Declaration)) = E
180             then
181                return Result;
182             end if;
183
184             Result := Result + 1;
185          end if;
186
187          Next (Current_Declaration);
188       end loop;
189
190       --  Error if we do not find it
191
192       raise Program_Error;
193    end Get_Subprogram_Id;
194
195    ------------------------
196    -- Is_All_Remote_Call --
197    ------------------------
198
199    function Is_All_Remote_Call (N : Node_Id) return Boolean is
200       Par : Node_Id;
201
202    begin
203       if (Nkind (N) = N_Function_Call
204               or else Nkind (N) = N_Procedure_Call_Statement)
205         and then Nkind (Name (N)) in N_Has_Entity
206         and then Is_Remote_Call_Interface (Entity (Name (N)))
207         and then Has_All_Calls_Remote (Scope (Entity (Name (N))))
208         and then Comes_From_Source (N)
209       then
210          Par := Parent (Entity (Name (N)));
211
212          while Present (Par)
213            and then (Nkind (Par) /= N_Package_Specification
214                        or else Is_Wrapper_Package (Defining_Entity (Par)))
215          loop
216             Par := Parent (Par);
217          end loop;
218
219          if Present (Par) then
220             return
221               not Scope_Within_Or_Same (Current_Scope, Defining_Entity (Par));
222          else
223             return False;
224          end if;
225       else
226          return False;
227       end if;
228    end Is_All_Remote_Call;
229
230    ------------------------------------
231    -- Package_Specification_Of_Scope --
232    ------------------------------------
233
234    function Package_Specification_Of_Scope (E : Entity_Id) return Node_Id is
235       N : Node_Id := Parent (E);
236    begin
237       while Nkind (N) /= N_Package_Specification loop
238          N := Parent (N);
239       end loop;
240
241       return N;
242    end Package_Specification_Of_Scope;
243
244    --------------------------
245    -- Process_Partition_ID --
246    --------------------------
247
248    procedure Process_Partition_Id (N : Node_Id) is
249       Loc            : constant Source_Ptr := Sloc (N);
250       Ety            : Entity_Id;
251       Get_Pt_Id      : Node_Id;
252       Get_Pt_Id_Call : Node_Id;
253       Prefix_String  : String_Id;
254       Typ            : constant Entity_Id := Etype (N);
255
256    begin
257       Ety := Entity (Prefix (N));
258
259       --  In case prefix is not a library unit entity, get the entity
260       --  of library unit.
261
262       while (Present (Scope (Ety))
263         and then Scope (Ety) /= Standard_Standard)
264         and not Is_Child_Unit (Ety)
265       loop
266          Ety := Scope (Ety);
267       end loop;
268
269       --  Retrieve the proper function to call.
270
271       if Is_Remote_Call_Interface (Ety) then
272          Get_Pt_Id := New_Occurrence_Of
273            (RTE (RE_Get_Active_Partition_Id), Loc);
274
275       elsif Is_Shared_Passive (Ety) then
276          Get_Pt_Id := New_Occurrence_Of
277            (RTE (RE_Get_Passive_Partition_Id), Loc);
278
279       else
280          Get_Pt_Id := New_Occurrence_Of
281            (RTE (RE_Get_Local_Partition_Id), Loc);
282       end if;
283
284       --  Get and store the String_Id corresponding to the name of the
285       --  library unit whose Partition_Id is needed
286
287       Get_Unit_Name_String (Get_Unit_Name (Unit_Declaration_Node (Ety)));
288
289       --  Remove seven last character ("(spec)" or " (body)").
290       --  (this is a bit nasty, should have interface for this ???)
291
292       Name_Len := Name_Len - 7;
293
294       Start_String;
295       Store_String_Chars (Name_Buffer (1 .. Name_Len));
296       Prefix_String := End_String;
297
298       --  Build the function call which will replace the attribute
299
300       if Is_Remote_Call_Interface (Ety)
301         or else Is_Shared_Passive (Ety)
302       then
303          Get_Pt_Id_Call :=
304            Make_Function_Call (Loc,
305              Name => Get_Pt_Id,
306              Parameter_Associations =>
307                New_List (Make_String_Literal (Loc, Prefix_String)));
308
309       else
310          Get_Pt_Id_Call := Make_Function_Call (Loc, Get_Pt_Id);
311
312       end if;
313
314       --  Replace the attribute node by a conversion of the function call
315       --  to the target type.
316
317       Rewrite (N, Convert_To (Typ, Get_Pt_Id_Call));
318       Analyze_And_Resolve (N, Typ);
319    end Process_Partition_Id;
320
321    ----------------------------------
322    -- Process_Remote_AST_Attribute --
323    ----------------------------------
324
325    procedure Process_Remote_AST_Attribute
326      (N        : Node_Id;
327       New_Type : Entity_Id)
328    is
329       Loc                   : constant Source_Ptr := Sloc (N);
330       Remote_Subp           : Entity_Id;
331       Tick_Access_Conv_Call : Node_Id;
332       Remote_Subp_Decl      : Node_Id;
333       RS_Pkg_Specif         : Node_Id;
334       RS_Pkg_E              : Entity_Id;
335       RAS_Type              : Entity_Id;
336       Async_E               : Entity_Id;
337       Subp_Id               : Int;
338       Attribute_Subp        : Entity_Id;
339       Parameter             : Node_Id;
340
341    begin
342       --  Check if we have to expand the access attribute
343
344       Remote_Subp := Entity (Prefix (N));
345
346       if not Expander_Active then
347          return;
348
349       elsif Ekind (New_Type) = E_Record_Type then
350          RAS_Type := New_Type;
351
352       else
353          --  If the remote type has not been constructed yet, create
354          --  it and its attributes now.
355
356          Attribute_Subp := TSS (New_Type, TSS_RAS_Access);
357
358          if No (Attribute_Subp) then
359             Add_RAST_Features (Parent (New_Type));
360          end if;
361
362          RAS_Type := Equivalent_Type (New_Type);
363       end if;
364
365       Attribute_Subp := TSS (RAS_Type, TSS_RAS_Access);
366       Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
367
368       if Nkind (Remote_Subp_Decl) = N_Subprogram_Body then
369          Remote_Subp := Corresponding_Spec (Remote_Subp_Decl);
370          Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
371       end if;
372
373       RS_Pkg_Specif := Parent (Remote_Subp_Decl);
374       RS_Pkg_E := Defining_Entity (RS_Pkg_Specif);
375
376       Subp_Id := Get_Subprogram_Id (Remote_Subp);
377
378       if Ekind (Remote_Subp) = E_Procedure
379         and then Is_Asynchronous (Remote_Subp)
380       then
381          Async_E := Standard_True;
382       else
383          Async_E := Standard_False;
384       end if;
385
386       Parameter := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
387
388       Tick_Access_Conv_Call :=
389         Make_Function_Call (Loc,
390           Name => New_Occurrence_Of (Attribute_Subp, Loc),
391           Parameter_Associations =>
392             New_List (
393               Parameter,
394               Make_String_Literal (Loc, Full_Qualified_Name (RS_Pkg_E)),
395               Make_Integer_Literal (Loc, Subp_Id),
396               New_Occurrence_Of (Async_E, Loc)));
397
398       Rewrite (N, Tick_Access_Conv_Call);
399       Analyze_And_Resolve (N, RAS_Type);
400    end Process_Remote_AST_Attribute;
401
402    ------------------------------------
403    -- Process_Remote_AST_Declaration --
404    ------------------------------------
405
406    procedure Process_Remote_AST_Declaration (N : Node_Id) is
407       Loc           : constant Source_Ptr := Sloc (N);
408       User_Type     : constant Node_Id := Defining_Identifier (N);
409       Fat_Type      : constant Entity_Id :=
410                         Make_Defining_Identifier
411                           (Loc, Chars (User_Type));
412       New_Type_Decl : Node_Id;
413
414    begin
415       --  We add a record type declaration for the equivalent fat pointer type
416
417       New_Type_Decl :=
418         Make_Full_Type_Declaration (Loc,
419           Defining_Identifier => Fat_Type,
420           Type_Definition =>
421             Make_Record_Definition (Loc,
422               Component_List =>
423                 Make_Component_List (Loc,
424                   Component_Items => New_List (
425
426                     Make_Component_Declaration (Loc,
427                       Defining_Identifier =>
428                         Make_Defining_Identifier (Loc,
429                           Chars => Name_Ras),
430                       Component_Definition =>
431                         Make_Component_Definition (Loc,
432                           Aliased_Present    => False,
433                           Subtype_Indication =>
434                             New_Occurrence_Of (RTE (RE_Unsigned_64), Loc))),
435
436                     Make_Component_Declaration (Loc,
437                       Defining_Identifier =>
438                         Make_Defining_Identifier (Loc,
439                           Chars => Name_Origin),
440                       Component_Definition =>
441                         Make_Component_Definition (Loc,
442                           Aliased_Present    => False,
443                           Subtype_Indication =>
444                             New_Reference_To (Standard_Integer, Loc))),
445
446                     Make_Component_Declaration (Loc,
447                       Defining_Identifier =>
448                         Make_Defining_Identifier (Loc,
449                           Chars => Name_Receiver),
450                       Component_Definition =>
451                         Make_Component_Definition (Loc,
452                           Aliased_Present    => False,
453                           Subtype_Indication =>
454                             New_Reference_To (RTE (RE_Unsigned_64), Loc))),
455
456                     Make_Component_Declaration (Loc,
457                       Defining_Identifier =>
458                         Make_Defining_Identifier (Loc,
459                           Chars => Name_Subp_Id),
460                       Component_Definition =>
461                         Make_Component_Definition (Loc,
462                           Aliased_Present    => False,
463                           Subtype_Indication =>
464                             New_Reference_To (Standard_Natural, Loc))),
465
466                     Make_Component_Declaration (Loc,
467                       Defining_Identifier =>
468                         Make_Defining_Identifier (Loc,
469                           Chars => Name_Async),
470                       Component_Definition =>
471                         Make_Component_Definition (Loc,
472                           Aliased_Present    => False,
473                           Subtype_Indication =>
474                             New_Reference_To (Standard_Boolean, Loc)))))));
475
476       Insert_After (N, New_Type_Decl);
477       Set_Equivalent_Type (User_Type, Fat_Type);
478       Set_Corresponding_Remote_Type (Fat_Type, User_Type);
479
480       --  The reason we suppress the initialization procedure is that we know
481       --  that no initialization is required (even if Initialize_Scalars mode
482       --  is active), and there are order of elaboration problems if we do try
483       --  to generate an init proc for this created record type.
484
485       Set_Suppress_Init_Proc (Fat_Type);
486
487       if Expander_Active then
488          Add_RAST_Features (Parent (User_Type));
489       end if;
490    end Process_Remote_AST_Declaration;
491
492    -----------------------
493    -- RAS_E_Dereference --
494    -----------------------
495
496    procedure RAS_E_Dereference (Pref : Node_Id) is
497       Loc             : constant Source_Ptr := Sloc (Pref);
498       Call_Node       : Node_Id;
499       New_Type        : constant Entity_Id := Etype (Pref);
500       RAS             : constant Entity_Id :=
501                           Corresponding_Remote_Type (New_Type);
502       RAS_Decl        : constant Node_Id   := Parent (RAS);
503       Explicit_Deref  : constant Node_Id   := Parent (Pref);
504       Deref_Subp_Call : constant Node_Id   := Parent (Explicit_Deref);
505       Deref_Proc      : Entity_Id;
506       Params          : List_Id;
507
508    begin
509       if Nkind (Deref_Subp_Call) = N_Procedure_Call_Statement then
510          Params := Parameter_Associations (Deref_Subp_Call);
511
512          if Present (Params) then
513             Prepend (Pref, Params);
514          else
515             Params := New_List (Pref);
516          end if;
517
518       elsif Nkind (Deref_Subp_Call) = N_Indexed_Component then
519
520          Params := Expressions (Deref_Subp_Call);
521
522          if Present (Params) then
523             Prepend (Pref, Params);
524          else
525             Params := New_List (Pref);
526          end if;
527
528       else
529          --  Context is not a call.
530
531          return;
532       end if;
533
534       Deref_Proc := TSS (New_Type, TSS_RAS_Dereference);
535
536       if not Expander_Active then
537          return;
538
539       elsif No (Deref_Proc) then
540          Add_RAST_Features (RAS_Decl);
541          Deref_Proc := TSS (New_Type, TSS_RAS_Dereference);
542       end if;
543
544       if Ekind (Deref_Proc) = E_Function then
545          Call_Node :=
546            Make_Function_Call (Loc,
547               Name => New_Occurrence_Of (Deref_Proc, Loc),
548               Parameter_Associations => Params);
549
550       else
551          Call_Node :=
552            Make_Procedure_Call_Statement (Loc,
553               Name => New_Occurrence_Of (Deref_Proc, Loc),
554               Parameter_Associations => Params);
555       end if;
556
557       Rewrite (Deref_Subp_Call, Call_Node);
558       Analyze (Deref_Subp_Call);
559    end RAS_E_Dereference;
560
561    ------------------------------
562    -- Remote_AST_E_Dereference --
563    ------------------------------
564
565    function Remote_AST_E_Dereference (P : Node_Id) return Boolean
566    is
567       ET : constant Entity_Id  := Etype (P);
568
569    begin
570       --  Perform the changes only on original dereferences, and only if
571       --  we are generating code.
572
573       if Comes_From_Source (P)
574         and then Is_Record_Type (ET)
575         and then (Is_Remote_Call_Interface (ET)
576                    or else Is_Remote_Types (ET))
577         and then Present (Corresponding_Remote_Type (ET))
578         and then (Nkind (Parent (Parent (P))) = N_Procedure_Call_Statement
579                    or else Nkind (Parent (Parent (P))) = N_Indexed_Component)
580         and then Expander_Active
581       then
582          RAS_E_Dereference (P);
583          return True;
584       else
585          return False;
586       end if;
587    end Remote_AST_E_Dereference;
588
589    ------------------------------
590    -- Remote_AST_I_Dereference --
591    ------------------------------
592
593    function Remote_AST_I_Dereference (P : Node_Id) return Boolean
594    is
595       ET     : constant Entity_Id  := Etype (P);
596       Deref  : Node_Id;
597    begin
598
599       if Comes_From_Source (P)
600         and then (Is_Remote_Call_Interface (ET)
601                    or else Is_Remote_Types (ET))
602         and then Present (Corresponding_Remote_Type (ET))
603         and then Ekind (Entity (P)) /= E_Function
604       then
605          Deref :=
606            Make_Explicit_Dereference (Sloc (P),
607              Prefix => Relocate_Node (P));
608          Rewrite (P, Deref);
609          Set_Etype (P, ET);
610          RAS_E_Dereference (Prefix (P));
611          return True;
612       end if;
613
614       return False;
615    end Remote_AST_I_Dereference;
616
617    ---------------------------
618    -- Remote_AST_Null_Value --
619    ---------------------------
620
621    function Remote_AST_Null_Value
622      (N    : Node_Id;
623       Typ  : Entity_Id)
624       return Boolean
625    is
626       Loc         : constant Source_Ptr := Sloc (N);
627       Target_Type : Entity_Id;
628
629    begin
630       if not Expander_Active then
631          return False;
632
633       elsif Ekind (Typ) = E_Access_Subprogram_Type
634         and then (Is_Remote_Call_Interface (Typ)
635                     or else Is_Remote_Types (Typ))
636         and then Comes_From_Source (N)
637         and then Expander_Active
638       then
639          --  Any null that comes from source and is of the RAS type must
640          --  be expanded, except if expansion is not active (nothing
641          --  gets expanded into the equivalent record type).
642
643          Target_Type := Equivalent_Type (Typ);
644
645       elsif Ekind (Typ) = E_Record_Type
646         and then Present (Corresponding_Remote_Type (Typ))
647       then
648          --  This is a record type representing a RAS type, this must be
649          --  expanded.
650
651          Target_Type := Typ;
652
653       else
654          --  We do not have to handle this case
655
656          return False;
657
658       end if;
659
660       Rewrite (N,
661         Make_Aggregate (Loc,
662           Expressions => New_List (
663             Make_Integer_Literal (Loc, 0),                  -- Ras
664             Make_Integer_Literal (Loc, 0),                  -- Origin
665             Make_Integer_Literal (Loc, 0),                  -- Receiver
666             Make_Integer_Literal (Loc, 0),                  -- Subp_Id
667             New_Occurrence_Of (Standard_False, Loc))));     -- Asyn
668       Analyze_And_Resolve (N, Target_Type);
669       return True;
670    end Remote_AST_Null_Value;
671
672 end Sem_Dist;