1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                              B I N D G E N                               --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 1992-2021, 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
26with Casing;   use Casing;
27with Fname;    use Fname;
28with Gnatvsn;  use Gnatvsn;
29with Hostparm;
30with Namet;    use Namet;
31with Opt;      use Opt;
32with Osint;    use Osint;
33with Osint.B;  use Osint.B;
34with Output;   use Output;
35with Rident;   use Rident;
36with Table;
37with Targparm; use Targparm;
38with Types;    use Types;
39
40with System.OS_Lib;
41with System.WCh_Con; use System.WCh_Con;
42
43with GNAT.Heap_Sort_A; use GNAT.Heap_Sort_A;
44with GNAT.HTable;
45
46package body Bindgen is
47   Statement_Buffer : String (1 .. 1000);
48   --  Buffer used for constructing output statements
49
50   Stm_Last : Natural := 0;
51   --  Stm_Last location in Statement_Buffer currently set
52
53   With_GNARL : Boolean := False;
54   --  Flag which indicates whether the program uses the GNARL library
55   --  (presence of the unit System.OS_Interface)
56
57   Num_Elab_Calls : Nat := 0;
58   --  Number of generated calls to elaboration routines
59
60   Num_Primary_Stacks : Int := 0;
61   --  Number of default-sized primary stacks the binder needs to allocate for
62   --  task objects declared in the program.
63
64   Num_Sec_Stacks : Int := 0;
65   --  Number of default-sized primary stacks the binder needs to allocate for
66   --  task objects declared in the program.
67
68   System_Restrictions_Used : Boolean := False;
69   --  Flag indicating whether the unit System.Restrictions is in the closure
70   --  of the partition. This is set by Resolve_Binder_Options, and is used
71   --  to determine whether or not to initialize the restrictions information
72   --  in the body of the binder generated file (we do not want to do this
73   --  unconditionally, since it drags in the System.Restrictions unit
74   --  unconditionally, which is unpleasand, especially for ZFP etc.)
75
76   Dispatching_Domains_Used : Boolean := False;
77   --  Flag indicating whether multiprocessor dispatching domains are used in
78   --  the closure of the partition. This is set by Resolve_Binder_Options, and
79   --  is used to call the routine to disallow the creation of new dispatching
80   --  domains just before calling the main procedure from the environment
81   --  task.
82
83   System_Secondary_Stack_Package_In_Closure : Boolean := False;
84   --  Flag indicating whether the unit System.Secondary_Stack is in the
85   --  closure of the partition. This is set by Resolve_Binder_Options, and
86   --  is used to initialize the package in cases where the run-time brings
87   --  in package but the secondary stack is not used.
88
89   System_Tasking_Restricted_Stages_Used : Boolean := False;
90   --  Flag indicating whether the unit System.Tasking.Restricted.Stages is in
91   --  the closure of the partition. This is set by Resolve_Binder_Options,
92   --  and it used to call a routine to active all the tasks at the end of
93   --  the elaboration when partition elaboration policy is sequential.
94
95   System_Interrupts_Used : Boolean := False;
96   --  Flag indicating whether the unit System.Interrups is in the closure of
97   --  the partition. This is set by Resolve_Binder_Options, and it used to
98   --  attach interrupt handlers at the end of the elaboration when partition
99   --  elaboration policy is sequential.
100
101   System_BB_CPU_Primitives_Multiprocessors_Used : Boolean := False;
102   --  Flag indicating whether unit System.BB.CPU_Primitives.Multiprocessors
103   --  is in the closure of the partition. This is set by procedure
104   --  Resolve_Binder_Options, and it is used to call a procedure that starts
105   --  slave processors.
106
107   System_Version_Control_Used : Boolean := False;
108   --  Flag indicating whether unit System.Version_Control is in the closure.
109   --  This unit is implicitly withed by the compiler when Version or
110   --  Body_Version attributes are used. If the package is not in the closure,
111   --  the version definitions can be removed.
112
113   Lib_Final_Built : Boolean := False;
114   --  Flag indicating whether the finalize_library rountine has been built
115
116   Bind_Env_String_Built : Boolean := False;
117   --  Flag indicating whether a bind environment string has been built
118
119   CodePeer_Wrapper_Name : constant String := "call_main_subprogram";
120   --  For CodePeer, introduce a wrapper subprogram which calls the
121   --  user-defined main subprogram.
122
123   ----------------------------------
124   -- Interface_State Pragma Table --
125   ----------------------------------
126
127   --  This table assembles the interface state pragma information from
128   --  all the units in the partition. Note that Bcheck has already checked
129   --  that the information is consistent across units. The entries
130   --  in this table are n/u/r/s for not set/user/runtime/system.
131
132   package IS_Pragma_Settings is new Table.Table
133     (Table_Component_Type => Character,
134      Table_Index_Type     => Int,
135      Table_Low_Bound      => 0,
136      Table_Initial        => 100,
137      Table_Increment      => 200,
138      Table_Name           => "IS_Pragma_Settings");
139
140   --  This table assembles the Priority_Specific_Dispatching pragma
141   --  information from all the units in the partition. Note that Bcheck has
142   --  already checked that the information is consistent across units.
143   --  The entries in this table are the upper case first character of the
144   --  policy name, e.g. 'F' for FIFO_Within_Priorities.
145
146   package PSD_Pragma_Settings is new Table.Table
147     (Table_Component_Type => Character,
148      Table_Index_Type     => Int,
149      Table_Low_Bound      => 0,
150      Table_Initial        => 100,
151      Table_Increment      => 200,
152      Table_Name           => "PSD_Pragma_Settings");
153
154   ----------------------------
155   -- Bind_Environment Table --
156   ----------------------------
157
158   subtype Header_Num is Int range 0 .. 36;
159
160   function Hash (Nam : Name_Id) return Header_Num;
161
162   package Bind_Environment is new GNAT.HTable.Simple_HTable
163     (Header_Num => Header_Num,
164      Element    => Name_Id,
165      No_Element => No_Name,
166      Key        => Name_Id,
167      Hash       => Hash,
168      Equal      => "=");
169
170   ----------------------
171   -- Run-Time Globals --
172   ----------------------
173
174   --  This section documents the global variables that are set from the
175   --  generated binder file.
176
177   --     Main_Priority                 : Integer;
178   --     Time_Slice_Value              : Integer;
179   --     Heap_Size                     : Natural;
180   --     WC_Encoding                   : Character;
181   --     Locking_Policy                : Character;
182   --     Queuing_Policy                : Character;
183   --     Task_Dispatching_Policy       : Character;
184   --     Priority_Specific_Dispatching : System.Address;
185   --     Num_Specific_Dispatching      : Integer;
186   --     Restrictions                  : System.Address;
187   --     Interrupt_States              : System.Address;
188   --     Num_Interrupt_States          : Integer;
189   --     Unreserve_All_Interrupts      : Integer;
190   --     Exception_Tracebacks          : Integer;
191   --     Exception_Tracebacks_Symbolic : Integer;
192   --     Detect_Blocking               : Integer;
193   --     Default_Stack_Size            : Integer;
194   --     Default_Secondary_Stack_Size  : System.Parameters.Size_Type;
195   --     Leap_Seconds_Support          : Integer;
196   --     Main_CPU                      : Integer;
197   --     Default_Sized_SS_Pool         : System.Address;
198   --     Binder_Sec_Stacks_Count       : Natural;
199   --     XDR_Stream                    : Integer;
200
201   --  Main_Priority is the priority value set by pragma Priority in the main
202   --  program. If no such pragma is present, the value is -1.
203
204   --  Time_Slice_Value is the time slice value set by pragma Time_Slice in the
205   --  main program, or by the use of a -Tnnn parameter for the binder (if both
206   --  are present, the binder value overrides). The value is in milliseconds.
207   --  A value of zero indicates that time slicing should be suppressed. If no
208   --  pragma is present, and no -T switch was used, the value is -1.
209
210   --  WC_Encoding shows the wide character encoding method used for the main
211   --  program. This is one of the encoding letters defined in
212   --  System.WCh_Con.WC_Encoding_Letters.
213
214   --  Locking_Policy is a space if no locking policy was specified for the
215   --  partition. If a locking policy was specified, the value is the upper
216   --  case first character of the locking policy name, for example, 'C' for
217   --  Ceiling_Locking.
218
219   --  Queuing_Policy is a space if no queuing policy was specified for the
220   --  partition. If a queuing policy was specified, the value is the upper
221   --  case first character of the queuing policy name for example, 'F' for
222   --  FIFO_Queuing.
223
224   --  Task_Dispatching_Policy is a space if no task dispatching policy was
225   --  specified for the partition. If a task dispatching policy was specified,
226   --  the value is the upper case first character of the policy name, e.g. 'F'
227   --  for FIFO_Within_Priorities.
228
229   --  Priority_Specific_Dispatching is the address of a string used to store
230   --  the task dispatching policy specified for the different priorities in
231   --  the partition. The length of this string is determined by the last
232   --  priority for which such a pragma applies (the string will be a null
233   --  string if no specific dispatching policies were used). If pragma were
234   --  present, the entries apply to the priorities in sequence from the first
235   --  priority. The value stored is the upper case first character of the
236   --  policy name, or 'F' (for FIFO_Within_Priorities) as the default value
237   --  for those priority ranges not specified.
238
239   --  Num_Specific_Dispatching is length of the Priority_Specific_Dispatching
240   --  string. It will be set to zero if no Priority_Specific_Dispatching
241   --  pragmas are present.
242
243   --  Restrictions is the address of a null-terminated string specifying the
244   --  restrictions information for the partition. The format is identical to
245   --  that of the parameter string found on R lines in ali files (see Lib.Writ
246   --  spec in lib-writ.ads for full details). The difference is that in this
247   --  context the values are the cumulative ones for the entire partition.
248
249   --  Interrupt_States is the address of a string used to specify the
250   --  cumulative results of Interrupt_State pragmas used in the partition.
251   --  The length of this string is determined by the last interrupt for which
252   --  such a pragma is given (the string will be a null string if no pragmas
253   --  were used). If pragma were present the entries apply to the interrupts
254   --  in sequence from the first interrupt, and are set to one of four
255   --  possible settings: 'n' for not specified, 'u' for user, 'r' for run
256   --  time, 's' for system, see description of Interrupt_State pragma for
257   --  further details.
258
259   --  Num_Interrupt_States is the length of the Interrupt_States string. It
260   --  will be set to zero if no Interrupt_State pragmas are present.
261
262   --  Unreserve_All_Interrupts is set to one if at least one unit in the
263   --  partition had a pragma Unreserve_All_Interrupts, and zero otherwise.
264
265   --  Exception_Tracebacks is set to one if the -Ea or -E parameter was
266   --  present in the bind and to zero otherwise. Note that on some targets
267   --  exception tracebacks are provided by default, so a value of zero for
268   --  this parameter does not necessarily mean no trace backs are available.
269
270   --  Exception_Tracebacks_Symbolic is set to one if the -Es parameter was
271   --  present in the bind and to zero otherwise.
272
273   --  Detect_Blocking indicates whether pragma Detect_Blocking is active or
274   --  not. A value of zero indicates that the pragma is not present, while a
275   --  value of 1 signals its presence in the partition.
276
277   --  Default_Stack_Size is the default stack size used when creating an Ada
278   --  task with no explicit Storage_Size clause.
279
280   --  Default_Secondary_Stack_Size is the default secondary stack size used
281   --  when creating an Ada task with no explicit Secondary_Stack_Size clause.
282
283   --  Leap_Seconds_Support denotes whether leap seconds have been enabled or
284   --  disabled. A value of zero indicates that leap seconds are turned "off",
285   --  while a value of one signifies "on" status.
286
287   --  Main_CPU is the processor set by pragma CPU in the main program. If no
288   --  such pragma is present, the value is -1.
289
290   --  Default_Sized_SS_Pool is set to the address of the default-sized
291   --  secondary stacks array generated by the binder. This pool of stacks is
292   --  generated when either the restriction No_Implicit_Heap_Allocations
293   --  or No_Implicit_Task_Allocations is active.
294
295   --  Binder_Sec_Stacks_Count is the number of generated secondary stacks in
296   --  the Default_Sized_SS_Pool.
297
298   --  XDR_Stream indicates whether streaming should be performed using the
299   --  XDR protocol. A value of one indicates that XDR streaming is enabled.
300
301   procedure WBI (Info : String) renames Osint.B.Write_Binder_Info;
302   --  Convenient shorthand used throughout
303
304   -----------------------
305   -- Local Subprograms --
306   -----------------------
307
308   procedure Gen_Adainit (Elab_Order : Unit_Id_Array);
309   --  Generates the Adainit procedure
310
311   procedure Gen_Adafinal;
312   --  Generate the Adafinal procedure
313
314   procedure Gen_Bind_Env_String;
315   --  Generate the bind environment buffer
316
317   procedure Gen_CodePeer_Wrapper;
318   --  For CodePeer, generate wrapper which calls user-defined main subprogram
319
320   procedure Gen_Elab_Calls (Elab_Order : Unit_Id_Array);
321   --  Generate sequence of elaboration calls
322
323   procedure Gen_Elab_Externals (Elab_Order : Unit_Id_Array);
324   --  Generate sequence of external declarations for elaboration
325
326   procedure Gen_Elab_Order (Elab_Order : Unit_Id_Array);
327   --  Generate comments showing elaboration order chosen
328
329   procedure Gen_Finalize_Library (Elab_Order : Unit_Id_Array);
330   --  Generate a sequence of finalization calls to elaborated packages
331
332   procedure Gen_Main;
333   --  Generate procedure main
334
335   procedure Gen_Object_Files_Options (Elab_Order : Unit_Id_Array);
336   --  Output comments containing a list of the full names of the object
337   --  files to be linked and the list of linker options supplied by
338   --  Linker_Options pragmas in the source.
339
340   procedure Gen_Output_File_Ada
341     (Filename   : String;
342      Elab_Order : Unit_Id_Array);
343   --  Generate Ada output file
344
345   procedure Gen_Restrictions;
346   --  Generate initialization of restrictions variable
347
348   procedure Gen_Versions;
349   --  Output series of definitions for unit versions
350
351   function Get_Ada_Main_Name return String;
352   --  This function is used for the Ada main output to compute a usable name
353   --  for the generated main program. The normal main program name is
354   --  Ada_Main, but this won't work if the user has a unit with this name.
355   --  This function tries Ada_Main first, and if there is such a clash, then
356   --  it tries Ada_Name_01, Ada_Name_02 ... Ada_Name_99 in sequence.
357
358   function Get_Main_Unit_Name (S : String) return String;
359   --  Return the main unit name corresponding to S by replacing '.' with '_'
360
361   function Get_Main_Name return String;
362   --  This function is used in the main output case to compute the correct
363   --  external main program. It is "main" by default, unless the flag
364   --  Use_Ada_Main_Program_Name_On_Target is set, in which case it is the name
365   --  of the Ada main name without the "_ada". This default can be overridden
366   --  explicitly using the -Mname binder switch.
367
368   function Get_WC_Encoding return Character;
369   --  Return wide character encoding method to set as WC_Encoding in output.
370   --  If -W has been used, returns the specified encoding, otherwise returns
371   --  the encoding method used for the main program source. If there is no
372   --  main program source (-z switch used), returns brackets ('b').
373
374   function Has_Finalizer (Elab_Order : Unit_Id_Array) return Boolean;
375   --  Determine whether the current unit has at least one library-level
376   --  finalizer.
377
378   function Lt_Linker_Option (Op1 : Natural; Op2 : Natural) return Boolean;
379   --  Compare linker options, when sorting, first according to
380   --  Is_Internal_File (internal files come later) and then by
381   --  elaboration order position (latest to earliest).
382
383   procedure Move_Linker_Option (From : Natural; To : Natural);
384   --  Move routine for sorting linker options
385
386   procedure Resolve_Binder_Options (Elab_Order : Unit_Id_Array);
387   --  Set the value of With_GNARL
388
389   procedure Set_Char (C : Character);
390   --  Set given character in Statement_Buffer at the Stm_Last + 1 position
391   --  and increment Stm_Last by one to reflect the stored character.
392
393   procedure Set_Int (N : Int);
394   --  Set given value in decimal in Statement_Buffer with no spaces starting
395   --  at the Stm_Last + 1 position, and updating Stm_Last past the value. A
396   --  minus sign is output for a negative value.
397
398   procedure Set_Boolean (B : Boolean);
399   --  Set given boolean value in Statement_Buffer at the Stm_Last + 1 position
400   --  and update Stm_Last past the value.
401
402   procedure Set_IS_Pragma_Table;
403   --  Initializes contents of IS_Pragma_Settings table from ALI table
404
405   procedure Set_Main_Program_Name;
406   --  Given the main program name in Name_Buffer (length in Name_Len) generate
407   --  the name of the routine to be used in the call. The name is generated
408   --  starting at Stm_Last + 1, and Stm_Last is updated past it.
409
410   procedure Set_Name_Buffer;
411   --  Set the value stored in positions 1 .. Name_Len of the Name_Buffer
412
413   procedure Set_PSD_Pragma_Table;
414   --  Initializes contents of PSD_Pragma_Settings table from ALI table
415
416   procedure Set_String (S : String);
417   --  Sets characters of given string in Statement_Buffer, starting at the
418   --  Stm_Last + 1 position, and updating last past the string value.
419
420   procedure Set_String_Replace (S : String);
421   --  Replaces the last S'Length characters in the Statement_Buffer with the
422   --  characters of S. The caller must ensure that these characters do in fact
423   --  exist in the Statement_Buffer.
424
425   procedure Set_Unit_Name;
426   --  Given a unit name in the Name_Buffer, copy it into Statement_Buffer,
427   --  starting at the Stm_Last + 1 position and update Stm_Last past the
428   --  value. Each dot (.) will be qualified into double underscores (__).
429
430   procedure Set_Unit_Number (U : Unit_Id);
431   --  Sets unit number (first unit is 1, leading zeroes output to line up all
432   --  output unit numbers nicely as required by the value, and by the total
433   --  number of units.
434
435   procedure Write_Statement_Buffer;
436   --  Write out contents of statement buffer up to Stm_Last, and reset
437   --  Stm_Last to 0.
438
439   procedure Write_Statement_Buffer (S : String);
440   --  First writes its argument (using Set_String (S)), then writes out the
441   --  contents of statement buffer up to Stm_Last, and resets Stm_Last to 0.
442
443   procedure Write_Bind_Line (S : String);
444   --  Write S (an LF-terminated string) to the binder file (for use with
445   --  Set_Special_Output).
446
447   ------------------
448   -- Gen_Adafinal --
449   ------------------
450
451   procedure Gen_Adafinal is
452   begin
453      WBI ("   procedure " & Ada_Final_Name.all & " is");
454
455      --  Call s_stalib_adafinal to await termination of tasks and so on. We
456      --  want to do this if there is a main program, either in Ada or in some
457      --  other language. (Note that Bind_Main_Program is True for Ada mains,
458      --  but False for mains in other languages.) We do not want to do this if
459      --  we're binding a library.
460
461      if not Bind_For_Library and not CodePeer_Mode then
462         WBI ("      procedure s_stalib_adafinal;");
463         Set_String ("      pragma Import (Ada, s_stalib_adafinal, ");
464         Set_String ("""system__standard_library__adafinal"");");
465         Write_Statement_Buffer;
466      end if;
467
468      WBI ("");
469      WBI ("      procedure Runtime_Finalize;");
470      WBI ("      pragma Import (C, Runtime_Finalize, " &
471             """__gnat_runtime_finalize"");");
472      WBI ("");
473      WBI ("   begin");
474
475      if not CodePeer_Mode then
476         WBI ("      if not Is_Elaborated then");
477         WBI ("         return;");
478         WBI ("      end if;");
479         WBI ("      Is_Elaborated := False;");
480      end if;
481
482      WBI ("      Runtime_Finalize;");
483
484      --  By default (real targets), finalization is done differently depending
485      --  on whether this is the main program or a library.
486
487      if not CodePeer_Mode then
488         if not Bind_For_Library then
489            WBI ("      s_stalib_adafinal;");
490         elsif Lib_Final_Built then
491            WBI ("      finalize_library;");
492         else
493            WBI ("      null;");
494         end if;
495
496      --  Pragma Import C cannot be used on virtual targets, therefore call the
497      --  runtime finalization routine directly in CodePeer mode, where
498      --  imported functions are ignored.
499
500      else
501         WBI ("      System.Standard_Library.Adafinal;");
502      end if;
503
504      WBI ("   end " & Ada_Final_Name.all & ";");
505      WBI ("");
506   end Gen_Adafinal;
507
508   -----------------
509   -- Gen_Adainit --
510   -----------------
511
512   procedure Gen_Adainit (Elab_Order : Unit_Id_Array) is
513      Main_Priority : Int renames ALIs.Table (ALIs.First).Main_Priority;
514      Main_CPU      : Int renames ALIs.Table (ALIs.First).Main_CPU;
515
516   begin
517      --  Declare the access-to-subprogram type used for initialization of
518      --  of __gnat_finalize_library_objects. This is declared at library
519      --  level for compatibility with the type used in System.Soft_Links.
520      --  The import of the soft link which performs library-level object
521      --  finalization does not work for CodePeer, so regular Ada is used in
522      --  that case. For restricted run-time libraries (ZFP and Ravenscar)
523      --  tasks are non-terminating, so we do not want finalization.
524
525      if not Suppress_Standard_Library_On_Target
526        and then not CodePeer_Mode
527        and then not Configurable_Run_Time_On_Target
528      then
529         WBI ("   type No_Param_Proc is access procedure;");
530         WBI ("   pragma Favor_Top_Level (No_Param_Proc);");
531         WBI ("");
532      end if;
533
534      WBI ("   procedure " & Ada_Init_Name.all & " is");
535
536      --  In CodePeer mode, simplify adainit procedure by only calling
537      --  elaboration procedures.
538
539      if CodePeer_Mode then
540         WBI ("   begin");
541
542      --  If the standard library is suppressed, then the only global variables
543      --  that might be needed (by the Ravenscar profile) are the priority and
544      --  the processor for the environment task.
545
546      elsif Suppress_Standard_Library_On_Target then
547         if Main_Priority /= No_Main_Priority then
548            WBI ("      Main_Priority : Integer;");
549            WBI ("      pragma Import (C, Main_Priority," &
550                 " ""__gl_main_priority"");");
551            WBI ("");
552         end if;
553
554         if Main_CPU /= No_Main_CPU then
555            WBI ("      Main_CPU : Integer;");
556            WBI ("      pragma Import (C, Main_CPU," &
557                 " ""__gl_main_cpu"");");
558            WBI ("");
559         end if;
560
561         if System_Interrupts_Used
562           and then Partition_Elaboration_Policy_Specified = 'S'
563         then
564            WBI ("      procedure Install_Restricted_Handlers_Sequential;");
565            WBI ("      pragma Import (C," &
566                 "Install_Restricted_Handlers_Sequential," &
567                 " ""__gnat_attach_all_handlers"");");
568            WBI ("");
569         end if;
570
571         if System_Tasking_Restricted_Stages_Used
572           and then Partition_Elaboration_Policy_Specified = 'S'
573         then
574            WBI ("      Partition_Elaboration_Policy : Character;");
575            WBI ("      pragma Import (C, Partition_Elaboration_Policy," &
576                 " ""__gnat_partition_elaboration_policy"");");
577            WBI ("");
578            WBI ("      procedure Activate_All_Tasks_Sequential;");
579            WBI ("      pragma Import (C, Activate_All_Tasks_Sequential," &
580                 " ""__gnat_activate_all_tasks"");");
581            WBI ("");
582         end if;
583
584         if System_BB_CPU_Primitives_Multiprocessors_Used then
585            WBI ("      procedure Start_Slave_CPUs;");
586            WBI ("      pragma Import (C, Start_Slave_CPUs," &
587                 " ""__gnat_start_slave_cpus"");");
588            WBI ("");
589         end if;
590
591         --  Import the default stack object if a size has been provided to the
592         --  binder.
593
594         if Opt.Default_Stack_Size /= Opt.No_Stack_Size then
595            WBI ("      Default_Stack_Size : Integer;");
596            WBI ("      pragma Import (C, Default_Stack_Size, " &
597                 """__gl_default_stack_size"");");
598         end if;
599
600         --  Initialize stack limit variable of the environment task if the
601         --  stack check method is stack limit and stack check is enabled.
602
603         if Stack_Check_Limits_On_Target
604           and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
605         then
606            WBI ("");
607            WBI ("      procedure Initialize_Stack_Limit;");
608            WBI ("      pragma Import (C, Initialize_Stack_Limit, " &
609                 """__gnat_initialize_stack_limit"");");
610         end if;
611
612         if System_Secondary_Stack_Package_In_Closure then
613            --  System.Secondary_Stack is in the closure of the program
614            --  because the program uses the secondary stack or the restricted
615            --  run-time is unconditionally calling SS_Init. In both cases,
616            --  SS_Init needs to know the number of secondary stacks created by
617            --  the binder.
618
619            WBI ("      Binder_Sec_Stacks_Count : Natural;");
620            WBI ("      pragma Import (Ada, Binder_Sec_Stacks_Count, " &
621                 """__gnat_binder_ss_count"");");
622            WBI ("");
623
624            --  Import secondary stack pool variables if the secondary stack
625            --  used. They are not referenced otherwise.
626
627            if Sec_Stack_Used then
628               WBI ("      Default_Secondary_Stack_Size : " &
629                    "System.Parameters.Size_Type;");
630               WBI ("      pragma Import (C, Default_Secondary_Stack_Size, " &
631                    """__gnat_default_ss_size"");");
632
633               WBI ("      Default_Sized_SS_Pool : System.Address;");
634               WBI ("      pragma Import (Ada, Default_Sized_SS_Pool, " &
635                    """__gnat_default_ss_pool"");");
636
637               WBI ("");
638            end if;
639         end if;
640
641         WBI ("   begin");
642
643         --  Set the default stack size if provided to the binder
644
645         if Opt.Default_Stack_Size /= Opt.No_Stack_Size then
646            Set_String ("      Default_Stack_Size := ");
647            Set_Int (Default_Stack_Size);
648            Set_String (";");
649            Write_Statement_Buffer;
650         end if;
651
652         if Main_Priority /= No_Main_Priority then
653            Set_String ("      Main_Priority := ");
654            Set_Int    (Main_Priority);
655            Set_Char   (';');
656            Write_Statement_Buffer;
657         end if;
658
659         if Main_CPU /= No_Main_CPU then
660            Set_String ("      Main_CPU := ");
661            Set_Int    (Main_CPU);
662            Set_Char   (';');
663            Write_Statement_Buffer;
664         end if;
665
666         if System_Tasking_Restricted_Stages_Used
667           and then Partition_Elaboration_Policy_Specified = 'S'
668         then
669            Set_String ("      Partition_Elaboration_Policy := '");
670            Set_Char   (Partition_Elaboration_Policy_Specified);
671            Set_String ("';");
672            Write_Statement_Buffer;
673         end if;
674
675         if Main_Priority = No_Main_Priority
676           and then Opt.Default_Stack_Size = Opt.No_Stack_Size
677           and then Main_CPU = No_Main_CPU
678           and then not System_Tasking_Restricted_Stages_Used
679         then
680            WBI ("      null;");
681         end if;
682
683         --  Generate the default-sized secondary stack pool if the secondary
684         --  stack is used by the program.
685
686         if System_Secondary_Stack_Package_In_Closure then
687            if Sec_Stack_Used then
688               --  Elaborate the body of the binder to initialize the default-
689               --  sized secondary stack pool.
690
691               WBI ("");
692               WBI ("      " & Get_Ada_Main_Name & "'Elab_Body;");
693
694               --  Generate the default-sized secondary stack pool and set the
695               --  related secondary stack globals.
696
697               Set_String ("      Default_Secondary_Stack_Size := ");
698
699               if Opt.Default_Sec_Stack_Size /= Opt.No_Stack_Size then
700                  Set_Int (Opt.Default_Sec_Stack_Size);
701               else
702                  Set_String
703                    ("System.Parameters.Runtime_Default_Sec_Stack_Size");
704               end if;
705
706               Set_Char (';');
707               Write_Statement_Buffer;
708
709               Set_String ("      Binder_Sec_Stacks_Count := ");
710               Set_Int (Num_Sec_Stacks);
711               Set_Char (';');
712               Write_Statement_Buffer;
713
714               WBI ("      Default_Sized_SS_Pool := " &
715                      "Sec_Default_Sized_Stacks'Address;");
716               WBI ("");
717
718            else
719               --  The presence of System.Secondary_Stack in the closure of the
720               --  program implies the restricted run-time is unconditionally
721               --  calling SS_Init. Let SS_Init know that no stacks were
722               --  created.
723
724               WBI ("      Binder_Sec_Stacks_Count := 0;");
725            end if;
726         end if;
727
728      --  Normal case (standard library not suppressed). Set all global values
729      --  used by the run time.
730
731      else
732         WBI ("      Main_Priority : Integer;");
733         WBI ("      pragma Import (C, Main_Priority, " &
734              """__gl_main_priority"");");
735         WBI ("      Time_Slice_Value : Integer;");
736         WBI ("      pragma Import (C, Time_Slice_Value, " &
737              """__gl_time_slice_val"");");
738         WBI ("      WC_Encoding : Character;");
739         WBI ("      pragma Import (C, WC_Encoding, ""__gl_wc_encoding"");");
740         WBI ("      Locking_Policy : Character;");
741         WBI ("      pragma Import (C, Locking_Policy, " &
742              """__gl_locking_policy"");");
743         WBI ("      Queuing_Policy : Character;");
744         WBI ("      pragma Import (C, Queuing_Policy, " &
745              """__gl_queuing_policy"");");
746         WBI ("      Task_Dispatching_Policy : Character;");
747         WBI ("      pragma Import (C, Task_Dispatching_Policy, " &
748              """__gl_task_dispatching_policy"");");
749         WBI ("      Priority_Specific_Dispatching : System.Address;");
750         WBI ("      pragma Import (C, Priority_Specific_Dispatching, " &
751              """__gl_priority_specific_dispatching"");");
752         WBI ("      Num_Specific_Dispatching : Integer;");
753         WBI ("      pragma Import (C, Num_Specific_Dispatching, " &
754              """__gl_num_specific_dispatching"");");
755         WBI ("      Main_CPU : Integer;");
756         WBI ("      pragma Import (C, Main_CPU, " &
757              """__gl_main_cpu"");");
758
759         WBI ("      Interrupt_States : System.Address;");
760         WBI ("      pragma Import (C, Interrupt_States, " &
761              """__gl_interrupt_states"");");
762         WBI ("      Num_Interrupt_States : Integer;");
763         WBI ("      pragma Import (C, Num_Interrupt_States, " &
764              """__gl_num_interrupt_states"");");
765         WBI ("      Unreserve_All_Interrupts : Integer;");
766         WBI ("      pragma Import (C, Unreserve_All_Interrupts, " &
767              """__gl_unreserve_all_interrupts"");");
768
769         if Exception_Tracebacks or Exception_Tracebacks_Symbolic then
770            WBI ("      Exception_Tracebacks : Integer;");
771            WBI ("      pragma Import (C, Exception_Tracebacks, " &
772                 """__gl_exception_tracebacks"");");
773
774            if Exception_Tracebacks_Symbolic then
775               WBI ("      Exception_Tracebacks_Symbolic : Integer;");
776               WBI ("      pragma Import (C, Exception_Tracebacks_Symbolic, " &
777                    """__gl_exception_tracebacks_symbolic"");");
778            end if;
779         end if;
780
781         WBI ("      Detect_Blocking : Integer;");
782         WBI ("      pragma Import (C, Detect_Blocking, " &
783              """__gl_detect_blocking"");");
784         WBI ("      Default_Stack_Size : Integer;");
785         WBI ("      pragma Import (C, Default_Stack_Size, " &
786              """__gl_default_stack_size"");");
787
788         if Sec_Stack_Used then
789            WBI ("      Default_Secondary_Stack_Size : " &
790                 "System.Parameters.Size_Type;");
791            WBI ("      pragma Import (C, Default_Secondary_Stack_Size, " &
792                 """__gnat_default_ss_size"");");
793         end if;
794
795         if Leap_Seconds_Support then
796            WBI ("      Leap_Seconds_Support : Integer;");
797            WBI ("      pragma Import (C, Leap_Seconds_Support, " &
798                 """__gl_leap_seconds_support"");");
799         end if;
800
801         WBI ("      Bind_Env_Addr : System.Address;");
802         WBI ("      pragma Import (C, Bind_Env_Addr, " &
803              """__gl_bind_env_addr"");");
804
805         if XDR_Stream then
806            WBI ("      XDR_Stream : Integer;");
807            WBI ("      pragma Import (C, XDR_Stream, ""__gl_xdr_stream"");");
808         end if;
809
810         --  Import entry point for elaboration time signal handler
811         --  installation, and indication of if it's been called previously.
812
813         WBI ("");
814         WBI ("      procedure Runtime_Initialize " &
815              "(Install_Handler : Integer);");
816         WBI ("      pragma Import (C, Runtime_Initialize, " &
817              """__gnat_runtime_initialize"");");
818
819         --  Import handlers attach procedure for sequential elaboration policy
820
821         if System_Interrupts_Used
822           and then Partition_Elaboration_Policy_Specified = 'S'
823         then
824            WBI ("      procedure Install_Restricted_Handlers_Sequential;");
825            WBI ("      pragma Import (C," &
826                 "Install_Restricted_Handlers_Sequential," &
827                 " ""__gnat_attach_all_handlers"");");
828            WBI ("");
829         end if;
830
831         --  Import task activation procedure for sequential elaboration
832         --  policy.
833
834         if System_Tasking_Restricted_Stages_Used
835           and then Partition_Elaboration_Policy_Specified = 'S'
836         then
837            WBI ("      Partition_Elaboration_Policy : Character;");
838            WBI ("      pragma Import (C, Partition_Elaboration_Policy," &
839                 " ""__gnat_partition_elaboration_policy"");");
840            WBI ("");
841            WBI ("      procedure Activate_All_Tasks_Sequential;");
842            WBI ("      pragma Import (C, Activate_All_Tasks_Sequential," &
843                 " ""__gnat_activate_all_tasks"");");
844         end if;
845
846         --  Import procedure to start slave cpus for bareboard runtime
847
848         if System_BB_CPU_Primitives_Multiprocessors_Used then
849            WBI ("      procedure Start_Slave_CPUs;");
850            WBI ("      pragma Import (C, Start_Slave_CPUs," &
851                 " ""__gnat_start_slave_cpus"");");
852         end if;
853
854         --  For restricted run-time libraries (ZFP and Ravenscar)
855         --  tasks are non-terminating, so we do not want finalization.
856
857         if not Configurable_Run_Time_On_Target then
858            WBI ("");
859            WBI ("      Finalize_Library_Objects : No_Param_Proc;");
860            WBI ("      pragma Import (C, Finalize_Library_Objects, " &
861                 """__gnat_finalize_library_objects"");");
862         end if;
863
864         --  Initialize stack limit variable of the environment task if the
865         --  stack check method is stack limit and stack check is enabled.
866
867         if Stack_Check_Limits_On_Target
868           and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
869         then
870            WBI ("");
871            WBI ("      procedure Initialize_Stack_Limit;");
872            WBI ("      pragma Import (C, Initialize_Stack_Limit, " &
873                 """__gnat_initialize_stack_limit"");");
874         end if;
875
876         --  When dispatching domains are used then we need to signal it
877         --  before calling the main procedure.
878
879         if Dispatching_Domains_Used then
880            WBI ("      procedure Freeze_Dispatching_Domains;");
881            WBI ("      pragma Import");
882            WBI ("        (Ada, Freeze_Dispatching_Domains, "
883                 & """__gnat_freeze_dispatching_domains"");");
884         end if;
885
886         --  Secondary stack global variables
887
888         WBI ("      Binder_Sec_Stacks_Count : Natural;");
889         WBI ("      pragma Import (Ada, Binder_Sec_Stacks_Count, " &
890              """__gnat_binder_ss_count"");");
891
892         WBI ("      Default_Sized_SS_Pool : System.Address;");
893         WBI ("      pragma Import (Ada, Default_Sized_SS_Pool, " &
894              """__gnat_default_ss_pool"");");
895
896         WBI ("");
897
898         --  Start of processing for Adainit
899
900         WBI ("   begin");
901         WBI ("      if Is_Elaborated then");
902         WBI ("         return;");
903         WBI ("      end if;");
904         WBI ("      Is_Elaborated := True;");
905
906         --  Call System.Elaboration_Allocators.Mark_Start_Of_Elaboration if
907         --  restriction No_Standard_Allocators_After_Elaboration is active.
908
909         if Cumulative_Restrictions.Set
910              (No_Standard_Allocators_After_Elaboration)
911         then
912            WBI ("      System.Elaboration_Allocators."
913                 & "Mark_Start_Of_Elaboration;");
914         end if;
915
916         --  Generate assignments to initialize globals
917
918         Set_String ("      Main_Priority := ");
919         Set_Int    (Main_Priority);
920         Set_Char   (';');
921         Write_Statement_Buffer;
922
923         Set_String ("      Time_Slice_Value := ");
924
925         if Task_Dispatching_Policy_Specified = 'F'
926           and then ALIs.Table (ALIs.First).Time_Slice_Value = -1
927         then
928            Set_Int (0);
929         else
930            Set_Int (ALIs.Table (ALIs.First).Time_Slice_Value);
931         end if;
932
933         Set_Char   (';');
934         Write_Statement_Buffer;
935
936         Set_String ("      WC_Encoding := '");
937         Set_Char   (Get_WC_Encoding);
938
939         Set_String ("';");
940         Write_Statement_Buffer;
941
942         Set_String ("      Locking_Policy := '");
943         Set_Char   (Locking_Policy_Specified);
944         Set_String ("';");
945         Write_Statement_Buffer;
946
947         Set_String ("      Queuing_Policy := '");
948         Set_Char   (Queuing_Policy_Specified);
949         Set_String ("';");
950         Write_Statement_Buffer;
951
952         Set_String ("      Task_Dispatching_Policy := '");
953         Set_Char   (Task_Dispatching_Policy_Specified);
954         Set_String ("';");
955         Write_Statement_Buffer;
956
957         if System_Tasking_Restricted_Stages_Used
958           and then Partition_Elaboration_Policy_Specified = 'S'
959         then
960            Set_String ("      Partition_Elaboration_Policy := '");
961            Set_Char   (Partition_Elaboration_Policy_Specified);
962            Set_String ("';");
963            Write_Statement_Buffer;
964         end if;
965
966         Gen_Restrictions;
967
968         WBI ("      Priority_Specific_Dispatching :=");
969         WBI ("        Local_Priority_Specific_Dispatching'Address;");
970
971         Set_String ("      Num_Specific_Dispatching := ");
972         Set_Int (PSD_Pragma_Settings.Last + 1);
973         Set_Char (';');
974         Write_Statement_Buffer;
975
976         Set_String ("      Main_CPU := ");
977         Set_Int    (Main_CPU);
978         Set_Char   (';');
979         Write_Statement_Buffer;
980
981         WBI ("      Interrupt_States := Local_Interrupt_States'Address;");
982
983         Set_String ("      Num_Interrupt_States := ");
984         Set_Int (IS_Pragma_Settings.Last + 1);
985         Set_Char (';');
986         Write_Statement_Buffer;
987
988         Set_String ("      Unreserve_All_Interrupts := ");
989
990         if Unreserve_All_Interrupts_Specified then
991            Set_String ("1");
992         else
993            Set_String ("0");
994         end if;
995
996         Set_Char (';');
997         Write_Statement_Buffer;
998
999         if Exception_Tracebacks or Exception_Tracebacks_Symbolic then
1000            WBI ("      Exception_Tracebacks := 1;");
1001
1002            if Exception_Tracebacks_Symbolic then
1003               WBI ("      Exception_Tracebacks_Symbolic := 1;");
1004            end if;
1005         end if;
1006
1007         Set_String ("      Detect_Blocking := ");
1008
1009         if Detect_Blocking then
1010            Set_Int (1);
1011         else
1012            Set_Int (0);
1013         end if;
1014
1015         Set_String (";");
1016         Write_Statement_Buffer;
1017
1018         Set_String ("      Default_Stack_Size := ");
1019         Set_Int (Default_Stack_Size);
1020         Set_String (";");
1021         Write_Statement_Buffer;
1022
1023         if Leap_Seconds_Support then
1024            WBI ("      Leap_Seconds_Support := 1;");
1025         end if;
1026
1027         if XDR_Stream then
1028            WBI ("      XDR_Stream := 1;");
1029         end if;
1030
1031         if Bind_Env_String_Built then
1032            WBI ("      Bind_Env_Addr := Bind_Env'Address;");
1033         end if;
1034
1035         WBI ("");
1036
1037         --  Generate default-sized secondary stack pool and set secondary
1038         --  stack globals.
1039
1040         if Sec_Stack_Used then
1041
1042            --  Elaborate the body of the binder to initialize the default-
1043            --  sized secondary stack pool.
1044
1045            WBI ("      " & Get_Ada_Main_Name & "'Elab_Body;");
1046
1047            --  Generate the default-sized secondary stack pool and set the
1048            --  related secondary stack globals.
1049
1050            Set_String ("      Default_Secondary_Stack_Size := ");
1051
1052            if Opt.Default_Sec_Stack_Size /= Opt.No_Stack_Size then
1053               Set_Int (Opt.Default_Sec_Stack_Size);
1054            else
1055               Set_String ("System.Parameters.Runtime_Default_Sec_Stack_Size");
1056            end if;
1057
1058            Set_Char (';');
1059            Write_Statement_Buffer;
1060
1061            Set_String ("      Binder_Sec_Stacks_Count := ");
1062            Set_Int (Num_Sec_Stacks);
1063            Set_Char (';');
1064            Write_Statement_Buffer;
1065
1066            Set_String ("      Default_Sized_SS_Pool := ");
1067
1068            if Num_Sec_Stacks > 0 then
1069               Set_String ("Sec_Default_Sized_Stacks'Address;");
1070            else
1071               Set_String ("System.Null_Address;");
1072            end if;
1073
1074            Write_Statement_Buffer;
1075            WBI ("");
1076         end if;
1077
1078         --  Generate call to Runtime_Initialize
1079
1080         WBI ("      Runtime_Initialize (1);");
1081      end if;
1082
1083      --  Generate call to set Initialize_Scalar values if active
1084
1085      if Initialize_Scalars_Used then
1086         WBI ("");
1087         Set_String ("      System.Scalar_Values.Initialize ('");
1088         Set_Char (Initialize_Scalars_Mode1);
1089         Set_String ("', '");
1090         Set_Char (Initialize_Scalars_Mode2);
1091         Set_String ("');");
1092         Write_Statement_Buffer;
1093      end if;
1094
1095      --  Initialize stack limit variable of the environment task if the stack
1096      --  check method is stack limit and stack check is enabled.
1097
1098      if Stack_Check_Limits_On_Target
1099        and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
1100      then
1101         WBI ("");
1102         WBI ("      Initialize_Stack_Limit;");
1103      end if;
1104
1105      --  On CodePeer, the finalization of library objects is not relevant
1106
1107      if CodePeer_Mode then
1108         null;
1109
1110      --  If this is the main program case, attach finalize_library to the soft
1111      --  link. Do it only when not using a restricted run time, in which case
1112      --  tasks are non-terminating, so we do not want library-level
1113      --  finalization.
1114
1115      elsif not Bind_For_Library
1116        and then not Configurable_Run_Time_On_Target
1117        and then not Suppress_Standard_Library_On_Target
1118      then
1119         WBI ("");
1120
1121         if Lib_Final_Built then
1122            Set_String ("      Finalize_Library_Objects := ");
1123            Set_String ("finalize_library'access;");
1124         else
1125            Set_String ("      Finalize_Library_Objects := null;");
1126         end if;
1127
1128         Write_Statement_Buffer;
1129      end if;
1130
1131      --  Generate elaboration calls
1132
1133      if not CodePeer_Mode then
1134         WBI ("");
1135      end if;
1136
1137      Gen_Elab_Calls (Elab_Order);
1138
1139      if not CodePeer_Mode then
1140
1141         --  Call System.Elaboration_Allocators.Mark_Start_Of_Elaboration if
1142         --  restriction No_Standard_Allocators_After_Elaboration is active.
1143
1144         if Cumulative_Restrictions.Set
1145              (No_Standard_Allocators_After_Elaboration)
1146         then
1147            WBI
1148              ("      System.Elaboration_Allocators.Mark_End_Of_Elaboration;");
1149         end if;
1150
1151         --  From this point, no new dispatching domain can be created
1152
1153         if Dispatching_Domains_Used then
1154            WBI ("      Freeze_Dispatching_Domains;");
1155         end if;
1156
1157         --  Sequential partition elaboration policy
1158
1159         if Partition_Elaboration_Policy_Specified = 'S' then
1160            if System_Interrupts_Used then
1161               WBI ("      Install_Restricted_Handlers_Sequential;");
1162            end if;
1163
1164            if System_Tasking_Restricted_Stages_Used then
1165               WBI ("      Activate_All_Tasks_Sequential;");
1166            end if;
1167         end if;
1168
1169         if System_BB_CPU_Primitives_Multiprocessors_Used then
1170            WBI ("      Start_Slave_CPUs;");
1171         end if;
1172      end if;
1173
1174      WBI ("   end " & Ada_Init_Name.all & ";");
1175      WBI ("");
1176   end Gen_Adainit;
1177
1178   -------------------------
1179   -- Gen_Bind_Env_String --
1180   -------------------------
1181
1182   procedure Gen_Bind_Env_String is
1183      procedure Write_Name_With_Len (Nam : Name_Id);
1184      --  Write Nam as a string literal, prefixed with one
1185      --  character encoding Nam's length.
1186
1187      -------------------------
1188      -- Write_Name_With_Len --
1189      -------------------------
1190
1191      procedure Write_Name_With_Len (Nam : Name_Id) is
1192      begin
1193         Get_Name_String (Nam);
1194         Write_Str ("Character'Val (");
1195         Write_Int (Int (Name_Len));
1196         Write_Str (") & """);
1197         Write_Str (Name_Buffer (1 .. Name_Len));
1198         Write_Char ('"');
1199      end Write_Name_With_Len;
1200
1201      --  Local variables
1202
1203      First : Boolean := True;
1204      KN    : Name_Id := No_Name;
1205      VN    : Name_Id := No_Name;
1206
1207   --  Start of processing for Gen_Bind_Env_String
1208
1209   begin
1210      Bind_Environment.Get_First (KN, VN);
1211
1212      if VN = No_Name then
1213         return;
1214      end if;
1215
1216      Set_Special_Output (Write_Bind_Line'Access);
1217
1218      WBI ("   Bind_Env : aliased constant String :=");
1219
1220      while VN /= No_Name loop
1221         if First then
1222            Write_Str ("     ");
1223         else
1224            Write_Str ("     & ");
1225         end if;
1226
1227         Write_Name_With_Len (KN);
1228         Write_Str (" & ");
1229         Write_Name_With_Len (VN);
1230         Write_Eol;
1231
1232         Bind_Environment.Get_Next (KN, VN);
1233         First := False;
1234      end loop;
1235
1236      WBI ("     & ASCII.NUL;");
1237
1238      Cancel_Special_Output;
1239      Bind_Env_String_Built := True;
1240   end Gen_Bind_Env_String;
1241
1242   --------------------------
1243   -- Gen_CodePeer_Wrapper --
1244   --------------------------
1245
1246   procedure Gen_CodePeer_Wrapper is
1247      Callee_Name : constant String := "Ada_Main_Program";
1248
1249   begin
1250      if ALIs.Table (ALIs.First).Main_Program = Proc then
1251         WBI ("   procedure " & CodePeer_Wrapper_Name & " is ");
1252         WBI ("   begin");
1253         WBI ("      " & Callee_Name & ";");
1254
1255      else
1256         WBI ("   function " & CodePeer_Wrapper_Name & " return Integer is");
1257         WBI ("   begin");
1258         WBI ("      return " & Callee_Name & ";");
1259      end if;
1260
1261      WBI ("   end " & CodePeer_Wrapper_Name & ";");
1262      WBI ("");
1263   end Gen_CodePeer_Wrapper;
1264
1265   --------------------
1266   -- Gen_Elab_Calls --
1267   --------------------
1268
1269   procedure Gen_Elab_Calls (Elab_Order : Unit_Id_Array) is
1270      Check_Elab_Flag : Boolean;
1271
1272   begin
1273      --  Loop through elaboration order entries
1274
1275      for E in Elab_Order'Range loop
1276         declare
1277            Unum : constant Unit_Id := Elab_Order (E);
1278            U    : Unit_Record renames Units.Table (Unum);
1279
1280            Unum_Spec : Unit_Id;
1281            --  This is the unit number of the spec that corresponds to
1282            --  this entry. It is the same as Unum except when the body
1283            --  and spec are different and we are currently processing
1284            --  the body, in which case it is the spec (Unum + 1).
1285
1286         begin
1287            if U.Utype = Is_Body then
1288               Unum_Spec := Unum + 1;
1289            else
1290               Unum_Spec := Unum;
1291            end if;
1292
1293            --  Nothing to do if predefined unit in no run time mode
1294
1295            if No_Run_Time_Mode and then Is_Predefined_File_Name (U.Sfile) then
1296               null;
1297
1298            --  Likewise if this is an interface to a stand alone library
1299
1300            elsif U.SAL_Interface then
1301               null;
1302
1303            --  Case of no elaboration code
1304
1305            elsif U.No_Elab
1306
1307              --  In CodePeer mode, we special case subprogram bodies which
1308              --  are handled in the 'else' part below, and lead to a call
1309              --  to <subp>'Elab_Subp_Body.
1310
1311              and then (not CodePeer_Mode
1312
1313                         --  Test for spec
1314
1315                         or else U.Utype = Is_Spec
1316                         or else U.Utype = Is_Spec_Only
1317                         or else U.Unit_Kind /= 's')
1318            then
1319               --  In the case of a body with a separate spec, where the
1320               --  separate spec has an elaboration entity defined, this is
1321               --  where we increment the elaboration entity if one exists.
1322
1323               --  Likewise for lone specs with an elaboration entity defined
1324               --  despite No_Elaboration_Code, e.g. when requested to preserve
1325               --  control flow.
1326
1327               if (U.Utype = Is_Body or else U.Utype = Is_Spec_Only)
1328                 and then Units.Table (Unum_Spec).Set_Elab_Entity
1329                 and then not CodePeer_Mode
1330               then
1331                  Set_String ("      E");
1332                  Set_Unit_Number (Unum_Spec);
1333                  Set_String (" := E");
1334                  Set_Unit_Number (Unum_Spec);
1335                  Set_String (" + 1;");
1336                  Write_Statement_Buffer;
1337               end if;
1338
1339            --  Here if elaboration code is present. If binding a library
1340            --  or if there is a non-Ada main subprogram then we generate:
1341
1342            --    if uname_E = 0 then
1343            --       uname'elab_[spec|body];
1344            --    end if;
1345            --    uname_E := uname_E + 1;
1346
1347            --  Otherwise, elaboration routines are called unconditionally:
1348
1349            --    uname'elab_[spec|body];
1350            --    uname_E := uname_E + 1;
1351
1352            --  The uname_E increment is skipped if this is a separate spec,
1353            --  since it will be done when we process the body.
1354
1355            --  In CodePeer mode, we do not generate any reference to xxx_E
1356            --  variables, only calls to 'Elab* subprograms.
1357
1358            else
1359               --  Check incompatibilities with No_Multiple_Elaboration
1360
1361               if not CodePeer_Mode
1362                 and then Cumulative_Restrictions.Set (No_Multiple_Elaboration)
1363               then
1364                  --  Force_Checking_Of_Elaboration_Flags (-F) not allowed
1365
1366                  if Force_Checking_Of_Elaboration_Flags then
1367                     Osint.Fail
1368                       ("-F (force elaboration checks) switch not allowed "
1369                        & "with restriction No_Multiple_Elaboration active");
1370
1371                  --  Interfacing of libraries not allowed
1372
1373                  elsif Interface_Library_Unit then
1374                     Osint.Fail
1375                       ("binding of interfaced libraries not allowed "
1376                        & "with restriction No_Multiple_Elaboration active");
1377
1378                  --  Non-Ada main program not allowed
1379
1380                  elsif not Bind_Main_Program then
1381                     Osint.Fail
1382                       ("non-Ada main program not allowed "
1383                        & "with restriction No_Multiple_Elaboration active");
1384                  end if;
1385               end if;
1386
1387               --  OK, see if we need to test elaboration flag
1388
1389               Check_Elab_Flag :=
1390                 Units.Table (Unum_Spec).Set_Elab_Entity
1391                   and then not CodePeer_Mode
1392                   and then (Force_Checking_Of_Elaboration_Flags
1393                              or Interface_Library_Unit
1394                              or not Bind_Main_Program);
1395
1396               if Check_Elab_Flag then
1397                  Set_String ("      if E");
1398                  Set_Unit_Number (Unum_Spec);
1399                  Set_String (" = 0 then");
1400                  Write_Statement_Buffer;
1401                  Set_String ("   ");
1402               end if;
1403
1404               Set_String ("      ");
1405               Get_Decoded_Name_String_With_Brackets (U.Uname);
1406
1407               if Name_Buffer (Name_Len) = 's' then
1408                  Name_Buffer (Name_Len - 1 .. Name_Len + 8) :=
1409                    "'elab_spec";
1410                  Name_Len := Name_Len + 8;
1411
1412               --  Special case in CodePeer mode for subprogram bodies
1413               --  which correspond to CodePeer 'Elab_Subp_Body special
1414               --  init procedure.
1415
1416               elsif U.Unit_Kind = 's' and CodePeer_Mode then
1417                  Name_Buffer (Name_Len - 1 .. Name_Len + 13) :=
1418                    "'elab_subp_body";
1419                  Name_Len := Name_Len + 13;
1420
1421               else
1422                  Name_Buffer (Name_Len - 1 .. Name_Len + 8) :=
1423                    "'elab_body";
1424                  Name_Len := Name_Len + 8;
1425               end if;
1426
1427               Set_Casing (U.Icasing);
1428               Set_Name_Buffer;
1429               Set_Char (';');
1430               Write_Statement_Buffer;
1431
1432               if Check_Elab_Flag then
1433                  WBI ("      end if;");
1434               end if;
1435
1436               if U.Utype /= Is_Spec
1437                 and then not CodePeer_Mode
1438                 and then Units.Table (Unum_Spec).Set_Elab_Entity
1439               then
1440                  Set_String ("      E");
1441                  Set_Unit_Number (Unum_Spec);
1442                  Set_String (" := E");
1443                  Set_Unit_Number (Unum_Spec);
1444                  Set_String (" + 1;");
1445                  Write_Statement_Buffer;
1446               end if;
1447            end if;
1448         end;
1449      end loop;
1450   end Gen_Elab_Calls;
1451
1452   ------------------------
1453   -- Gen_Elab_Externals --
1454   ------------------------
1455
1456   procedure Gen_Elab_Externals (Elab_Order : Unit_Id_Array) is
1457   begin
1458      if CodePeer_Mode then
1459         return;
1460      end if;
1461
1462      for E in Elab_Order'Range loop
1463         declare
1464            Unum : constant Unit_Id := Elab_Order (E);
1465            U    : Unit_Record renames Units.Table (Unum);
1466
1467         begin
1468            --  Check for Elab_Entity to be set for this unit
1469
1470            if U.Set_Elab_Entity
1471
1472              --  Don't generate reference for stand alone library
1473
1474              and then not U.SAL_Interface
1475
1476              --  Don't generate reference for predefined file in No_Run_Time
1477              --  mode, since we don't include the object files in this case
1478
1479              and then not
1480                (No_Run_Time_Mode
1481                  and then Is_Predefined_File_Name (U.Sfile))
1482            then
1483               Get_Name_String (U.Sfile);
1484               Set_String ("   ");
1485               Set_String ("E");
1486               Set_Unit_Number (Unum);
1487               Set_String (" : Short_Integer; pragma Import (Ada, E");
1488               Set_Unit_Number (Unum);
1489               Set_String (", """);
1490               Get_Name_String (U.Uname);
1491               Set_Unit_Name;
1492               Set_String ("_E"");");
1493               Write_Statement_Buffer;
1494            end if;
1495         end;
1496      end loop;
1497
1498      WBI ("");
1499   end Gen_Elab_Externals;
1500
1501   --------------------
1502   -- Gen_Elab_Order --
1503   --------------------
1504
1505   procedure Gen_Elab_Order (Elab_Order : Unit_Id_Array) is
1506   begin
1507      WBI ("");
1508      WBI ("   --  BEGIN ELABORATION ORDER");
1509
1510      for J in Elab_Order'Range loop
1511         Set_String ("   --  ");
1512         Get_Name_String (Units.Table (Elab_Order (J)).Uname);
1513         Set_Name_Buffer;
1514         Write_Statement_Buffer;
1515      end loop;
1516
1517      WBI ("   --  END ELABORATION ORDER");
1518   end Gen_Elab_Order;
1519
1520   --------------------------
1521   -- Gen_Finalize_Library --
1522   --------------------------
1523
1524   procedure Gen_Finalize_Library (Elab_Order : Unit_Id_Array) is
1525      procedure Gen_Header;
1526      --  Generate the header of the finalization routine
1527
1528      ----------------
1529      -- Gen_Header --
1530      ----------------
1531
1532      procedure Gen_Header is
1533      begin
1534         WBI ("   procedure finalize_library is");
1535         WBI ("   begin");
1536      end Gen_Header;
1537
1538      --  Local variables
1539
1540      Count : Int := 1;
1541      U     : Unit_Record;
1542      Uspec : Unit_Record;
1543      Unum  : Unit_Id;
1544
1545   --  Start of processing for Gen_Finalize_Library
1546
1547   begin
1548      if CodePeer_Mode then
1549         return;
1550      end if;
1551
1552      for E in reverse Elab_Order'Range loop
1553         Unum := Elab_Order (E);
1554         U    := Units.Table (Unum);
1555
1556         --  Dealing with package bodies is a little complicated. In such
1557         --  cases we must retrieve the package spec since it contains the
1558         --  spec of the body finalizer.
1559
1560         if U.Utype = Is_Body then
1561            Unum  := Unum + 1;
1562            Uspec := Units.Table (Unum);
1563         else
1564            Uspec := U;
1565         end if;
1566
1567         Get_Name_String (Uspec.Uname);
1568
1569         --  We are only interested in non-generic packages
1570
1571         if U.Unit_Kind /= 'p' or else U.Is_Generic then
1572            null;
1573
1574         --  That aren't an interface to a stand alone library
1575
1576         elsif U.SAL_Interface then
1577            null;
1578
1579         --  Case of no finalization
1580
1581         elsif not U.Has_Finalizer then
1582
1583            --  The only case in which we have to do something is if this
1584            --  is a body, with a separate spec, where the separate spec
1585            --  has a finalizer. In that case, this is where we decrement
1586            --  the elaboration entity.
1587
1588            if U.Utype = Is_Body and then Uspec.Has_Finalizer then
1589               if not Lib_Final_Built then
1590                  Gen_Header;
1591                  Lib_Final_Built := True;
1592               end if;
1593
1594               Set_String ("      E");
1595               Set_Unit_Number (Unum);
1596               Set_String (" := E");
1597               Set_Unit_Number (Unum);
1598               Set_String (" - 1;");
1599               Write_Statement_Buffer;
1600            end if;
1601
1602         else
1603            if not Lib_Final_Built then
1604               Gen_Header;
1605               Lib_Final_Built := True;
1606            end if;
1607
1608            --  Generate:
1609            --    declare
1610            --       procedure F<Count>;
1611
1612            Set_String ("      declare");
1613            Write_Statement_Buffer;
1614
1615            Set_String ("         procedure F");
1616            Set_Int    (Count);
1617            Set_Char   (';');
1618            Write_Statement_Buffer;
1619
1620            --  Generate:
1621            --    pragma Import (Ada, F<Count>,
1622            --                  "xx__yy__finalize_[body|spec]");
1623
1624            Set_String ("         pragma Import (Ada, F");
1625            Set_Int (Count);
1626            Set_String (", """);
1627
1628            --  Perform name construction
1629
1630            Set_Unit_Name;
1631            Set_String ("__finalize_");
1632
1633            --  Package spec processing
1634
1635            if U.Utype = Is_Spec
1636              or else U.Utype = Is_Spec_Only
1637            then
1638               Set_String ("spec");
1639
1640            --  Package body processing
1641
1642            else
1643               Set_String ("body");
1644            end if;
1645
1646            Set_String (""");");
1647            Write_Statement_Buffer;
1648
1649            --  If binding a library or if there is a non-Ada main subprogram
1650            --  then we generate:
1651
1652            --    begin
1653            --       uname_E := uname_E - 1;
1654            --       if uname_E = 0 then
1655            --          F<Count>;
1656            --       end if;
1657            --    end;
1658
1659            --  Otherwise, finalization routines are called unconditionally:
1660
1661            --    begin
1662            --       uname_E := uname_E - 1;
1663            --       F<Count>;
1664            --    end;
1665
1666            --  The uname_E decrement is skipped if this is a separate spec,
1667            --  since it will be done when we process the body.
1668
1669            WBI ("      begin");
1670
1671            if U.Utype /= Is_Spec then
1672               Set_String ("         E");
1673               Set_Unit_Number (Unum);
1674               Set_String (" := E");
1675               Set_Unit_Number (Unum);
1676               Set_String (" - 1;");
1677               Write_Statement_Buffer;
1678            end if;
1679
1680            if Interface_Library_Unit or not Bind_Main_Program then
1681               Set_String ("         if E");
1682               Set_Unit_Number (Unum);
1683               Set_String (" = 0 then");
1684               Write_Statement_Buffer;
1685               Set_String ("   ");
1686            end if;
1687
1688            Set_String ("         F");
1689            Set_Int    (Count);
1690            Set_Char   (';');
1691            Write_Statement_Buffer;
1692
1693            if Interface_Library_Unit or not Bind_Main_Program then
1694               WBI ("         end if;");
1695            end if;
1696
1697            WBI ("      end;");
1698
1699            Count := Count + 1;
1700         end if;
1701      end loop;
1702
1703      if Lib_Final_Built then
1704
1705         --  It is possible that the finalization of a library-level object
1706         --  raised an exception. In that case import the actual exception
1707         --  and the routine necessary to raise it.
1708
1709         WBI ("      declare");
1710         WBI ("         procedure Reraise_Library_Exception_If_Any;");
1711
1712         Set_String ("            pragma Import (Ada, ");
1713         Set_String ("Reraise_Library_Exception_If_Any, ");
1714         Set_String ("""__gnat_reraise_library_exception_if_any"");");
1715         Write_Statement_Buffer;
1716
1717         WBI ("      begin");
1718         WBI ("         Reraise_Library_Exception_If_Any;");
1719         WBI ("      end;");
1720         WBI ("   end finalize_library;");
1721         WBI ("");
1722      end if;
1723   end Gen_Finalize_Library;
1724
1725   --------------
1726   -- Gen_Main --
1727   --------------
1728
1729   procedure Gen_Main is
1730   begin
1731      if not No_Main_Subprogram then
1732
1733         --  To call the main program, we declare it using a pragma Import
1734         --  Ada with the right link name.
1735
1736         --  It might seem more obvious to "with" the main program, and call
1737         --  it in the normal Ada manner. We do not do this for three
1738         --  reasons:
1739
1740         --    1. It is more efficient not to recompile the main program
1741         --    2. We are not entitled to assume the source is accessible
1742         --    3. We don't know what options to use to compile it
1743
1744         --  It is really reason 3 that is most critical (indeed we used
1745         --  to generate the "with", but several regression tests failed).
1746
1747         if ALIs.Table (ALIs.First).Main_Program = Func then
1748            WBI ("   function Ada_Main_Program return Integer;");
1749         else
1750            WBI ("   procedure Ada_Main_Program;");
1751         end if;
1752
1753         Set_String ("   pragma Import (Ada, Ada_Main_Program, """);
1754         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
1755         Set_Main_Program_Name;
1756         Set_String (""");");
1757
1758         Write_Statement_Buffer;
1759         WBI ("");
1760
1761         --  For CodePeer, declare a wrapper for the user-defined main program
1762
1763         if CodePeer_Mode then
1764            Gen_CodePeer_Wrapper;
1765         end if;
1766      end if;
1767
1768      if Exit_Status_Supported_On_Target then
1769         Set_String ("   function ");
1770      else
1771         Set_String ("   procedure ");
1772      end if;
1773
1774      Set_String (Get_Main_Name);
1775
1776      if Command_Line_Args_On_Target then
1777         Write_Statement_Buffer;
1778         WBI ("     (argc : Integer;");
1779         WBI ("      argv : System.Address;");
1780         WBI ("      envp : System.Address)");
1781
1782         if Exit_Status_Supported_On_Target then
1783            WBI ("      return Integer");
1784         end if;
1785
1786         WBI ("   is");
1787
1788      else
1789         if Exit_Status_Supported_On_Target then
1790            Set_String (" return Integer is");
1791         else
1792            Set_String (" is");
1793         end if;
1794
1795         Write_Statement_Buffer;
1796      end if;
1797
1798      if Opt.Default_Exit_Status /= 0
1799        and then Bind_Main_Program
1800        and then not Configurable_Run_Time_Mode
1801      then
1802         WBI ("      procedure Set_Exit_Status (Status : Integer);");
1803         WBI ("      pragma Import (C, Set_Exit_Status, " &
1804                     """__gnat_set_exit_status"");");
1805         WBI ("");
1806      end if;
1807
1808      --  Initialize and Finalize
1809
1810      if not CodePeer_Mode
1811        and then not Cumulative_Restrictions.Set (No_Finalization)
1812      then
1813         WBI ("      procedure Initialize (Addr : System.Address);");
1814         WBI ("      pragma Import (C, Initialize, ""__gnat_initialize"");");
1815         WBI ("");
1816         WBI ("      procedure Finalize;");
1817         WBI ("      pragma Import (C, Finalize, ""__gnat_finalize"");");
1818      end if;
1819
1820      --  If we want to analyze the stack, we must import corresponding symbols
1821
1822      if Dynamic_Stack_Measurement then
1823         WBI ("");
1824         WBI ("      procedure Output_Results;");
1825         WBI ("      pragma Import (C, Output_Results, " &
1826              """__gnat_stack_usage_output_results"");");
1827
1828         WBI ("");
1829         WBI ("      " &
1830              "procedure Initialize_Stack_Analysis (Buffer_Size : Natural);");
1831         WBI ("      pragma Import (C, Initialize_Stack_Analysis, " &
1832              """__gnat_stack_usage_initialize"");");
1833      end if;
1834
1835      --  Deal with declarations for main program case
1836
1837      if not No_Main_Subprogram then
1838         if ALIs.Table (ALIs.First).Main_Program = Func then
1839            WBI ("      Result : Integer;");
1840            WBI ("");
1841         end if;
1842
1843         if Bind_Main_Program
1844           and not Suppress_Standard_Library_On_Target
1845           and not CodePeer_Mode
1846         then
1847            WBI ("      SEH : aliased array (1 .. 2) of Integer;");
1848            WBI ("");
1849         end if;
1850      end if;
1851
1852      --  Generate a reference to Ada_Main_Program_Name. This symbol is not
1853      --  referenced elsewhere in the generated program, but is needed by
1854      --  the debugger (that's why it is generated in the first place). The
1855      --  reference stops Ada_Main_Program_Name from being optimized away by
1856      --  smart linkers.
1857
1858      --  Because this variable is unused, we make this variable "aliased"
1859      --  with a pragma Volatile in order to tell the compiler to preserve
1860      --  this variable at any level of optimization.
1861
1862      --  CodePeer and CCG do not need this extra code. The code is also not
1863      --  needed if the binder is in "Minimal Binder" mode.
1864
1865      if Bind_Main_Program
1866        and then not Minimal_Binder
1867        and then not CodePeer_Mode
1868        and then not Generate_C_Code
1869      then
1870         WBI ("      Ensure_Reference : aliased System.Address := " &
1871              "Ada_Main_Program_Name'Address;");
1872         WBI ("      pragma Volatile (Ensure_Reference);");
1873         WBI ("");
1874      end if;
1875
1876      WBI ("   begin");
1877
1878      --  Acquire command-line arguments if present on target
1879
1880      if CodePeer_Mode then
1881         null;
1882
1883      elsif Command_Line_Args_On_Target then
1884
1885         --  Initialize gnat_argc/gnat_argv only if not already initialized,
1886         --  to avoid losing the result of any command-line processing done by
1887         --  earlier GNAT run-time initialization.
1888
1889         WBI ("      if gnat_argc = 0 then");
1890         WBI ("         gnat_argc := argc;");
1891         WBI ("         gnat_argv := argv;");
1892         WBI ("      end if;");
1893         WBI ("      gnat_envp := envp;");
1894         WBI ("");
1895
1896      --  If configurable run-time and no command-line args, then nothing needs
1897      --  to be done since the gnat_argc/argv/envp variables are suppressed in
1898      --  this case.
1899
1900      elsif Configurable_Run_Time_On_Target then
1901         null;
1902
1903      --  Otherwise set dummy values (to be filled in by some other unit?)
1904
1905      else
1906         WBI ("      gnat_argc := 0;");
1907         WBI ("      gnat_argv := System.Null_Address;");
1908         WBI ("      gnat_envp := System.Null_Address;");
1909      end if;
1910
1911      if Opt.Default_Exit_Status /= 0
1912        and then Bind_Main_Program
1913        and then not Configurable_Run_Time_Mode
1914      then
1915         Set_String ("      Set_Exit_Status (");
1916         Set_Int (Opt.Default_Exit_Status);
1917         Set_String (");");
1918         Write_Statement_Buffer;
1919      end if;
1920
1921      if Dynamic_Stack_Measurement then
1922         Set_String ("      Initialize_Stack_Analysis (");
1923         Set_Int (Dynamic_Stack_Measurement_Array_Size);
1924         Set_String (");");
1925         Write_Statement_Buffer;
1926      end if;
1927
1928      if not Cumulative_Restrictions.Set (No_Finalization)
1929        and then not CodePeer_Mode
1930      then
1931         if not No_Main_Subprogram
1932           and then Bind_Main_Program
1933           and then not Suppress_Standard_Library_On_Target
1934         then
1935            WBI ("      Initialize (SEH'Address);");
1936         else
1937            WBI ("      Initialize (System.Null_Address);");
1938         end if;
1939      end if;
1940
1941      WBI ("      " & Ada_Init_Name.all & ";");
1942
1943      if not No_Main_Subprogram then
1944         if CodePeer_Mode then
1945            if ALIs.Table (ALIs.First).Main_Program = Proc then
1946               WBI ("      " & CodePeer_Wrapper_Name & ";");
1947            else
1948               WBI ("      Result := " & CodePeer_Wrapper_Name & ";");
1949            end if;
1950
1951         elsif ALIs.Table (ALIs.First).Main_Program = Proc then
1952            WBI ("      Ada_Main_Program;");
1953
1954         else
1955            WBI ("      Result := Ada_Main_Program;");
1956         end if;
1957      end if;
1958
1959      --  Adafinal call is skipped if no finalization
1960
1961      if not Cumulative_Restrictions.Set (No_Finalization) then
1962         WBI ("      adafinal;");
1963      end if;
1964
1965      --  Prints the result of static stack analysis
1966
1967      if Dynamic_Stack_Measurement then
1968         WBI ("      Output_Results;");
1969      end if;
1970
1971      --  Finalize is only called if we have a run time
1972
1973      if not Cumulative_Restrictions.Set (No_Finalization)
1974        and then not CodePeer_Mode
1975      then
1976         WBI ("      Finalize;");
1977      end if;
1978
1979      --  Return result
1980
1981      if Exit_Status_Supported_On_Target then
1982         if No_Main_Subprogram
1983           or else ALIs.Table (ALIs.First).Main_Program = Proc
1984         then
1985            WBI ("      return (gnat_exit_status);");
1986         else
1987            WBI ("      return (Result);");
1988         end if;
1989      end if;
1990
1991      WBI ("   end;");
1992      WBI ("");
1993   end Gen_Main;
1994
1995   ------------------------------
1996   -- Gen_Object_Files_Options --
1997   ------------------------------
1998
1999   procedure Gen_Object_Files_Options (Elab_Order : Unit_Id_Array) is
2000      Lgnat : Natural;
2001      --  This keeps track of the position in the sorted set of entries in the
2002      --  Linker_Options table of where the first entry from an internal file
2003      --  appears.
2004
2005      Linker_Option_List_Started : Boolean := False;
2006      --  Set to True when "LINKER OPTION LIST" is displayed
2007
2008      procedure Write_Linker_Option;
2009      --  Write binder info linker option
2010
2011      -------------------------
2012      -- Write_Linker_Option --
2013      -------------------------
2014
2015      procedure Write_Linker_Option is
2016         Start : Natural;
2017         Stop  : Natural;
2018
2019      begin
2020         --  Loop through string, breaking at null's
2021
2022         Start := 1;
2023         while Start < Name_Len loop
2024
2025            --  Find null ending this section
2026
2027            Stop := Start + 1;
2028            while Name_Buffer (Stop) /= ASCII.NUL
2029              and then Stop <= Name_Len loop
2030               Stop := Stop + 1;
2031            end loop;
2032
2033            --  Process section if non-null
2034
2035            if Stop > Start then
2036               if Output_Linker_Option_List then
2037                  if not Zero_Formatting then
2038                     if not Linker_Option_List_Started then
2039                        Linker_Option_List_Started := True;
2040                        Write_Eol;
2041                        Write_Str ("     LINKER OPTION LIST");
2042                        Write_Eol;
2043                        Write_Eol;
2044                     end if;
2045
2046                     Write_Str ("   ");
2047                  end if;
2048
2049                  Write_Str (Name_Buffer (Start .. Stop - 1));
2050                  Write_Eol;
2051               end if;
2052               WBI ("   --   " & Name_Buffer (Start .. Stop - 1));
2053            end if;
2054
2055            Start := Stop + 1;
2056         end loop;
2057      end Write_Linker_Option;
2058
2059   --  Start of processing for Gen_Object_Files_Options
2060
2061   begin
2062      WBI ("--  BEGIN Object file/option list");
2063
2064      if Object_List_Filename /= null then
2065         Set_List_File (Object_List_Filename.all);
2066      end if;
2067
2068      for E in Elab_Order'Range loop
2069
2070         --  If not spec that has an associated body, then generate a comment
2071         --  giving the name of the corresponding object file.
2072
2073         if not Units.Table (Elab_Order (E)).SAL_Interface
2074           and then Units.Table (Elab_Order (E)).Utype /= Is_Spec
2075         then
2076            Get_Name_String
2077              (ALIs.Table
2078                (Units.Table (Elab_Order (E)).My_ALI).Ofile_Full_Name);
2079
2080            --  If the presence of an object file is necessary or if it exists,
2081            --  then use it.
2082
2083            if not Hostparm.Exclude_Missing_Objects
2084              or else
2085                System.OS_Lib.Is_Regular_File (Name_Buffer (1 .. Name_Len))
2086            then
2087               WBI ("   --   " & Name_Buffer (1 .. Name_Len));
2088
2089               if Output_Object_List then
2090                  Write_Str (Name_Buffer (1 .. Name_Len));
2091                  Write_Eol;
2092               end if;
2093            end if;
2094         end if;
2095      end loop;
2096
2097      if Object_List_Filename /= null then
2098         Close_List_File;
2099      end if;
2100
2101      --  Add a "-Ldir" for each directory in the object path
2102
2103      for J in 1 .. Nb_Dir_In_Obj_Search_Path loop
2104         declare
2105            Dir : constant String_Ptr := Dir_In_Obj_Search_Path (J);
2106
2107         begin
2108            Name_Len := 0;
2109            Add_Str_To_Name_Buffer ("-L");
2110            Add_Str_To_Name_Buffer (Dir.all);
2111            Write_Linker_Option;
2112         end;
2113      end loop;
2114
2115      if not (Opt.No_Run_Time_Mode or Opt.No_Stdlib) then
2116         Name_Len := 0;
2117
2118         if Opt.Shared_Libgnat then
2119            Add_Str_To_Name_Buffer ("-shared");
2120         else
2121            Add_Str_To_Name_Buffer ("-static");
2122         end if;
2123
2124         --  Write directly to avoid inclusion in -K output as -static and
2125         --  -shared are not usually specified linker options.
2126
2127         WBI ("   --   " & Name_Buffer (1 .. Name_Len));
2128      end if;
2129
2130      --  Sort linker options
2131
2132      --  This sort accomplishes two important purposes:
2133
2134      --    a) All application files are sorted to the front, and all GNAT
2135      --       internal files are sorted to the end. This results in a well
2136      --       defined dividing line between the two sets of files, for the
2137      --       purpose of inserting certain standard library references into
2138      --       the linker arguments list.
2139
2140      --    b) Given two different units, we sort the linker options so that
2141      --       those from a unit earlier in the elaboration order comes later
2142      --       in the list. This is a heuristic designed to create a more
2143      --       friendly order of linker options when the operations appear in
2144      --       separate units. The idea is that if unit A must be elaborated
2145      --       before unit B, then it is more likely that B references
2146      --       libraries included by A, than vice versa, so we want libraries
2147      --       included by A to come after libraries included by B.
2148
2149      --  These two criteria are implemented by function Lt_Linker_Option. Note
2150      --  that a special case of b) is that specs are elaborated before bodies,
2151      --  so linker options from specs come after linker options for bodies,
2152      --  and again, the assumption is that libraries used by the body are more
2153      --  likely to reference libraries used by the spec, than vice versa.
2154
2155      Sort
2156        (Linker_Options.Last,
2157         Move_Linker_Option'Access,
2158         Lt_Linker_Option'Access);
2159
2160      --  Write user linker options, i.e. the set of linker options that come
2161      --  from all files other than GNAT internal files, Lgnat is left set to
2162      --  point to the first entry from a GNAT internal file, or past the end
2163      --  of the entries if there are no internal files.
2164
2165      Lgnat := Linker_Options.Last + 1;
2166
2167      for J in 1 .. Linker_Options.Last loop
2168         if not Linker_Options.Table (J).Internal_File then
2169            Get_Name_String (Linker_Options.Table (J).Name);
2170            Write_Linker_Option;
2171         else
2172            Lgnat := J;
2173            exit;
2174         end if;
2175      end loop;
2176
2177      --  Now we insert standard linker options that must appear after the
2178      --  entries from user files, and before the entries from GNAT run-time
2179      --  files. The reason for this decision is that libraries referenced
2180      --  by internal routines may reference these standard library entries.
2181
2182      --  Note that we do not insert anything when pragma No_Run_Time has
2183      --  been specified or when the standard libraries are not to be used,
2184      --  otherwise on some platforms, we may get duplicate symbols when
2185      --  linking (not clear if this is still the case, but it is harmless).
2186
2187      if not (Opt.No_Run_Time_Mode or else Opt.No_Stdlib) then
2188         if With_GNARL then
2189            Name_Len := 0;
2190
2191            if Opt.Shared_Libgnat then
2192               Add_Str_To_Name_Buffer (Shared_Lib ("gnarl"));
2193            else
2194               Add_Str_To_Name_Buffer ("-lgnarl");
2195            end if;
2196
2197            Write_Linker_Option;
2198         end if;
2199
2200         Name_Len := 0;
2201
2202         if Opt.Shared_Libgnat then
2203            Add_Str_To_Name_Buffer (Shared_Lib ("gnat"));
2204         else
2205            Add_Str_To_Name_Buffer ("-lgnat");
2206         end if;
2207
2208         Write_Linker_Option;
2209      end if;
2210
2211      --  Write linker options from all internal files
2212
2213      for J in Lgnat .. Linker_Options.Last loop
2214         Get_Name_String (Linker_Options.Table (J).Name);
2215         Write_Linker_Option;
2216      end loop;
2217
2218      if Output_Linker_Option_List and then not Zero_Formatting then
2219         Write_Eol;
2220      end if;
2221
2222      WBI ("--  END Object file/option list   ");
2223   end Gen_Object_Files_Options;
2224
2225   ---------------------
2226   -- Gen_Output_File --
2227   ---------------------
2228
2229   procedure Gen_Output_File
2230     (Filename   : String;
2231      Elab_Order : Unit_Id_Array)
2232   is
2233   begin
2234      --  Acquire settings for Interrupt_State pragmas
2235
2236      Set_IS_Pragma_Table;
2237
2238      --  Acquire settings for Priority_Specific_Dispatching pragma
2239
2240      Set_PSD_Pragma_Table;
2241
2242      --  Override time slice value if -T switch is set
2243
2244      if Time_Slice_Set then
2245         ALIs.Table (ALIs.First).Time_Slice_Value := Opt.Time_Slice_Value;
2246      end if;
2247
2248      --  Count number of elaboration calls
2249
2250      for E in Elab_Order'Range loop
2251         if Units.Table (Elab_Order (E)).No_Elab then
2252            null;
2253         else
2254            Num_Elab_Calls := Num_Elab_Calls + 1;
2255         end if;
2256      end loop;
2257
2258      --  Count the number of statically allocated stacks to be generated by
2259      --  the binder. If the user has specified the number of default-sized
2260      --  secondary stacks, use that number. Otherwise start the count at one
2261      --  as the binder is responsible for creating a secondary stack for the
2262      --  main task.
2263
2264      if Opt.Quantity_Of_Default_Size_Sec_Stacks /= -1 then
2265         Num_Sec_Stacks := Quantity_Of_Default_Size_Sec_Stacks;
2266      elsif Sec_Stack_Used then
2267         Num_Sec_Stacks := 1;
2268      end if;
2269
2270      for J in Units.First .. Units.Last loop
2271         Num_Primary_Stacks :=
2272           Num_Primary_Stacks + Units.Table (J).Primary_Stack_Count;
2273
2274         Num_Sec_Stacks :=
2275           Num_Sec_Stacks + Units.Table (J).Sec_Stack_Count;
2276      end loop;
2277
2278      --  Generate output file in appropriate language
2279
2280      Gen_Output_File_Ada (Filename, Elab_Order);
2281   end Gen_Output_File;
2282
2283   -------------------------
2284   -- Gen_Output_File_Ada --
2285   -------------------------
2286
2287   procedure Gen_Output_File_Ada
2288     (Filename : String; Elab_Order : Unit_Id_Array)
2289   is
2290      Ada_Main : constant String := Get_Ada_Main_Name;
2291      --  Name to be used for generated Ada main program. See the body of
2292      --  function Get_Ada_Main_Name for details on the form of the name.
2293
2294      Needs_Library_Finalization : constant Boolean :=
2295        not Configurable_Run_Time_On_Target
2296        and then Has_Finalizer (Elab_Order);
2297      --  For restricted run-time libraries (ZFP and Ravenscar) tasks are
2298      --  non-terminating, so we do not want finalization.
2299
2300      Bfiles : Name_Id;
2301      --  Name of generated bind file (spec)
2302
2303      Bfileb : Name_Id;
2304      --  Name of generated bind file (body)
2305
2306   begin
2307      --  Create spec first
2308
2309      Create_Binder_Output (Filename, 's', Bfiles);
2310
2311      --  We always compile the binder file in Ada 95 mode so that we properly
2312      --  handle use of Ada 2005 keywords as identifiers in Ada 95 mode. None
2313      --  of the Ada 2005 or Ada 2012 constructs are needed by the binder file.
2314
2315      WBI ("pragma Warnings (Off);");
2316      WBI ("pragma Ada_95;");
2317
2318      --  If we are operating in Restrictions (No_Exception_Handlers) mode,
2319      --  then we need to make sure that the binder program is compiled with
2320      --  the same restriction, so that no exception tables are generated.
2321
2322      if Cumulative_Restrictions.Set (No_Exception_Handlers) then
2323         WBI ("pragma Restrictions (No_Exception_Handlers);");
2324      end if;
2325
2326      --  Same processing for Restrictions (No_Exception_Propagation)
2327
2328      if Cumulative_Restrictions.Set (No_Exception_Propagation) then
2329         WBI ("pragma Restrictions (No_Exception_Propagation);");
2330      end if;
2331
2332      --  Same processing for pragma No_Run_Time
2333
2334      if No_Run_Time_Mode then
2335         WBI ("pragma No_Run_Time;");
2336      end if;
2337
2338      --  Generate with of System so we can reference System.Address
2339
2340      WBI ("with System;");
2341
2342      --  Generate with of System.Initialize_Scalars if active
2343
2344      if Initialize_Scalars_Used then
2345         WBI ("with System.Scalar_Values;");
2346      end if;
2347
2348      --  Generate withs of System.Secondary_Stack and System.Parameters to
2349      --  allow the generation of the default-sized secondary stack pool.
2350
2351      if Sec_Stack_Used then
2352         WBI ("with System.Parameters;");
2353         WBI ("with System.Secondary_Stack;");
2354      end if;
2355
2356      Resolve_Binder_Options (Elab_Order);
2357
2358      --  Generate standard with's
2359
2360      if not Suppress_Standard_Library_On_Target then
2361         if CodePeer_Mode then
2362            WBI ("with System.Standard_Library;");
2363         end if;
2364      end if;
2365
2366      WBI ("package " & Ada_Main & " is");
2367
2368      --  Main program case
2369
2370      if Bind_Main_Program then
2371         --  Generate argc/argv stuff unless suppressed
2372
2373         if Command_Line_Args_On_Target
2374           or not Configurable_Run_Time_On_Target
2375         then
2376            WBI ("");
2377            WBI ("   gnat_argc : Integer;");
2378            WBI ("   gnat_argv : System.Address;");
2379            WBI ("   gnat_envp : System.Address;");
2380
2381            --  If the standard library is not suppressed, these variables
2382            --  are in the run-time data area for easy run time access.
2383
2384            if not Suppress_Standard_Library_On_Target then
2385               WBI ("");
2386               WBI ("   pragma Import (C, gnat_argc);");
2387               WBI ("   pragma Import (C, gnat_argv);");
2388               WBI ("   pragma Import (C, gnat_envp);");
2389            end if;
2390         end if;
2391
2392         --  Define exit status. Again in normal mode, this is in the run-time
2393         --  library, and is initialized there, but in the configurable
2394         --  run-time case, the variable is declared and initialized in this
2395         --  file.
2396
2397         WBI ("");
2398
2399         if Configurable_Run_Time_Mode then
2400            if Exit_Status_Supported_On_Target then
2401               WBI ("   gnat_exit_status : Integer := 0;");
2402            end if;
2403
2404         else
2405            WBI ("   gnat_exit_status : Integer;");
2406            WBI ("   pragma Import (C, gnat_exit_status);");
2407         end if;
2408
2409         --  Generate the GNAT_Version and Ada_Main_Program_Name info only for
2410         --  the main program. Otherwise, it can lead under some circumstances
2411         --  to a symbol duplication during the link (for instance when a C
2412         --  program uses two Ada libraries). Also zero terminate the string
2413         --  so that its end can be found reliably at run time.
2414
2415         if not Minimal_Binder then
2416            WBI ("");
2417            WBI ("   GNAT_Version : constant String :=");
2418            WBI ("                    """ & Ver_Prefix &
2419                                      Gnat_Version_String &
2420                                      """ & ASCII.NUL;");
2421            WBI ("   pragma Export (C, GNAT_Version, ""__gnat_version"");");
2422            WBI ("");
2423            WBI ("   GNAT_Version_Address : constant System.Address := " &
2424                 "GNAT_Version'Address;");
2425            WBI ("   pragma Export (C, GNAT_Version_Address, " &
2426                 """__gnat_version_address"");");
2427            WBI ("");
2428            Set_String ("   Ada_Main_Program_Name : constant String := """);
2429            Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2430
2431            Set_Main_Program_Name;
2432            Set_String (""" & ASCII.NUL;");
2433
2434            Write_Statement_Buffer;
2435
2436            WBI
2437              ("   pragma Export (C, Ada_Main_Program_Name, " &
2438               """__gnat_ada_main_program_name"");");
2439         end if;
2440      end if;
2441
2442      WBI ("");
2443      WBI ("   procedure " & Ada_Init_Name.all & ";");
2444      WBI ("   pragma Export (C, " & Ada_Init_Name.all & ", """ &
2445           Ada_Init_Name.all & """);");
2446
2447      --  If -a has been specified use pragma Linker_Constructor for the init
2448      --  procedure and pragma Linker_Destructor for the final procedure.
2449
2450      if Use_Pragma_Linker_Constructor then
2451         WBI ("   pragma Linker_Constructor (" & Ada_Init_Name.all & ");");
2452      end if;
2453
2454      if not Cumulative_Restrictions.Set (No_Finalization) then
2455         WBI ("");
2456         WBI ("   procedure " & Ada_Final_Name.all & ";");
2457         WBI ("   pragma Export (C, " & Ada_Final_Name.all & ", """ &
2458              Ada_Final_Name.all & """);");
2459
2460         if Use_Pragma_Linker_Constructor then
2461            WBI ("   pragma Linker_Destructor (" & Ada_Final_Name.all & ");");
2462         end if;
2463      end if;
2464
2465      if Bind_Main_Program then
2466
2467         WBI ("");
2468
2469         if Exit_Status_Supported_On_Target then
2470            Set_String ("   function ");
2471         else
2472            Set_String ("   procedure ");
2473         end if;
2474
2475         Set_String (Get_Main_Name);
2476
2477         --  Generate argument list if present
2478
2479         if Command_Line_Args_On_Target then
2480            Write_Statement_Buffer;
2481            WBI ("     (argc : Integer;");
2482            WBI ("      argv : System.Address;");
2483            Set_String
2484                ("      envp : System.Address)");
2485
2486            if Exit_Status_Supported_On_Target then
2487               Write_Statement_Buffer;
2488               WBI ("      return Integer;");
2489            else
2490               Write_Statement_Buffer (";");
2491            end if;
2492
2493         else
2494            if Exit_Status_Supported_On_Target then
2495               Write_Statement_Buffer (" return Integer;");
2496            else
2497               Write_Statement_Buffer (";");
2498            end if;
2499         end if;
2500
2501         WBI ("   pragma Export (C, " & Get_Main_Name & ", """ &
2502           Get_Main_Name & """);");
2503      end if;
2504
2505      --  Generate version numbers for units, only if needed. Be very safe on
2506      --  the condition.
2507
2508      if not Configurable_Run_Time_On_Target
2509        or else System_Version_Control_Used
2510        or else not Bind_Main_Program
2511      then
2512         Gen_Versions;
2513      end if;
2514
2515      Gen_Elab_Order (Elab_Order);
2516
2517      --  Spec is complete
2518
2519      WBI ("");
2520      WBI ("end " & Ada_Main & ";");
2521      Close_Binder_Output;
2522
2523      --  Prepare to write body
2524
2525      Create_Binder_Output (Filename, 'b', Bfileb);
2526
2527      --  We always compile the binder file in Ada 95 mode so that we properly
2528      --  handle use of Ada 2005 keywords as identifiers in Ada 95 mode. None
2529      --  of the Ada 2005/2012 constructs are needed by the binder file.
2530
2531      WBI ("pragma Warnings (Off);");
2532      WBI ("pragma Ada_95;");
2533
2534      --  Output Source_File_Name pragmas which look like
2535
2536      --    pragma Source_File_Name (Ada_Main, Spec_File_Name => "sss");
2537      --    pragma Source_File_Name (Ada_Main, Body_File_Name => "bbb");
2538
2539      --  where sss/bbb are the spec/body file names respectively
2540
2541      Get_Name_String (Bfiles);
2542      Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
2543
2544      WBI ("pragma Source_File_Name (" &
2545           Ada_Main &
2546           ", Spec_File_Name => """ &
2547           Name_Buffer (1 .. Name_Len + 3));
2548
2549      Get_Name_String (Bfileb);
2550      Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
2551
2552      WBI ("pragma Source_File_Name (" &
2553           Ada_Main &
2554           ", Body_File_Name => """ &
2555           Name_Buffer (1 .. Name_Len + 3));
2556
2557      --  Generate pragma Suppress (Overflow_Check). This is needed for recent
2558      --  versions of the compiler which have overflow checks on by default.
2559      --  We do not want overflow checking enabled for the increments of the
2560      --  elaboration variables (since this can cause an unwanted reference to
2561      --  the last chance exception handler for limited run-times).
2562
2563      WBI ("pragma Suppress (Overflow_Check);");
2564
2565      --  Generate with of System.Restrictions to initialize
2566      --  Run_Time_Restrictions.
2567
2568      if System_Restrictions_Used
2569        and not Suppress_Standard_Library_On_Target
2570      then
2571         WBI ("");
2572         WBI ("with System.Restrictions;");
2573      end if;
2574
2575      --  Generate with of Ada.Exceptions if needs library finalization
2576
2577      if Needs_Library_Finalization then
2578         WBI ("with Ada.Exceptions;");
2579      end if;
2580
2581      --  Generate with of System.Elaboration_Allocators if the restriction
2582      --  No_Standard_Allocators_After_Elaboration was present.
2583
2584      if Cumulative_Restrictions.Set
2585           (No_Standard_Allocators_After_Elaboration)
2586      then
2587         WBI ("with System.Elaboration_Allocators;");
2588      end if;
2589
2590      --  Generate start of package body
2591
2592      WBI ("");
2593      WBI ("package body " & Ada_Main & " is");
2594      WBI ("");
2595
2596      --  Generate externals for elaboration entities
2597
2598      Gen_Elab_Externals (Elab_Order);
2599
2600      --  Generate default-sized secondary stacks pool. At least one stack is
2601      --  created and assigned to the environment task if secondary stacks are
2602      --  used by the program.
2603
2604      if Sec_Stack_Used then
2605         Set_String ("   Sec_Default_Sized_Stacks");
2606         Set_String (" : array (1 .. ");
2607         Set_Int (Num_Sec_Stacks);
2608         Set_String (") of aliased System.Secondary_Stack.SS_Stack (");
2609
2610         if Opt.Default_Sec_Stack_Size /= No_Stack_Size then
2611            Set_Int (Opt.Default_Sec_Stack_Size);
2612         else
2613            Set_String ("System.Parameters.Runtime_Default_Sec_Stack_Size");
2614         end if;
2615
2616         Set_String (");");
2617         Write_Statement_Buffer;
2618         WBI ("");
2619      end if;
2620
2621      --  Generate reference
2622
2623      if not CodePeer_Mode then
2624         if not Suppress_Standard_Library_On_Target then
2625
2626            --  Generate Priority_Specific_Dispatching pragma string
2627
2628            Set_String
2629              ("   Local_Priority_Specific_Dispatching : " &
2630               "constant String := """);
2631
2632            for J in 0 .. PSD_Pragma_Settings.Last loop
2633               Set_Char (PSD_Pragma_Settings.Table (J));
2634            end loop;
2635
2636            Set_String (""";");
2637            Write_Statement_Buffer;
2638
2639            --  Generate Interrupt_State pragma string
2640
2641            Set_String ("   Local_Interrupt_States : constant String := """);
2642
2643            for J in 0 .. IS_Pragma_Settings.Last loop
2644               Set_Char (IS_Pragma_Settings.Table (J));
2645            end loop;
2646
2647            Set_String (""";");
2648            Write_Statement_Buffer;
2649            WBI ("");
2650         end if;
2651
2652         if not Suppress_Standard_Library_On_Target then
2653
2654            --  The B.1(39) implementation advice says that the adainit and
2655            --  adafinal routines should be idempotent. Generate a flag to
2656            --  ensure that. This is not needed if we are suppressing the
2657            --  standard library since it would never be referenced.
2658
2659            WBI ("   Is_Elaborated : Boolean := False;");
2660
2661            --  Generate bind environment string
2662
2663            Gen_Bind_Env_String;
2664         end if;
2665
2666         WBI ("");
2667      end if;
2668
2669      --  Generate the adafinal routine unless there is no finalization to do
2670
2671      if not Cumulative_Restrictions.Set (No_Finalization) then
2672         if Needs_Library_Finalization then
2673            Gen_Finalize_Library (Elab_Order);
2674         end if;
2675
2676         Gen_Adafinal;
2677      end if;
2678
2679      Gen_Adainit (Elab_Order);
2680
2681      if Bind_Main_Program then
2682         Gen_Main;
2683      end if;
2684
2685      --  Output object file list and the Ada body is complete
2686
2687      Gen_Object_Files_Options (Elab_Order);
2688
2689      WBI ("");
2690      WBI ("end " & Ada_Main & ";");
2691
2692      Close_Binder_Output;
2693   end Gen_Output_File_Ada;
2694
2695   ----------------------
2696   -- Gen_Restrictions --
2697   ----------------------
2698
2699   procedure Gen_Restrictions is
2700      Count : Integer;
2701
2702   begin
2703      if Suppress_Standard_Library_On_Target
2704        or not System_Restrictions_Used
2705      then
2706         return;
2707      end if;
2708
2709      WBI ("      System.Restrictions.Run_Time_Restrictions :=");
2710      WBI ("        (Set =>");
2711      Set_String      ("          (");
2712
2713      Count := 0;
2714
2715      for J in Cumulative_Restrictions.Set'Range loop
2716         Set_Boolean (Cumulative_Restrictions.Set (J));
2717         Set_String (", ");
2718         Count := Count + 1;
2719
2720         if J /= Cumulative_Restrictions.Set'Last and then Count = 8 then
2721            Write_Statement_Buffer;
2722            Set_String ("           ");
2723            Count := 0;
2724         end if;
2725      end loop;
2726
2727      Set_String_Replace ("),");
2728      Write_Statement_Buffer;
2729      Set_String ("         Value => (");
2730
2731      for J in Cumulative_Restrictions.Value'Range loop
2732         Set_Int (Int (Cumulative_Restrictions.Value (J)));
2733         Set_String (", ");
2734      end loop;
2735
2736      Set_String_Replace ("),");
2737      Write_Statement_Buffer;
2738      WBI ("         Violated =>");
2739      Set_String ("          (");
2740      Count := 0;
2741
2742      for J in Cumulative_Restrictions.Violated'Range loop
2743         Set_Boolean (Cumulative_Restrictions.Violated (J));
2744         Set_String (", ");
2745         Count := Count + 1;
2746
2747         if J /= Cumulative_Restrictions.Set'Last and then Count = 8 then
2748            Write_Statement_Buffer;
2749            Set_String ("           ");
2750            Count := 0;
2751         end if;
2752      end loop;
2753
2754      Set_String_Replace ("),");
2755      Write_Statement_Buffer;
2756      Set_String ("         Count => (");
2757
2758      for J in Cumulative_Restrictions.Count'Range loop
2759         Set_Int (Int (Cumulative_Restrictions.Count (J)));
2760         Set_String (", ");
2761      end loop;
2762
2763      Set_String_Replace ("),");
2764      Write_Statement_Buffer;
2765      Set_String ("         Unknown => (");
2766
2767      for J in Cumulative_Restrictions.Unknown'Range loop
2768         Set_Boolean (Cumulative_Restrictions.Unknown (J));
2769         Set_String (", ");
2770      end loop;
2771
2772      Set_String_Replace ("))");
2773      Set_String (";");
2774      Write_Statement_Buffer;
2775   end Gen_Restrictions;
2776
2777   ------------------
2778   -- Gen_Versions --
2779   ------------------
2780
2781   --  This routine generates lines such as:
2782
2783   --    unnnnn : constant Integer := 16#hhhhhhhh#;
2784   --    pragma Export (C, unnnnn, unam);
2785
2786   --  for each unit, where unam is the unit name suffixed by either B or S for
2787   --  body or spec, with dots replaced by double underscores, and hhhhhhhh is
2788   --  the version number, and nnnnn is a 5-digits serial number.
2789
2790   procedure Gen_Versions is
2791      Ubuf : String (1 .. 6) := "u00000";
2792
2793      procedure Increment_Ubuf;
2794      --  Little procedure to increment the serial number
2795
2796      --------------------
2797      -- Increment_Ubuf --
2798      --------------------
2799
2800      procedure Increment_Ubuf is
2801      begin
2802         for J in reverse Ubuf'Range loop
2803            Ubuf (J) := Character'Succ (Ubuf (J));
2804            exit when Ubuf (J) <= '9';
2805            Ubuf (J) := '0';
2806         end loop;
2807      end Increment_Ubuf;
2808
2809   --  Start of processing for Gen_Versions
2810
2811   begin
2812      WBI ("");
2813
2814      WBI ("   type Version_32 is mod 2 ** 32;");
2815      for U in Units.First .. Units.Last loop
2816         if not Units.Table (U).SAL_Interface
2817           and then (not Bind_For_Library
2818                      or else Units.Table (U).Directly_Scanned)
2819         then
2820            Increment_Ubuf;
2821            WBI ("   " & Ubuf & " : constant Version_32 := 16#" &
2822                 Units.Table (U).Version & "#;");
2823            Set_String ("   pragma Export (C, ");
2824            Set_String (Ubuf);
2825            Set_String (", """);
2826
2827            Get_Name_String (Units.Table (U).Uname);
2828
2829            for K in 1 .. Name_Len loop
2830               if Name_Buffer (K) = '.' then
2831                  Set_Char ('_');
2832                  Set_Char ('_');
2833
2834               elsif Name_Buffer (K) = '%' then
2835                  exit;
2836
2837               else
2838                  Set_Char (Name_Buffer (K));
2839               end if;
2840            end loop;
2841
2842            if Name_Buffer (Name_Len) = 's' then
2843               Set_Char ('S');
2844            else
2845               Set_Char ('B');
2846            end if;
2847
2848            Set_String (""");");
2849            Write_Statement_Buffer;
2850         end if;
2851      end loop;
2852   end Gen_Versions;
2853
2854   ------------------------
2855   -- Get_Main_Unit_Name --
2856   ------------------------
2857
2858   function Get_Main_Unit_Name (S : String) return String is
2859      Result : String := S;
2860
2861   begin
2862      for J in S'Range loop
2863         if Result (J) = '.' then
2864            Result (J) := '_';
2865         end if;
2866      end loop;
2867
2868      return Result;
2869   end Get_Main_Unit_Name;
2870
2871   -----------------------
2872   -- Get_Ada_Main_Name --
2873   -----------------------
2874
2875   function Get_Ada_Main_Name return String is
2876      Suffix : constant String := "_00";
2877      Name   : String (1 .. Opt.Ada_Main_Name.all'Length + Suffix'Length) :=
2878                 Opt.Ada_Main_Name.all & Suffix;
2879      Nlen   : Natural;
2880
2881   begin
2882      --  For CodePeer, we want reproducible names (independent of other mains
2883      --  that may or may not be present) that don't collide when analyzing
2884      --  multiple mains and which are easily recognizable as "ada_main" names.
2885
2886      if CodePeer_Mode then
2887         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2888
2889         return
2890           "ada_main_for_" &
2891             Get_Main_Unit_Name (Name_Buffer (1 .. Name_Len - 2));
2892      end if;
2893
2894      --  This loop tries the following possibilities in order
2895      --    <Ada_Main>
2896      --    <Ada_Main>_01
2897      --    <Ada_Main>_02
2898      --    ..
2899      --    <Ada_Main>_99
2900      --  where <Ada_Main> is equal to Opt.Ada_Main_Name. By default,
2901      --  it is set to 'ada_main'.
2902
2903      for J in 0 .. 99 loop
2904         if J = 0 then
2905            Nlen := Name'Length - Suffix'Length;
2906         else
2907            Nlen := Name'Length;
2908            Name (Name'Last) := Character'Val (J mod 10 + Character'Pos ('0'));
2909            Name (Name'Last - 1) :=
2910              Character'Val (J /   10 + Character'Pos ('0'));
2911         end if;
2912
2913         for K in ALIs.First .. ALIs.Last loop
2914            for L in ALIs.Table (K).First_Unit .. ALIs.Table (K).Last_Unit loop
2915
2916               --  Get unit name, removing %b or %e at end
2917
2918               Get_Name_String (Units.Table (L).Uname);
2919               Name_Len := Name_Len - 2;
2920
2921               if Name_Buffer (1 .. Name_Len) = Name (1 .. Nlen) then
2922                  goto Continue;
2923               end if;
2924            end loop;
2925         end loop;
2926
2927         return Name (1 .. Nlen);
2928
2929      <<Continue>>
2930         null;
2931      end loop;
2932
2933      --  If we fall through, just use a peculiar unlikely name
2934
2935      return ("Qwertyuiop");
2936   end Get_Ada_Main_Name;
2937
2938   -------------------
2939   -- Get_Main_Name --
2940   -------------------
2941
2942   function Get_Main_Name return String is
2943   begin
2944      --  Explicit name given with -M switch
2945
2946      if Bind_Alternate_Main_Name then
2947         return Alternate_Main_Name.all;
2948
2949      --  Case of main program name to be used directly
2950
2951      elsif Use_Ada_Main_Program_Name_On_Target then
2952
2953         --  Get main program name
2954
2955         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2956
2957         --  If this is a child name, return only the name of the child, since
2958         --  we can't have dots in a nested program name. Note that we do not
2959         --  include the %b at the end of the unit name.
2960
2961         for J in reverse 1 .. Name_Len - 2 loop
2962            if J = 1 or else Name_Buffer (J - 1) = '.' then
2963               return Name_Buffer (J .. Name_Len - 2);
2964            end if;
2965         end loop;
2966
2967         raise Program_Error; -- impossible exit
2968
2969      --  Case where "main" is to be used as default
2970
2971      else
2972         return "main";
2973      end if;
2974   end Get_Main_Name;
2975
2976   ---------------------
2977   -- Get_WC_Encoding --
2978   ---------------------
2979
2980   function Get_WC_Encoding return Character is
2981   begin
2982      --  If encoding method specified by -W switch, then return it
2983
2984      if Wide_Character_Encoding_Method_Specified then
2985         return WC_Encoding_Letters (Wide_Character_Encoding_Method);
2986
2987      --  If no main program, and not specified, set brackets, we really have
2988      --  no better choice. If some other encoding is required when there is
2989      --  no main, it must be set explicitly using -Wx.
2990
2991      --  Note: if the ALI file always passed the wide character encoding of
2992      --  every file, then we could use the encoding of the initial specified
2993      --  file, but this information is passed only for potential main
2994      --  programs. We could fix this sometime, but it is a very minor point
2995      --  (wide character default encoding for [Wide_[Wide_]]Text_IO when there
2996      --  is no main program).
2997
2998      elsif No_Main_Subprogram then
2999         return 'b';
3000
3001      --  Otherwise if there is a main program, take encoding from it
3002
3003      else
3004         return ALIs.Table (ALIs.First).WC_Encoding;
3005      end if;
3006   end Get_WC_Encoding;
3007
3008   -------------------
3009   -- Has_Finalizer --
3010   -------------------
3011
3012   function Has_Finalizer (Elab_Order : Unit_Id_Array) return Boolean is
3013      U     : Unit_Record;
3014      Unum  : Unit_Id;
3015
3016   begin
3017      for E in reverse Elab_Order'Range loop
3018         Unum := Elab_Order (E);
3019         U    := Units.Table (Unum);
3020
3021         --  We are only interested in non-generic packages
3022
3023         if U.Unit_Kind = 'p'
3024           and then U.Has_Finalizer
3025           and then not U.Is_Generic
3026           and then not U.No_Elab
3027         then
3028            return True;
3029         end if;
3030      end loop;
3031
3032      return False;
3033   end Has_Finalizer;
3034
3035   ----------
3036   -- Hash --
3037   ----------
3038
3039   function Hash (Nam : Name_Id) return Header_Num is
3040   begin
3041      return Int (Nam - Names_Low_Bound) rem Header_Num'Last;
3042   end Hash;
3043
3044   ----------------------
3045   -- Lt_Linker_Option --
3046   ----------------------
3047
3048   function Lt_Linker_Option (Op1 : Natural; Op2 : Natural) return Boolean is
3049   begin
3050      --  Sort internal files last
3051
3052      if Linker_Options.Table (Op1).Internal_File
3053           /=
3054         Linker_Options.Table (Op2).Internal_File
3055      then
3056         --  Note: following test uses False < True
3057
3058         return Linker_Options.Table (Op1).Internal_File
3059                  <
3060                Linker_Options.Table (Op2).Internal_File;
3061
3062      --  If both internal or both non-internal, sort according to the
3063      --  elaboration position. A unit that is elaborated later should come
3064      --  earlier in the linker options list.
3065
3066      else
3067         return Units.Table (Linker_Options.Table (Op1).Unit).Elab_Position
3068                  >
3069                Units.Table (Linker_Options.Table (Op2).Unit).Elab_Position;
3070      end if;
3071   end Lt_Linker_Option;
3072
3073   ------------------------
3074   -- Move_Linker_Option --
3075   ------------------------
3076
3077   procedure Move_Linker_Option (From : Natural; To : Natural) is
3078   begin
3079      Linker_Options.Table (To) := Linker_Options.Table (From);
3080   end Move_Linker_Option;
3081
3082   ----------------------------
3083   -- Resolve_Binder_Options --
3084   ----------------------------
3085
3086   procedure Resolve_Binder_Options (Elab_Order : Unit_Id_Array) is
3087      procedure Check_Package (Var : in out Boolean; Name : String);
3088      --  Set Var to true iff the current identifier in Namet is Name. Do
3089      --  nothing if it doesn't match. This procedure is just a helper to
3090      --  avoid explicitly dealing with length.
3091
3092      -------------------
3093      -- Check_Package --
3094      -------------------
3095
3096      procedure Check_Package (Var : in out Boolean; Name : String) is
3097      begin
3098         if Name_Len = Name'Length
3099           and then Name_Buffer (1 .. Name_Len) = Name
3100         then
3101            Var := True;
3102         end if;
3103      end Check_Package;
3104
3105   --  Start of processing for Resolve_Binder_Options
3106
3107   begin
3108      for E in Elab_Order'Range loop
3109         Get_Name_String (Units.Table (Elab_Order (E)).Uname);
3110
3111         --  This is not a perfect approach, but is the current protocol
3112         --  between the run-time and the binder to indicate that tasking is
3113         --  used: System.OS_Interface should always be used by any tasking
3114         --  application.
3115
3116         Check_Package (With_GNARL, "system.os_interface%s");
3117
3118         --  Ditto for the use of restricted tasking
3119
3120         Check_Package
3121           (System_Tasking_Restricted_Stages_Used,
3122            "system.tasking.restricted.stages%s");
3123
3124         --  Ditto for the use of interrupts
3125
3126         Check_Package (System_Interrupts_Used, "system.interrupts%s");
3127
3128         --  Ditto for the use of dispatching domains
3129
3130         Check_Package
3131           (Dispatching_Domains_Used,
3132            "system.multiprocessors.dispatching_domains%s");
3133
3134         --  Ditto for the use of restrictions
3135
3136         Check_Package (System_Restrictions_Used, "system.restrictions%s");
3137
3138         --  Ditto for the use of System.Secondary_Stack
3139
3140         Check_Package
3141           (System_Secondary_Stack_Package_In_Closure,
3142            "system.secondary_stack%s");
3143
3144         --  Ditto for use of an SMP bareboard runtime
3145
3146         Check_Package (System_BB_CPU_Primitives_Multiprocessors_Used,
3147                        "system.bb.cpu_primitives.multiprocessors%s");
3148
3149         --  Ditto for System.Version_Control, which is used for Version and
3150         --  Body_Version attributes.
3151
3152         Check_Package (System_Version_Control_Used,
3153                        "system.version_control%s");
3154      end loop;
3155   end Resolve_Binder_Options;
3156
3157   ------------------
3158   -- Set_Bind_Env --
3159   ------------------
3160
3161   procedure Set_Bind_Env (Key, Value : String) is
3162   begin
3163      --  The lengths of Key and Value are stored as single bytes
3164
3165      if Key'Length > 255 then
3166         Osint.Fail ("bind environment key """ & Key & """ too long");
3167      end if;
3168
3169      if Value'Length > 255 then
3170         Osint.Fail ("bind environment value """ & Value & """ too long");
3171      end if;
3172
3173      Bind_Environment.Set (Name_Find (Key), Name_Find (Value));
3174   end Set_Bind_Env;
3175
3176   -----------------
3177   -- Set_Boolean --
3178   -----------------
3179
3180   procedure Set_Boolean (B : Boolean) is
3181      False_Str : constant String := "False";
3182      True_Str  : constant String := "True";
3183
3184   begin
3185      if B then
3186         Statement_Buffer (Stm_Last + 1 .. Stm_Last + True_Str'Length) :=
3187           True_Str;
3188         Stm_Last := Stm_Last + True_Str'Length;
3189      else
3190         Statement_Buffer (Stm_Last + 1 .. Stm_Last + False_Str'Length) :=
3191           False_Str;
3192         Stm_Last := Stm_Last + False_Str'Length;
3193      end if;
3194   end Set_Boolean;
3195
3196   --------------
3197   -- Set_Char --
3198   --------------
3199
3200   procedure Set_Char (C : Character) is
3201   begin
3202      Stm_Last := Stm_Last + 1;
3203      Statement_Buffer (Stm_Last) := C;
3204   end Set_Char;
3205
3206   -------------
3207   -- Set_Int --
3208   -------------
3209
3210   procedure Set_Int (N : Int) is
3211   begin
3212      if N < 0 then
3213         Set_String ("-");
3214         Set_Int (-N);
3215
3216      else
3217         if N > 9 then
3218            Set_Int (N / 10);
3219         end if;
3220
3221         Stm_Last := Stm_Last + 1;
3222         Statement_Buffer (Stm_Last) :=
3223           Character'Val (N mod 10 + Character'Pos ('0'));
3224      end if;
3225   end Set_Int;
3226
3227   -------------------------
3228   -- Set_IS_Pragma_Table --
3229   -------------------------
3230
3231   procedure Set_IS_Pragma_Table is
3232   begin
3233      for F in ALIs.First .. ALIs.Last loop
3234         for K in ALIs.Table (F).First_Interrupt_State ..
3235                  ALIs.Table (F).Last_Interrupt_State
3236         loop
3237            declare
3238               Inum : constant Int :=
3239                        Interrupt_States.Table (K).Interrupt_Id;
3240               Stat : constant Character :=
3241                        Interrupt_States.Table (K).Interrupt_State;
3242
3243            begin
3244               while IS_Pragma_Settings.Last < Inum loop
3245                  IS_Pragma_Settings.Append ('n');
3246               end loop;
3247
3248               IS_Pragma_Settings.Table (Inum) := Stat;
3249            end;
3250         end loop;
3251      end loop;
3252   end Set_IS_Pragma_Table;
3253
3254   ---------------------------
3255   -- Set_Main_Program_Name --
3256   ---------------------------
3257
3258   procedure Set_Main_Program_Name is
3259   begin
3260      --  Note that name has %b on the end which we ignore
3261
3262      --  First we output the initial _ada_ since we know that the main program
3263      --  is a library level subprogram.
3264
3265      Set_String ("_ada_");
3266
3267      --  Copy name, changing dots to double underscores
3268
3269      for J in 1 .. Name_Len - 2 loop
3270         if Name_Buffer (J) = '.' then
3271            Set_String ("__");
3272         else
3273            Set_Char (Name_Buffer (J));
3274         end if;
3275      end loop;
3276   end Set_Main_Program_Name;
3277
3278   ---------------------
3279   -- Set_Name_Buffer --
3280   ---------------------
3281
3282   procedure Set_Name_Buffer is
3283   begin
3284      for J in 1 .. Name_Len loop
3285         Set_Char (Name_Buffer (J));
3286      end loop;
3287   end Set_Name_Buffer;
3288
3289   -------------------------
3290   -- Set_PSD_Pragma_Table --
3291   -------------------------
3292
3293   procedure Set_PSD_Pragma_Table is
3294   begin
3295      for F in ALIs.First .. ALIs.Last loop
3296         for K in ALIs.Table (F).First_Specific_Dispatching ..
3297                  ALIs.Table (F).Last_Specific_Dispatching
3298         loop
3299            declare
3300               DTK : Specific_Dispatching_Record
3301                       renames Specific_Dispatching.Table (K);
3302
3303            begin
3304               while PSD_Pragma_Settings.Last < DTK.Last_Priority loop
3305                  PSD_Pragma_Settings.Append ('F');
3306               end loop;
3307
3308               for Prio in DTK.First_Priority .. DTK.Last_Priority loop
3309                  PSD_Pragma_Settings.Table (Prio) := DTK.Dispatching_Policy;
3310               end loop;
3311            end;
3312         end loop;
3313      end loop;
3314   end Set_PSD_Pragma_Table;
3315
3316   ----------------
3317   -- Set_String --
3318   ----------------
3319
3320   procedure Set_String (S : String) is
3321   begin
3322      Statement_Buffer (Stm_Last + 1 .. Stm_Last + S'Length) := S;
3323      Stm_Last := Stm_Last + S'Length;
3324   end Set_String;
3325
3326   ------------------------
3327   -- Set_String_Replace --
3328   ------------------------
3329
3330   procedure Set_String_Replace (S : String) is
3331   begin
3332      Statement_Buffer (Stm_Last - S'Length + 1 .. Stm_Last) := S;
3333   end Set_String_Replace;
3334
3335   -------------------
3336   -- Set_Unit_Name --
3337   -------------------
3338
3339   procedure Set_Unit_Name is
3340   begin
3341      for J in 1 .. Name_Len - 2 loop
3342         if Name_Buffer (J) = '.' then
3343            Set_String ("__");
3344         else
3345            Set_Char (Name_Buffer (J));
3346         end if;
3347      end loop;
3348   end Set_Unit_Name;
3349
3350   ---------------------
3351   -- Set_Unit_Number --
3352   ---------------------
3353
3354   procedure Set_Unit_Number (U : Unit_Id) is
3355      Num_Units : constant Nat := Nat (Units.Last) - Nat (Unit_Id'First);
3356      Unum      : constant Nat := Nat (U) - Nat (Unit_Id'First);
3357
3358   begin
3359      if Num_Units >= 10 and then Unum < 10 then
3360         Set_Char ('0');
3361      end if;
3362
3363      if Num_Units >= 100 and then Unum < 100 then
3364         Set_Char ('0');
3365      end if;
3366
3367      Set_Int (Unum);
3368   end Set_Unit_Number;
3369
3370   ---------------------
3371   -- Write_Bind_Line --
3372   ---------------------
3373
3374   procedure Write_Bind_Line (S : String) is
3375   begin
3376      --  Need to strip trailing LF from S
3377
3378      WBI (S (S'First .. S'Last - 1));
3379   end Write_Bind_Line;
3380
3381   ----------------------------
3382   -- Write_Statement_Buffer --
3383   ----------------------------
3384
3385   procedure Write_Statement_Buffer is
3386   begin
3387      WBI (Statement_Buffer (1 .. Stm_Last));
3388      Stm_Last := 0;
3389   end Write_Statement_Buffer;
3390
3391   procedure Write_Statement_Buffer (S : String) is
3392   begin
3393      Set_String (S);
3394      Write_Statement_Buffer;
3395   end Write_Statement_Buffer;
3396
3397end Bindgen;
3398