This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

AIX collect2


This patch improves  64 bit linking and static constructors/ destructors
on AIX.

For 64 bit linking the environmental variable LD_EMULATION is set to
aixppc64.  This was done instead of mapping -b64 to -maixppc64, because
doing so would break native linking.

On AIX static constuctors/desctructors are handled with a special symbol
__rtinit.   This is -binitfini:<init func>:<fini func>  on the native
linker.  This symbol is now emitted.

The usual testsuite does not explicitly look for the __rtinit symbol.
I have created a test.  Since it is device dependent, I placed it in a
new dir.  g++.dd/rs6000.

Tom

--
Tom Rix
GCC Engineer
trix@redhat.com
256.704.9201


2001-10-17  Tom Rix  <trix@redhat.com>

	* collect2.c (main): Set LDEMULATION to aixpp64 for -b64.
	(collect_exit): Restore LDEMULATION.
	(ld_rtinit_print): New function.  Writes out special AIX __rtinit 
	symbol.
	(write_c_file_stat): Call ld_rtinit_print. 

	* config/rs6000/aix51.h : Define LD_RTINIT.
	* config/rs6000/aix43.h : Define LD_RTINIT.

2001-10-17  Tom Rix  <trix@redhat.com>

	* g++.dd/rs6000/rs6000.exp: New driver for AIX specific g++ tests.
	* g++.dd/rs6000/hello.C: New test.  Exercises special AIX __rtinit 
	symbol emitted by collect2.
	
diff -rc -N -x *~ gcc-old/collect2.c gcc/collect2.c
*** gcc-old/collect2.c	Fri Oct 12 21:30:17 2001
--- gcc/collect2.c	Wed Oct 17 19:56:57 2001
***************
*** 199,204 ****
--- 199,205 ----
  #ifdef COLLECT_EXPORT_LIST
  static int export_flag;                 /* true if -bE */
  static int aix64_flag;			/* true if -b64 */
+ static char *old_aix_emulation_saved = NULL;
  #endif
  
  int debug;				/* true if -debug */
***************
*** 344,349 ****
--- 345,357 ----
  #ifdef COLLECT_EXPORT_LIST
    if (export_file != 0 && export_file[0])
      maybe_unlink (export_file);
+ 
+   /* Reset the LDEMULATION environmental variable.  */
+   if (NULL != old_aix_emulation_saved) 
+     {
+       setenv ("LDEMULATION", old_aix_emulation_saved, 1);
+     }
+ 
  #endif
  
    if (ldout != 0 && ldout[0])
***************
*** 1120,1127 ****
  	    case 'b':
  	      if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
                  export_flag = 1;
! 	      else if (arg[2] == '6' && arg[3] == '4')
! 		aix64_flag = 1;
  	      break;
  #endif
  
--- 1128,1166 ----
  	    case 'b':
  	      if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
                  export_flag = 1;
! 	      else if (arg[2] == '6' && arg[3] == '4') 
! 		{
! 		  static char *old_aix_emulation; 
! 		  char *var = "LDEMULATION=";
! 		  int status = 0;
! 
! 		  aix64_flag = 1;
! 
! 		  old_aix_emulation = getenv("LDEMULATION");
! 		  if (NULL != old_aix_emulation) 
! 		    {
! 		      size_t size = strlen(old_aix_emulation) + 
! 			strlen(var) + 1;
! 		      old_aix_emulation_saved = (char *)malloc(size);
! 		      
! 		      if (NULL != old_aix_emulation_saved) 
! 			{
! 			  sprintf(old_aix_emulation_saved, "%s%s", var, 
! 				  old_aix_emulation);
! 			} 
! 		    } 
! 		  else 
! 		    {
! 		      old_aix_emulation_saved = NULL;
! 		    }
! 		  
! 		  status = putenv("LDEMULATION=aixppc64");
! 
! 		  if (status) 
! 		    {
! 		      fatal_perror ("Unable to set environment variable LDEMULATION");
! 		    } 
! 		}
  	      break;
  #endif
  
