[Ada] Fix C binder generated file on AIX

Arnaud Charlet charlet@adacore.com
Wed Feb 15 10:11:00 GMT 2006


Tested on i686-linux, committed on trunk

GNAT generates during the bind a symbol named __gnat_ada_main_program_name.
This symbol is used by the debugger to implement the "start" command for
Ada. Certain linkers have the capability to remove unused symbols from the
executable, so in order to avoid this from happening, the binder generates
a dummy variable named ensure_reference that takes the address of our symbol.
Unfortunately, compiling the binder file with optimization defeats that
variable since the compiler notices easily that this variable is unused
and can therefore be removed. A few weeks ago, we modified the Ada binder
file to make this variable aliased and volatile. This change makes the
corresponding update to the C binder file, by declaring the variable as
volatile, thus telling the compiler that this variable should not be
removed.

Using the following example:

        procedure Foo is
        begin
           null;
        end Foo;

And then compiling it with:

        % gnatmake -g -O foo

Here is what happens on AIX when debugging the program with GDB:             

        % gdb foo
        (gdb) start
        Breakpoint 1 at 0x10000478: file b~foo.adb, line 96.
        Starting program: /[...]/foo
        main (argc=1, argv=(system.address) 0x2ff22854,
            envp=(system.address) 0x2ff2285c) at b~foo.adb:96                   
        96            gnat_argc := argc;

After this change is applied, the debugger will stop inside procedure           
Foo, as expected.

2006-02-13  Joel Brobecker  <brobecke@adacore.com>

	* bindgen.adb (Gen_Main_C): declare the ensure_reference variable as
	volatile, to tell the compiler to preserve this variable at any level
	of optimization.
	(Gen_Versions_Ada): Temporarily work around codegen bug.

-------------- next part --------------
Index: bindgen.adb
===================================================================
--- bindgen.adb	(revision 110833)
+++ bindgen.adb	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2005, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2006, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -347,7 +347,7 @@
 
    procedure Gen_Adafinal_C is
    begin
-      WBI ("void " & Ada_Final_Name.all & " () {");
+      WBI ("void " & Ada_Final_Name.all & " (void) {");
       WBI ("   system__standard_library__adafinal ();");
       WBI ("}");
       WBI ("");
@@ -523,7 +523,8 @@
          WBI ("         Unreserve_All_Interrupts : Integer;");
          WBI ("         Exception_Tracebacks     : Integer;");
          WBI ("         Zero_Cost_Exceptions     : Integer;");
-         WBI ("         Detect_Blocking          : Integer);");
+         WBI ("         Detect_Blocking          : Integer;");
+         WBI ("         Default_Stack_Size       : Integer);");
          WBI ("      pragma Import (C, Set_Globals, ""__gnat_set_globals"");");
 
          --  Import entry point for elaboration time signal handler
@@ -632,6 +633,12 @@
             Set_Int (0);
          end if;
 
+         Set_String (",");
+         Write_Statement_Buffer;
+
+         Set_String ("         Default_Stack_Size       => ");
+         Set_Int (Default_Stack_Size);
+
          Set_String (");");
          Write_Statement_Buffer;
 
@@ -876,10 +883,18 @@
             Set_Int (0);
          end if;
 
-         Set_String (");");
+         Set_String (",");
          Tab_To (24);
          Set_String ("/* Detect_Blocking            */");
          Write_Statement_Buffer;
+
+         Set_String ("      ");
+         Set_Int    (Default_Stack_Size);
+         Set_String (");");
+         Tab_To (24);
+         Set_String ("/* Default_Stack_Size     */");
+         Write_Statement_Buffer;
+
          WBI ("");
 
          --  Install elaboration time signal handler
@@ -1334,10 +1349,15 @@
       --  The reference stops Ada_Main_Program_Name from being optimized
       --  away by smart linkers, such as the AiX linker.
 
+      --  Because this variable is unused, we make this variable "aliased"
+      --  with a pragma Volatile in order to tell the compiler to preserve
+      --  this variable at any level of optimization.
+
       if Bind_Main_Program then
          WBI
-           ("      Ensure_Reference : System.Address := " &
+           ("      Ensure_Reference : aliased System.Address := " &
             "Ada_Main_Program_Name'Address;");
+         WBI ("      pragma Volatile (Ensure_Reference);");
          WBI ("");
       end if;
 
@@ -1471,7 +1491,7 @@
       --  Case of no command line arguments on target
 
       else
-         Write_Statement_Buffer (" ()");
+         Write_Statement_Buffer (" (void)");
       end if;
 
       WBI ("{");
@@ -1482,8 +1502,13 @@
       --  place). The reference stops Ada_Main_Program_Name from being
       --  optimized away by smart linkers, such as the AiX linker.
 
+      --  Because this variable is unused, we declare this variable as
+      --  volatile in order to tell the compiler to preserve it at any
+      --  level of optimization.
+
       if Bind_Main_Program then
-         WBI ("   char *ensure_reference __attribute__ ((__unused__)) = " &
+         WBI ("   char * volatile ensure_reference " &
+              "__attribute__ ((__unused__)) = " &
               "__gnat_ada_main_program_name;");
          WBI ("");
 
@@ -1826,7 +1851,13 @@
 
          if With_DECGNAT then
             Name_Len := 0;
-            Add_Str_To_Name_Buffer ("-ldecgnat");
+
+            if Opt.Shared_Libgnat then
+               Add_Str_To_Name_Buffer (Shared_Lib ("decgnat"));
+            else
+               Add_Str_To_Name_Buffer ("-ldecgnat");
+            end if;
+
             Write_Linker_Option;
          end if;
 
@@ -2229,7 +2260,7 @@
       WBI ("extern void __gnat_set_globals");
       WBI ("  (int, int, char, char, char, char,");
       WBI ("   const char *, const char *,");
-      WBI ("   int, int, int, int, int);");
+      WBI ("   int, int, int, int, int, int);");
 
       if Use_Pragma_Linker_Constructor then
          WBI ("extern void " & Ada_Final_Name.all &
@@ -2361,7 +2392,7 @@
 
       if Suppress_Standard_Library_On_Target then
          WBI ("");
-         WBI ("void __gnat_break_start () {}");
+         WBI ("void __gnat_break_start (void) {}");
       end if;
 
       --  Generate the __gnat_version and __gnat_ada_main_program_name info
@@ -2507,8 +2538,14 @@
       end loop;
 
       WBI ("");
-      Ubuf := "u00000";
 
+      --  We used to have more complex code: Ubuf := "u00000";
+      --  which was being miscompiled, so use simpler code instead:
+
+      for J in Ubuf'First + 1 .. Ubuf'Last loop
+         Ubuf (J) := '0';
+      end loop;
+
       for U in Units.First .. Units.Last loop
          Increment_Ubuf;
          Set_String ("   pragma Export (C, ");


More information about the Gcc-patches mailing list