OSDN Git Service

Nathanael Nerode <neroden@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / ada / rtsfind.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              R T S F I N D                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --                                                                          --
10 --          Copyright (C) 1992-2002, Free Software Foundation, Inc.         --
11 --                                                                          --
12 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
13 -- terms of the  GNU General Public License as published  by the Free Soft- --
14 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
20 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
21 -- MA 02111-1307, USA.                                                      --
22 --                                                                          --
23 -- GNAT was originally developed  by the GNAT team at  New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
25 --                                                                          --
26 ------------------------------------------------------------------------------
27
28 with Atree;     use Atree;
29 with Casing;    use Casing;
30 with Csets;     use Csets;
31 with Debug;     use Debug;
32 with Einfo;     use Einfo;
33 with Elists;    use Elists;
34 with Fname;     use Fname;
35 with Fname.UF;  use Fname.UF;
36 with Lib;       use Lib;
37 with Lib.Load;  use Lib.Load;
38 with Namet;     use Namet;
39 with Nlists;    use Nlists;
40 with Nmake;     use Nmake;
41 with Output;    use Output;
42 with Opt;       use Opt;
43 with Restrict;  use Restrict;
44 with Sem;       use Sem;
45 with Sem_Ch7;   use Sem_Ch7;
46 with Sem_Util;  use Sem_Util;
47 with Sinfo;     use Sinfo;
48 with Stand;     use Stand;
49 with Snames;    use Snames;
50 with Tbuild;    use Tbuild;
51 with Uname;     use Uname;
52
53 package body Rtsfind is
54
55    ----------------
56    -- Unit table --
57    ----------------
58
59    --  The unit table has one entry for each unit included in the definition
60    --  of the type RTU_Id in the spec. The table entries are initialized in
61    --  Initialize to set the Entity field to Empty, indicating that the
62    --  corresponding unit has not yet been loaded. The fields are set when
63    --  a unit is loaded to contain the defining entity for the unit, the
64    --  unit name, and the unit number.
65
66    type RT_Unit_Table_Record is record
67       Entity : Entity_Id;
68       Uname  : Unit_Name_Type;
69       Unum   : Unit_Number_Type;
70       Withed : Boolean;
71    end record;
72
73    RT_Unit_Table : array (RTU_Id) of RT_Unit_Table_Record;
74
75    --------------------------
76    -- Runtime Entity Table --
77    --------------------------
78
79    --  There is one entry in the runtime entity table for each entity that is
80    --  included in the definition of the RE_Id type in the spec. The entries
81    --  are set by Initialize_Rtsfind to contain Empty, indicating that the
82    --  entity has not yet been located. Once the entity is located for the
83    --  first time, its ID is stored in this array, so that subsequent calls
84    --  for the same entity can be satisfied immediately.
85
86    RE_Table : array (RE_Id) of Entity_Id;
87
88    --------------------------
89    -- Generation of WITH's --
90    --------------------------
91
92    --  When a unit is implicitly loaded as a result of a call to RTE, it
93    --  is necessary to create an implicit with to ensure that the object
94    --  is correctly loaded by the binder. Such with statements are only
95    --  required when the request is from the extended main unit (if a
96    --  client needs a with, that will be taken care of when the client
97    --  is compiled.
98
99    --  We always attach the with to the main unit. This is not perfectly
100    --  accurate in terms of elaboration requirements, but it is close
101    --  enough, since the units that are accessed using rtsfind do not
102    --  have delicate elaboration requirements.
103
104    --  The flag Withed in the unit table record is initially set to False.
105    --  It is set True if a with has been generated for the main unit for
106    --  the corresponding unit.
107
108    -----------------------
109    -- Local Subprograms --
110    -----------------------
111
112    procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "");
113    --  Internal procedure called if we can't find the entity or unit.
114    --  The parameter is a detailed error message that is to be given.
115    --  S is a reason for failing to compile the file. U_Id is the unit
116    --  id, and Ent_Name, if non-null, is the associated entity name.
117
118    function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type;
119    --  Retrieves the Unit Name given a unit id represented by its
120    --  enumaration value in RTU_Id.
121
122    procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False);
123    --  Load the unit whose Id is given if not already loaded. The unit is
124    --  loaded, analyzed, and added to the with list, and the entry in
125    --  RT_Unit_Table is updated to reflect the load. The second parameter
126    --  indicates the initial setting for the Is_Potentially_Use_Visible
127    --  flag of the entity for the loaded unit (if it is indeed loaded).
128    --  A value of False means nothing special need be done. A value of
129    --  True indicates that this flag must be set to True. It is needed
130    --  only in the Text_IO_Kludge procedure, which may materialize an
131    --  entity of Text_IO (or Wide_Text_IO) that was previously unknown.
132
133    function RE_Chars (E : RE_Id) return Name_Id;
134    --  Given a RE_Id value returns the Chars of the corresponding entity.
135
136    -------------------
137    -- Get_Unit_Name --
138    -------------------
139
140    function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type is
141       Uname_Chars : constant String := RTU_Id'Image (U_Id);
142
143    begin
144       Name_Len := Uname_Chars'Length;
145       Name_Buffer (1 .. Name_Len) := Uname_Chars;
146       Set_Casing (All_Lower_Case);
147
148       if U_Id in Ada_Child then
149          Name_Buffer (4) := '.';
150
151          if U_Id in Ada_Calendar_Child then
152             Name_Buffer (13) := '.';
153
154          elsif U_Id in Ada_Finalization_Child then
155             Name_Buffer (17) := '.';
156
157          elsif U_Id in Ada_Real_Time_Child then
158             Name_Buffer (14) := '.';
159
160          elsif U_Id in Ada_Streams_Child then
161             Name_Buffer (12) := '.';
162
163          elsif U_Id in Ada_Text_IO_Child then
164             Name_Buffer (12) := '.';
165
166          elsif U_Id in Ada_Wide_Text_IO_Child then
167             Name_Buffer (17) := '.';
168          end if;
169
170       elsif U_Id in Interfaces_Child then
171          Name_Buffer (11) := '.';
172
173       elsif U_Id in System_Child then
174          Name_Buffer (7) := '.';
175
176          if U_Id in System_Tasking_Child then
177             Name_Buffer (15) := '.';
178          end if;
179
180          if U_Id in System_Tasking_Restricted_Child then
181             Name_Buffer (26) := '.';
182          end if;
183
184          if U_Id in System_Tasking_Protected_Objects_Child then
185             Name_Buffer (33) := '.';
186          end if;
187
188          if U_Id in System_Tasking_Async_Delays_Child then
189             Name_Buffer (28) := '.';
190          end if;
191       end if;
192
193       --  Add %s at end for spec
194
195       Name_Buffer (Name_Len + 1) := '%';
196       Name_Buffer (Name_Len + 2) := 's';
197       Name_Len := Name_Len + 2;
198
199       return Name_Find;
200    end Get_Unit_Name;
201
202    ----------------
203    -- Initialize --
204    ----------------
205
206    procedure Initialize is
207    begin
208       --  Initialize the unit table
209
210       for J in RTU_Id loop
211          RT_Unit_Table (J).Entity := Empty;
212       end loop;
213
214       for J in RE_Id loop
215          RE_Table (J) := Empty;
216       end loop;
217    end Initialize;
218
219    ------------
220    -- Is_RTE --
221    ------------
222
223    function Is_RTE (Ent : Entity_Id; E : RE_Id) return Boolean is
224       E_Unit_Name   : Unit_Name_Type;
225       Ent_Unit_Name : Unit_Name_Type;
226
227       S  : Entity_Id;
228       E1 : Entity_Id;
229       E2 : Entity_Id;
230
231    begin
232       if No (Ent) then
233          return False;
234
235       --  If E has already a corresponding entity, check it directly,
236       --  going to full views if they exist to deal with the incomplete
237       --  and private type cases properly.
238
239       elsif Present (RE_Table (E)) then
240          E1 := Ent;
241
242          if Is_Type (E1) and then Present (Full_View (E1)) then
243             E1 := Full_View (E1);
244          end if;
245
246          E2 := RE_Table (E);
247
248          if Is_Type (E2) and then Present (Full_View (E2)) then
249             E2 := Full_View (E2);
250          end if;
251
252          return E1 = E2;
253       end if;
254
255       --  If the unit containing E is not loaded, we already know that
256       --  the entity we have cannot have come from this unit.
257
258       E_Unit_Name := Get_Unit_Name (RE_Unit_Table (E));
259
260       if not Is_Loaded (E_Unit_Name) then
261          return False;
262       end if;
263
264       --  Here the unit containing the entity is loaded. We have not made
265       --  an explicit call to RTE to get the entity in question, but we may
266       --  have obtained a reference to it indirectly from some other entity
267       --  in the same unit, or some other unit that references it.
268
269       --  Get the defining unit of the entity
270
271       S := Scope (Ent);
272
273       if Ekind (S) /= E_Package then
274          return False;
275       end if;
276
277       Ent_Unit_Name := Get_Unit_Name (Unit_Declaration_Node (S));
278
279       --  If the defining unit of the entity we are testing is not the
280       --  unit containing E, then they cannot possibly match.
281
282       if Ent_Unit_Name /= E_Unit_Name then
283          return False;
284       end if;
285
286       --  If the units match, then compare the names (remember that no
287       --  overloading is permitted in entities fetched using Rtsfind).
288
289       if RE_Chars (E) = Chars (Ent) then
290          RE_Table (E) := Ent;
291
292          --  If front-end inlining is enabled, we may be within a body that
293          --  contains inlined functions, which has not been retrieved through
294          --  rtsfind, and therefore is not yet recorded in the RT_Unit_Table.
295          --  Add the unit information now, it must be fully available.
296
297          declare
298             U : RT_Unit_Table_Record
299                   renames  RT_Unit_Table (RE_Unit_Table (E));
300          begin
301             if No (U.Entity) then
302                U.Entity := S;
303                U.Uname  := E_Unit_Name;
304                U.Unum   := Get_Source_Unit (S);
305             end if;
306          end;
307
308          return True;
309       else
310          return False;
311       end if;
312    end Is_RTE;
313
314    ----------------------------
315    -- Is_Text_IO_Kludge_Unit --
316    ----------------------------
317
318    function Is_Text_IO_Kludge_Unit (Nam : Node_Id) return Boolean is
319       Prf : Node_Id;
320       Sel : Node_Id;
321
322    begin
323       if Nkind (Nam) /= N_Expanded_Name then
324          return False;
325       end if;
326
327       Prf := Prefix (Nam);
328       Sel := Selector_Name (Nam);
329
330       if Nkind (Sel) /= N_Expanded_Name
331         or else Nkind (Prf) /= N_Identifier
332         or else Chars (Prf) /= Name_Ada
333       then
334          return False;
335       end if;
336
337       Prf := Prefix (Sel);
338       Sel := Selector_Name (Sel);
339
340       return
341         Nkind (Prf) = N_Identifier
342           and then
343         (Chars (Prf) = Name_Text_IO or else Chars (Prf) = Name_Wide_Text_IO)
344           and then
345         Nkind (Sel) = N_Identifier
346           and then
347         Chars (Sel) in Text_IO_Package_Name;
348
349    end Is_Text_IO_Kludge_Unit;
350
351    ---------------
352    -- Load_Fail --
353    ---------------
354
355    procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "") is
356    begin
357       Set_Standard_Error;
358
359       Write_Str ("fatal error: run-time library configuration error");
360       Write_Eol;
361
362       if Ent_Name /= "" then
363          Write_Str ("cannot locate """);
364
365          --  Copy name skipping initial RE_ or RO_XX characters
366
367          if Ent_Name (1 .. 2) = "RE" then
368             for J in 4 .. Ent_Name'Length loop
369                Name_Buffer (J - 3) := Ent_Name (J);
370             end loop;
371          else
372             for J in 7 .. Ent_Name'Length loop
373                Name_Buffer (J - 6) := Ent_Name (J);
374             end loop;
375          end if;
376
377          Name_Len := Ent_Name'Length - 3;
378          Set_Casing (Mixed_Case);
379          Write_Str (Name_Buffer (1 .. Name_Len));
380          Write_Str (""" in file """);
381
382       else
383          Write_Str ("cannot load file """);
384       end if;
385
386       Write_Name
387         (Get_File_Name (RT_Unit_Table (U_Id).Uname, Subunit => False));
388       Write_Str (""" (");
389       Write_Str (S);
390       Write_Char (')');
391       Write_Eol;
392       Set_Standard_Output;
393       raise Unrecoverable_Error;
394    end Load_Fail;
395
396    --------------
397    -- Load_RTU --
398    --------------
399
400    procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False) is
401       Loaded   : Boolean;
402       U        : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
403       Priv_Par : Elist_Id := New_Elmt_List;
404       Lib_Unit : Node_Id;
405
406       procedure Save_Private_Visibility;
407       --  If the current unit is the body of child unit or the spec of a
408       --  private child unit, the private declarations of the parent (s)
409       --  are visible. If the unit to be loaded is another public sibling,
410       --  its compilation will affect the visibility of the common ancestors.
411       --  Indicate those that must be restored.
412
413       procedure Restore_Private_Visibility;
414       --  Restore the visibility of ancestors after compiling RTU.
415
416       --------------------------------
417       -- Restore_Private_Visibility --
418       --------------------------------
419
420       procedure Restore_Private_Visibility is
421          E_Par : Elmt_Id;
422
423       begin
424          E_Par := First_Elmt (Priv_Par);
425
426          while Present (E_Par) loop
427             if not In_Private_Part (Node (E_Par)) then
428                Install_Private_Declarations (Node (E_Par));
429             end if;
430
431             Next_Elmt (E_Par);
432          end loop;
433       end Restore_Private_Visibility;
434
435       -----------------------------
436       -- Save_Private_Visibility --
437       -----------------------------
438
439       procedure Save_Private_Visibility is
440          Par : Entity_Id;
441
442       begin
443          Par := Scope (Current_Scope);
444
445          while Present (Par)
446            and then Par /= Standard_Standard
447          loop
448             if Ekind (Par) = E_Package
449               and then Is_Compilation_Unit (Par)
450               and then In_Private_Part (Par)
451             then
452                Append_Elmt (Par, Priv_Par);
453             end if;
454
455             Par := Scope (Par);
456          end loop;
457       end Save_Private_Visibility;
458
459    --  Start of processing for Load_RTU
460
461    begin
462       --  Nothing to do if unit is already loaded
463
464       if Present (U.Entity) then
465          return;
466       end if;
467
468       --  Otherwise we need to load the unit, First build unit name
469       --  from the enumeration literal name in type RTU_Id.
470
471       U.Uname  := Get_Unit_Name (U_Id);
472       U.Withed := False;
473       Loaded   := Is_Loaded (U.Uname);
474
475       --  Now do the load call, note that setting Error_Node to Empty is
476       --  a signal to Load_Unit that we will regard a failure to find the
477       --  file as a fatal error, and that it should not output any kind
478       --  of diagnostics, since we will take care of it here.
479
480       U.Unum :=
481         Load_Unit
482           (Load_Name  => U.Uname,
483            Required   => False,
484            Subunit    => False,
485            Error_Node => Empty);
486
487       if U.Unum = No_Unit then
488          Load_Fail ("unit not found", U_Id);
489
490       elsif Fatal_Error (U.Unum) then
491          Load_Fail ("parser errors", U_Id);
492       end if;
493
494       --  Make sure that the unit is analyzed
495
496       declare
497          Was_Analyzed : Boolean := Analyzed (Cunit (Current_Sem_Unit));
498
499       begin
500          --  Pretend that the current unit is analysed, in case it is
501          --  System or some such. This allows us to put some declarations,
502          --  such as exceptions and packed arrays of Boolean, into System
503          --  even though expanding them requires System...
504
505          --  This is a bit odd but works fine. If the RTS unit does not depend
506          --  in any way on the current unit, then it never gets back into the
507          --  current unit's tree, and the change we make to the current unit
508          --  tree is never noticed by anyone (it is undone in a moment). That
509          --  is the normal situation.
510
511          --  If the RTS Unit *does* depend on the current unit, for instance,
512          --  when you are compiling System, then you had better have finished
513          --  Analyzing the part of System that is depended on before you try
514          --  to load the RTS Unit. This means having the System ordered in an
515          --  appropriate manner.
516
517          Set_Analyzed (Cunit (Current_Sem_Unit), True);
518
519          if not Analyzed (Cunit (U.Unum)) then
520
521             Save_Private_Visibility;
522             Semantics (Cunit (U.Unum));
523             Restore_Private_Visibility;
524
525             if Fatal_Error (U.Unum) then
526                Load_Fail ("semantic errors", U_Id);
527             end if;
528          end if;
529
530          --  Undo the pretence
531
532          Set_Analyzed (Cunit (Current_Sem_Unit), Was_Analyzed);
533       end;
534
535       Lib_Unit := Unit (Cunit (U.Unum));
536       U.Entity := Defining_Entity (Lib_Unit);
537
538       if Use_Setting then
539          Set_Is_Potentially_Use_Visible (U.Entity, True);
540       end if;
541    end Load_RTU;
542
543    --------------
544    -- RE_Chars --
545    --------------
546
547    function RE_Chars (E : RE_Id) return Name_Id is
548       RE_Name_Chars : constant String := RE_Id'Image (E);
549
550    begin
551       --  Copy name skipping initial RE_ or RO_XX characters
552
553       if RE_Name_Chars (1 .. 2) = "RE" then
554          for J in 4 .. RE_Name_Chars'Last loop
555             Name_Buffer (J - 3) := Fold_Lower (RE_Name_Chars (J));
556          end loop;
557
558          Name_Len := RE_Name_Chars'Length - 3;
559
560       else
561          for J in 7 .. RE_Name_Chars'Last loop
562             Name_Buffer (J - 6) := Fold_Lower (RE_Name_Chars (J));
563          end loop;
564
565          Name_Len := RE_Name_Chars'Length - 6;
566       end if;
567
568       return Name_Find;
569    end RE_Chars;
570
571    ---------
572    -- RTE --
573    ---------
574
575    function RTE (E : RE_Id) return Entity_Id is
576       U_Id : constant RTU_Id := RE_Unit_Table (E);
577       U    : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
578
579       Lib_Unit : Node_Id;
580       Pkg_Ent  : Entity_Id;
581       Ename    : Name_Id;
582
583       Ravenscar : constant Boolean := Restricted_Profile;
584
585       --  The following flag is used to disable front-end inlining when RTE
586       --  is invoked. This prevents the analysis of other runtime bodies when
587       --  a particular spec is loaded through Rtsfind. This is both efficient,
588       --  and it prevents spurious visibility conflicts between use-visible
589       --  user entities, and entities in run-time packages.
590
591       --  In No_Run_Time mode, subprograms marked Inlined_Always must be
592       --  inlined, so in the case we retain the Front_End_Inlining mode.
593
594       Save_Front_End_Inlining : Boolean;
595
596       procedure Check_RPC;
597       --  Reject programs that make use of distribution features not supported
598       --  on the current target. On such targets (VMS, Vxworks, others?) we
599       --  only provide a minimal body for System.Rpc that only supplies an
600       --  implementation of partition_id.
601
602       function Find_Local_Entity (E : RE_Id) return Entity_Id;
603       --  This function is used when entity E is in this compilation's main
604       --  unit. It gets the value from the already compiled declaration.
605
606       function Make_Unit_Name (N : Node_Id) return Node_Id;
607       --  If the unit is a child unit, build fully qualified name for use
608       --  in with_clause.
609
610       ---------------
611       -- Check_RPC --
612       ---------------
613
614       procedure Check_RPC is
615          Body_Name    : Unit_Name_Type;
616          Unum         : Unit_Number_Type;
617
618       begin
619          --  Bypass this check if debug flag -gnatdR set
620
621          if Debug_Flag_RR then
622             return;
623          end if;
624
625          --  Otherwise we need the check if we are going after one of
626          --  the critical entities in System.RPC in stubs mode.
627
628          if (Distribution_Stub_Mode = Generate_Receiver_Stub_Body
629                       or else
630                         Distribution_Stub_Mode = Generate_Caller_Stub_Body)
631            and then (E = RE_Do_Rpc
632                        or else E = RE_Do_Apc
633                        or else E = RE_Params_Stream_Type
634                        or else E = RE_RPC_Receiver)
635          then
636             --  Load body of System.Rpc, and abort if this is the body that is
637             --  provided by GNAT, for which these features are not supported
638             --  on current target. We identify the gnat body by the presence
639             --  of a local entity called Gnat in the first declaration.
640
641             Lib_Unit := Unit (Cunit (U.Unum));
642             Body_Name := Get_Body_Name (Get_Unit_Name (Lib_Unit));
643             Unum :=
644               Load_Unit
645                 (Load_Name  => Body_Name,
646                  Required   => False,
647                  Subunit    => False,
648                  Error_Node => Empty,
649                  Renamings  => True);
650
651             if Unum /= No_Unit then
652                declare
653                   Decls : List_Id := Declarations (Unit (Cunit (Unum)));
654
655                begin
656                   if Present (Decls)
657                     and then Nkind (First (Decls)) = N_Object_Declaration
658                     and then
659                       Chars (Defining_Identifier (First (Decls))) = Name_Gnat
660                   then
661                      Set_Standard_Error;
662                      Write_Str ("distribution feature not supported");
663                      Write_Eol;
664                      raise Unrecoverable_Error;
665                   end if;
666                end;
667             end if;
668          end if;
669       end Check_RPC;
670
671       ------------------------
672       -- Find_System_Entity --
673       ------------------------
674
675       function Find_Local_Entity (E : RE_Id) return Entity_Id is
676          RE_Str : String renames RE_Id'Image (E);
677          Ent    : Entity_Id;
678
679          Save_Nam : constant String := Name_Buffer (1 .. Name_Len);
680          --  Save name buffer and length over call
681
682       begin
683          Name_Len := Natural'Max (0, RE_Str'Length - 3);
684          Name_Buffer (1 .. Name_Len) :=
685            RE_Str (RE_Str'First + 3 .. RE_Str'Last);
686
687          Ent := Entity_Id (Get_Name_Table_Info (Name_Find));
688
689          Name_Len := Save_Nam'Length;
690          Name_Buffer (1 .. Name_Len) := Save_Nam;
691
692          return Ent;
693       end Find_Local_Entity;
694
695       --------------------
696       -- Make_Unit_Name --
697       --------------------
698
699       function Make_Unit_Name (N : Node_Id) return Node_Id is
700          Nam  : Node_Id;
701          Scop : Entity_Id;
702
703       begin
704          Nam  := New_Reference_To (U.Entity, Standard_Location);
705          Scop := Scope (U.Entity);
706
707          if Nkind (N) = N_Defining_Program_Unit_Name then
708             while Scop /= Standard_Standard loop
709                Nam :=
710                  Make_Expanded_Name (Standard_Location,
711                    Chars  => Chars (U.Entity),
712                    Prefix => New_Reference_To (Scop, Standard_Location),
713                    Selector_Name => Nam);
714                Set_Entity (Nam, U.Entity);
715
716                Scop := Scope (Scop);
717             end loop;
718          end if;
719
720          return Nam;
721       end Make_Unit_Name;
722
723    --  Start of processing for RTE
724
725    begin
726
727       --  Check violation of no run time and ravenscar mode
728
729       if No_Run_Time
730         and then not OK_To_Use_In_No_Run_Time_Mode (U_Id)
731       then
732          if not Ravenscar
733            or else not OK_To_Use_In_Ravenscar_Mode (U_Id)
734          then
735             Disallow_In_No_Run_Time_Mode (Current_Error_Node);
736             return Empty;
737          end if;
738       end if;
739
740       --  Doing a rtsfind in system.ads is special, as we cannot do this
741       --  when compiling System itself. So if we are compiling system then
742       --  we should already have acquired and processed the declaration
743       --  of the entity. The test is to see if this compilation's main unit
744       --  is System. If so, return the value from the already compiled
745       --  declaration and otherwise do a regular find.
746
747       --  Not pleasant, but these kinds of annoying recursion when
748       --  writing an Ada compiler in Ada have to be broken somewhere!
749
750       if Present (Main_Unit_Entity)
751         and then Chars (Main_Unit_Entity) = Name_System
752         and then Analyzed (Main_Unit_Entity)
753         and then not Is_Child_Unit (Main_Unit_Entity)
754       then
755          return Find_Local_Entity (E);
756       end if;
757
758       Save_Front_End_Inlining := Front_End_Inlining;
759       Front_End_Inlining := No_Run_Time;
760
761       --  Load unit if unit not previously loaded
762
763       if No (RE_Table (E)) then
764          Load_RTU (U_Id);
765          Lib_Unit := Unit (Cunit (U.Unum));
766
767          --  In the subprogram case, we are all done, the entity we want
768          --  is the entity for the subprogram itself. Note that we do not
769          --  bother to check that it is the entity that was requested.
770          --  the only way that could fail to be the case is if runtime is
771          --  hopelessly misconfigured, and it isn't worth testing for this.
772
773          if Nkind (Lib_Unit) = N_Subprogram_Declaration then
774             RE_Table (E) := U.Entity;
775
776          --  Otherwise we must have the package case, and here we have to
777          --  search the package entity chain for the entity we want. The
778          --  entity we want must be present in this chain, or we have a
779          --  misconfigured runtime.
780
781          else
782             pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
783             Ename := RE_Chars (E);
784
785             Pkg_Ent := First_Entity (U.Entity);
786
787             while Present (Pkg_Ent) loop
788                if Ename = Chars (Pkg_Ent) then
789                   RE_Table (E) := Pkg_Ent;
790                   Check_RPC;
791                   goto Found;
792                end if;
793
794                Next_Entity (Pkg_Ent);
795             end loop;
796
797             --  If we didn't find the unit we want, something is wrong
798             --  although in no run time mode, we already gave a suitable
799             --  message, and so we simply return Empty, and the caller must
800             --  be prepared to handle this if the RTE call is otherwise
801             --  possible in high integrity mode.
802
803             if No_Run_Time
804               and then not OK_To_Use_In_No_Run_Time_Mode (U_Id)
805             then
806                Front_End_Inlining := Save_Front_End_Inlining;
807                return Empty;
808
809             else
810                Load_Fail ("entity not in package", U_Id,  RE_Id'Image (E));
811                raise Program_Error;
812             end if;
813          end if;
814       end if;
815
816       --  See if we have to generate a with for this entity. We generate
817       --  a with if the current unit is part of the extended main code
818       --  unit, and if we have not already added the with. The with is
819       --  added to the appropriate unit (the current one).
820
821    <<Found>>
822       if (not U.Withed)
823         and then
824           In_Extended_Main_Code_Unit (Cunit_Entity (Current_Sem_Unit))
825       then
826          U.Withed := True;
827
828          declare
829             Withn    : Node_Id;
830             Lib_Unit : Node_Id;
831
832          begin
833             Lib_Unit := Unit (Cunit (U.Unum));
834             Withn :=
835               Make_With_Clause (Standard_Location,
836                 Name =>
837                   Make_Unit_Name
838                     (Defining_Unit_Name (Specification (Lib_Unit))));
839             Set_Library_Unit          (Withn, Cunit (U.Unum));
840             Set_Corresponding_Spec    (Withn, U.Entity);
841             Set_First_Name            (Withn, True);
842             Set_Implicit_With         (Withn, True);
843
844             Mark_Rewrite_Insertion (Withn);
845             Append (Withn, Context_Items (Cunit (Current_Sem_Unit)));
846          end;
847       end if;
848
849       Front_End_Inlining := Save_Front_End_Inlining;
850       return RE_Table (E);
851    end RTE;
852
853    --------------------
854    -- Text_IO_Kludge --
855    --------------------
856
857    procedure Text_IO_Kludge (Nam : Node_Id) is
858       Chrs : Name_Id;
859
860       type Name_Map_Type is array (Text_IO_Package_Name) of RTU_Id;
861
862       Name_Map : Name_Map_Type := Name_Map_Type'(
863         Name_Decimal_IO     => Ada_Text_IO_Decimal_IO,
864         Name_Enumeration_IO => Ada_Text_IO_Enumeration_IO,
865         Name_Fixed_IO       => Ada_Text_IO_Fixed_IO,
866         Name_Float_IO       => Ada_Text_IO_Float_IO,
867         Name_Integer_IO     => Ada_Text_IO_Integer_IO,
868         Name_Modular_IO     => Ada_Text_IO_Modular_IO);
869
870       Wide_Name_Map : Name_Map_Type := Name_Map_Type'(
871         Name_Decimal_IO     => Ada_Wide_Text_IO_Decimal_IO,
872         Name_Enumeration_IO => Ada_Wide_Text_IO_Enumeration_IO,
873         Name_Fixed_IO       => Ada_Wide_Text_IO_Fixed_IO,
874         Name_Float_IO       => Ada_Wide_Text_IO_Float_IO,
875         Name_Integer_IO     => Ada_Wide_Text_IO_Integer_IO,
876         Name_Modular_IO     => Ada_Wide_Text_IO_Modular_IO);
877
878    begin
879       --  Nothing to do if name is not identifier or a selected component
880       --  whose selector_name is not an identifier.
881
882       if Nkind (Nam) = N_Identifier then
883          Chrs := Chars (Nam);
884
885       elsif Nkind (Nam) = N_Selected_Component
886         and then Nkind (Selector_Name (Nam)) = N_Identifier
887       then
888          Chrs := Chars (Selector_Name (Nam));
889
890       else
891          return;
892       end if;
893
894       --  Nothing to do if name is not one of the Text_IO subpackages
895       --  Otherwise look through loaded units, and if we find Text_IO
896       --  or Wide_Text_IO already loaded, then load the proper child.
897
898       if Chrs in Text_IO_Package_Name then
899          for U in Main_Unit .. Last_Unit loop
900             Get_Name_String (Unit_File_Name (U));
901
902             if Name_Len = 12 then
903
904                --  Here is where we do the loads if we find one of the
905                --  units Ada.Text_IO or Ada.Wide_Text_IO. An interesting
906                --  detail is that these units may already be used (i.e.
907                --  their In_Use flags may be set). Normally when the In_Use
908                --  flag is set, the Is_Potentially_Use_Visible flag of all
909                --  entities in the package is set, but the new entity we
910                --  are mysteriously adding was not there to have its flag
911                --  set at the time. So that's why we pass the extra parameter
912                --  to RTU_Find, to make sure the flag does get set now.
913                --  Given that those generic packages are in fact child units,
914                --  we must indicate that they are visible.
915
916                if Name_Buffer (1 .. 12) = "a-textio.ads" then
917                   Load_RTU (Name_Map (Chrs), In_Use (Cunit_Entity (U)));
918                   Set_Is_Visible_Child_Unit
919                     (RT_Unit_Table (Name_Map (Chrs)).Entity);
920
921                elsif Name_Buffer (1 .. 12) = "a-witeio.ads" then
922                   Load_RTU (Wide_Name_Map (Chrs), In_Use (Cunit_Entity (U)));
923                   Set_Is_Visible_Child_Unit
924                     (RT_Unit_Table (Wide_Name_Map (Chrs)).Entity);
925                end if;
926             end if;
927          end loop;
928       end if;
929    end Text_IO_Kludge;
930
931 end Rtsfind;