***************
*** 1824,1829 ****
--- 1863,1936 ----
      }
  }
  
+ #ifdef LD_RTINIT
+ /* To support the -binitfini option in the gnu linker, the __rtinit symbol 
+    must be defined.  For more information on __rtinit, see the linker 
+    emulation script aix.em.  */
+ 
+ static void 
+ ld_rtinit_print(stream, initname, fininame) 
+      FILE *stream;
+      char *initname;
+      char *fininame;
+ {
+   unsigned int i;
+   fprintf (stream, "__asm__ (\"\n");
+   fprintf (stream, ".csect .data[RW],3\n");
+   fprintf (stream, "	.globl __rtinit\n");
+   fprintf (stream, "	.extern %s\n", initname);
+   fprintf (stream, "	.extern %s\n", fininame);
+   fprintf (stream, "__rtinit:\n");
+   if (aix64_flag) {
+     fprintf (stream, "	.llong 0\n");
+   } else {
+     fprintf (stream, "	.long 0\n");
+   }
+   fprintf (stream, "	.long f1i - __rtinit\n");
+   fprintf (stream, "	.long f1f - __rtinit\n");
+   fprintf (stream, "	.long f2i - f1i\n");
+   fprintf (stream, "	.align 3\n");
+   if (aix64_flag) {  
+     fprintf (stream, "f1i:	.llong %s\n", initname);
+   } else {
+     fprintf (stream, "f1i:	.long %s\n", initname);
+   }
+   fprintf (stream, "	.long s1i - __rtinit\n");
+   fprintf (stream, "	.long 0\n");
+   if (aix64_flag) {  
+     fprintf (stream, "f2i:	.llong 0\n");
+   } else {
+     fprintf (stream, "f2i:	.long 0\n");
+   }
+   fprintf (stream, "	.long 0\n");
+   fprintf (stream, "	.long 0\n");
+   if (aix64_flag) {    
+     fprintf (stream, "f1f:	.llong %s\n", fininame);
+   } else {
+     fprintf (stream, "f1f:	.long %s\n", fininame);
+   }
+   fprintf (stream, "	.long s1f - __rtinit\n");
+   fprintf (stream, "	.long 0\n");
+   if (aix64_flag) {  
+     fprintf (stream, "f2f:	.llong 0\n");
+   } else {
+     fprintf (stream, "f2f:	.long 0\n");
+   }
+   fprintf (stream, "	.long 0\n");
+   fprintf (stream, "	.long 0\n");
+   fprintf (stream, "	.align 3\n");
+   fprintf (stream, "s1i:\n");
+   for (i = 0; i <= strlen(initname); i++)
+     fprintf (stream, "        .byte %u\n", initname[i]);
+   fprintf (stream, "	.align 3\n");
+   fprintf (stream, "s1f:\n");
+   for (i = 0; i <= strlen(fininame); i++)
+     fprintf (stream, "        .byte %u\n", fininame[i]);
+   fprintf (stream, "\");\n");
+ 
+ }
+ #endif
+ 
  /* Write out the constructor and destructor tables statically (for a shared
     object), along with the functions to execute them.  */
  
***************
*** 1953,1958 ****
--- 2060,2071 ----
        fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
        fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
      }
+ 
+ #ifdef LD_RTINIT
+   /* AIX gnu linker needs to have the special symbol __rtinit defined.  */
+   ld_rtinit_print(stream, initname, fininame);
+ #endif
+ 
  }
  
  /* Write the constructor/destructor tables.  */
diff -rc -N -x *~ gcc-old/config/rs6000/aix43.h gcc/config/rs6000/aix43.h
*** gcc-old/config/rs6000/aix43.h	Fri Oct 12 21:31:40 2001
--- gcc/config/rs6000/aix43.h	Fri Oct 12 21:50:09 2001
***************
*** 221,223 ****
--- 221,227 ----
  
  #undef LD_INIT_SWITCH
  #define LD_INIT_SWITCH "-binitfini"
+ 
+ /* So collect2.c generates the __rtinit symbol. */
+ #undef LD_RTINIT
+ #define LD_RTINIT
diff -rc -N -x *~ gcc-old/config/rs6000/aix51.h gcc/config/rs6000/aix51.h
*** gcc-old/config/rs6000/aix51.h	Fri Oct 12 21:31:40 2001
--- gcc/config/rs6000/aix51.h	Fri Oct 12 21:50:09 2001
***************
*** 233,235 ****
--- 233,239 ----
  
  #undef LD_INIT_SWITCH
  #define LD_INIT_SWITCH "-binitfini"
+ 
+ /* So collect2.c generates the __rtinit symbol. */
+ #undef LD_RTINIT
+ #define LD_RTINIT
diff -rc -N -x *~ gcc-old/testsuite/g++.dd/rs6000/hello.C gcc/testsuite/g++.dd/rs6000/hello.C
*** gcc-old/testsuite/g++.dd/rs6000/hello.C	Wed Dec 31 16:00:00 1969
--- gcc/testsuite/g++.dd/rs6000/hello.C	Sun Oct 14 23:26:00 2001
***************
*** 0 ****
--- 1,27 ----
+ #include <stdio.h>
+ 
+ class foo {
+ public:
+   int i;
+   foo() {
+     i=0;
+     printf("Init %d\n", i);
+     i++;
+   };
+   ~foo() {
+     printf("Fini %d\n", i);
+     i++;
+   };
+ };
+ 
+ static class foo bar;
+ 
+ int
+ main() 
+ {
+   printf("Hello World %d\n", bar.i);
+   bar.i++;
+   return 0;
+ }
+ 
+ 
diff -rc -N -x *~ gcc-old/testsuite/g++.dd/rs6000/rs6000.exp gcc/testsuite/g++.dd/rs6000/rs6000.exp
*** gcc-old/testsuite/g++.dd/rs6000/rs6000.exp	Wed Dec 31 16:00:00 1969
--- gcc/testsuite/g++.dd/rs6000/rs6000.exp	Sun Oct 14 23:39:46 2001
***************
*** 0 ****
--- 1,72 ----
+ # Copyright (C) 2001 Free Software Foundation, Inc.
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ # 
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ # 
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+ #
+ 
+ #
+ # Aix on PowerPC tests
+ #
+ 
+ if $tracelevel then {
+     strace $tracelevel
+ }
+ 
+ load_lib g++.exp
+ load_lib c-torture.exp
+ 
+ proc initfini_test1 {} {
+     global tmpdir srcdir subdir output tool
+ 
+     set testname "InitFini 1"
+     set filename "$srcdir/$subdir/hello.C"
+     set executable "$tmpdir/hello.x1"
+ 
+     set output [g++_target_compile $filename $executable  executable ""]
+     if { ![file exists $executable] } {
+ 	fail "$testname compile"
+ 	untested "$testname execute"
+ 	untested "$testname symbol check"
+ 	return
+     } else {
+ 	pass "$testname compile"
+     }
+ 
+     set run_output [ exec $executable ]
+ # The last \n is stripped 
+     set pass_output "Init 0\nHello World 1\nFini 2"
+ 
+     if { [ string compare $run_output $pass_output] == 0} {
+ 	pass "$testname execution"
+     }
+ 
+     catch { exec objdump -D $executable | grep __rtinit } sym_output
+     if { [ string match *__rtinit* $sym_output ] } {
+ 	pass "$testname symbol check"
+     } else {
+ 	fail "$testname symbol check"
+     }
+ 
+     remote_file build delete $executable
+ }
+ 
+ proc do_initfini {} {
+     initfini_test1
+ }
+ 
+ if { [istarget powerpc-*-*] || [istarget rs6000-*-aix*] } then {
+ 
+     do_initfini
+ }
+ 
+ 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]