public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "CHIGOT, CLEMENT" <clement.chigot@atos.net>
To: David Edelsohn <dje.gcc@gmail.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] gcc: implement AIX-style constructors
Date: Tue, 2 Nov 2021 13:28:16 +0000	[thread overview]
Message-ID: <PA4PR02MB6686B6289F877B745915FEB7EA8B9@PA4PR02MB6686.eurprd02.prod.outlook.com> (raw)
In-Reply-To: <CAGWvny=R0OS-yXSmnv5m+jQ8efS9wVfYOQuiifkkvUwpqozsng@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 471 bytes --]

Hi David,

Here is the new version of the patch.
I've moved the startup function in crtcdtors files.

I'm just wondering if the part dealing with the
__init_aix_libgcc_cxa_atexit is needed. I'm adding it because
the destructor created in crtcxa.o is following GCC format and
thus won't be launched if the flag "-mcdtors=aix" is passed.
However, as you said, this option might not operate correctly
if the GCC runtime isn't rebuild with it.

Thanks,
Clément

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-gcc-implement-AIX-style-constructors.patch --]
[-- Type: text/x-patch; name="0001-gcc-implement-AIX-style-constructors.patch", Size: 23397 bytes --]

From 8a14b0eb312628ad9cce8ac9f439c420b12b33c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= <clement.chigot@atos.net>
Date: Mon, 4 Oct 2021 09:24:43 +0200
Subject: [PATCH] gcc: implement AIX-style constructors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

AIX linker now supports constructors and destructors detection. For such
functions to be detected, their name must starts with __sinit or __sterm.
and -bcdtors must be passed to linker calls. It will create "_cdtors"
symbol which can be used to launch the initialization.

This patch creates a new RS6000 flag "-mcdtors=".
With "-mcdtors=aix", gcc will generate these new constructors/destructors.
With "-mcdtors=gcc", which is currently the default, gcc will continue
to generate "gcc" format for constructors (ie _GLOBAL__I and _GLOBAL__D
symbols).
Ideally, it would have been better to enable the AIX format by default
instead of using collect2. However, the compatibility between the
previously-built binaries and the new ones is too complex to be done.

gcc/ChangeLog:
2021-10-04  Clément Chigot  <clement.chigot@atos.net>

	* collect2.c (aixbcdtors_flags): New variable.
	(main): Use it to detect -bcdtors and remove -binitfini flag.
	(write_c_file_stat): Adapt to new AIX format.
	* config/rs6000/aix.h (FILE_SINIT_FORMAT): New define.
	(FILE_STERM_FORMAT): New define.
	(TARGET_FILE_FUNCTION_FORMAT): New define.
	* config/rs6000/aix64.opt: Add -mcdtors flag.
	* config/rs6000/aix71.h (LINK_SPEC_COMMON): Pass -bcdtors when
	  -mcdtors=aix is passed.
	(STARTFILE_SPEC): Add crtcdtors.o with -mcdtors=aix.
	* config/rs6000/aix72.h (LINK_SPEC_COMMON): Likewise.
	(STARTFILE_SPEC): Likewise.
	* config/rs6000/aix73.h (LINK_SPEC_COMMON): Likewise.
	(STARTFILE_SPEC): Likewise.
	* config/rs6000/rs6000-opts.h (enum rs6000_cdtors): New enum.
	* doc/invoke.texi: Add -mcdtors flag.
	* tree.c (get_file_function_name): Add
	  TARGET_FILE_FUNCTION_FORMAT support.

libgcc/ChangeLog:

	* config.host: Add crtcdtors.o files.
	* config/rs6000/t-aix-cxa: Likewise.
	* config/rs6000/crtcdtors.c: New file.

gcc/testsuite/ChangeLog:
2021-10-04  Clément Chigot  <clement.chigot@atos.net>

	* gcc.target/powerpc/constructor-aix.c: New test.
---
 gcc/collect2.c                                | 63 ++++++++++++++++---
 gcc/config/rs6000/aix.h                       | 56 +++++++++++++++++
 gcc/config/rs6000/aix64.opt                   | 17 +++++
 gcc/config/rs6000/aix71.h                     | 10 ++-
 gcc/config/rs6000/aix72.h                     | 10 ++-
 gcc/config/rs6000/aix73.h                     | 10 ++-
 gcc/config/rs6000/rs6000-opts.h               |  8 +++
 gcc/doc/invoke.texi                           | 21 ++++++-
 .../gcc.target/powerpc/constructor-aix.c      | 12 ++++
 gcc/tree.c                                    |  5 ++
 libgcc/config.host                            |  2 +-
 libgcc/config/rs6000/crtcdtors.c              | 53 ++++++++++++++++
 libgcc/config/rs6000/t-aix-cxa                | 12 ++++
 13 files changed, 260 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/constructor-aix.c
 create mode 100644 libgcc/config/rs6000/crtcdtors.c

diff --git a/gcc/collect2.c b/gcc/collect2.c
index 33114322f01..3d04bc8465f 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -186,6 +186,7 @@ static int aix64_flag;			/* true if -b64 */
 static int aixrtl_flag;			/* true if -brtl */
 static int aixlazy_flag;		/* true if -blazy */
 static int visibility_flag;		/* true if -fvisibility */
+static int aixbcdtors_flag;                /* True if -bcdtors */
 #endif
 
 enum lto_mode_d {
@@ -984,6 +985,8 @@ main (int argc, char **argv)
 	  aixrtl_flag = 0;
 	else if (strcmp (argv[i], "-blazy") == 0)
 	  aixlazy_flag = 1;
+	else if (strcmp (argv[i], "-bcdtors") == 0)
+	  aixbcdtors_flag = 1;
 #endif
       }
 
@@ -1731,7 +1734,9 @@ main (int argc, char **argv)
   /* Tell the linker that we have initializer and finalizer functions.  */
 #ifdef LD_INIT_SWITCH
 #ifdef COLLECT_EXPORT_LIST
-  *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
+  /* Do not emit -binitfini when -bcdtors is enabled. */
+  if (!aixbcdtors_flag)
+    *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
 #else
   *ld2++ = LD_INIT_SWITCH;
   *ld2++ = initname;
@@ -2020,6 +2025,7 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
 {
   const char *p, *q;
   char *prefix, *r;
+  char *regframe_name, *deregframe_name;
   int frames = (frame_tables.number > 0);
 
   /* Figure out name of output_file, stripping off .so version.  */
@@ -2062,6 +2068,22 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
   aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL);
 #endif
 
+  regframe_name = concat ("reg_frame", NULL, NULL);
+  deregframe_name = concat ("dereg_frame", NULL, NULL);
+#ifdef COLLECT_EXPORT_LIST
+  /* In order to be detected by the linker, sinit/sterm symbols
+     must be external. Thus, reg_frame and dereg_frame can't
+     be static anymore and their name needs to be unique.
+     In order to ensure that frames are initialized before any
+     constructors, their constructor must have the highest priority
+     0.  */
+  if (aixbcdtors_flag)
+    {
+      regframe_name = concat ("__sinit0_reg_frame_", prefix, NULL);
+      deregframe_name = concat ("__sterm0_dereg_frame_", prefix, NULL);
+    }
+#endif
+
   free (prefix);
 
   /* Write the tables as C code.  */
@@ -2073,9 +2095,16 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
      mechanisms GCC uses to order constructors across different dependent
      shared libraries (see config/rs6000/aix.h).
    */
-  fprintf (stream, "static int count;\n");
-  fprintf (stream, "typedef void entry_pt();\n");
-  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
+#ifdef COLLECT_EXPORT_LIST
+  if (!aixbcdtors_flag)
+    {
+#endif
+      fprintf (stream, "static int count;\n");
+      fprintf (stream, "typedef void entry_pt();\n");
+      write_list_with_asm (stream, "extern entry_pt ", constructors.first);
+#ifdef COLLECT_EXPORT_LIST
+    }
+#endif
 
   if (frames)
     {
@@ -2102,7 +2131,12 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
       fprintf (stream, "extern void *__gcc_unwind_dbase;\n");
 #endif
 
-      fprintf (stream, "static void reg_frame () {\n");
+#ifdef COLLECT_EXPORT_LIST
+      if (aixbcdtors_flag)
+	fprintf (stream, "void %s () {\n", regframe_name);
+      else
+#endif
+	fprintf (stream, "static void %s () {\n", regframe_name);
       fprintf (stream, "\tstatic struct object ob;\n");
 #ifdef TARGET_AIX_VERSION
       /* Use __gcc_unwind_dbase as the base address for data on AIX.
@@ -2114,11 +2148,24 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
 #endif
       fprintf (stream, "\t}\n");
 
-      fprintf (stream, "static void dereg_frame () {\n");
+#ifdef COLLECT_EXPORT_LIST
+      if (aixbcdtors_flag)
+	fprintf (stream, "void %s () {\n", deregframe_name);
+      else
+#endif
+	fprintf (stream, "static void %s () {\n", deregframe_name);
       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
       fprintf (stream, "\t}\n");
     }
 
+#ifdef COLLECT_EXPORT_LIST
+  /* Files built with the new AIX cdtors format don't need to
+     explicitly call them.
+     NOTE: This breaks compatibility with previously-built files.  */
+  if (aixbcdtors_flag)
+    return;
+#endif
+
 #ifdef COLLECT_EXPORT_LIST
   /* Set visibility of initializers to default.  */
   if (visibility_flag)
@@ -2130,7 +2177,7 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
       write_list (stream, "\t\t", constructors.first);
       if (frames)
-	fprintf (stream, "\treg_frame,\n");
+	fprintf (stream, "\t%s,\n", regframe_name);
       fprintf (stream, "\t};\n");
       fprintf (stream, "\tentry_pt **p;\n");
       fprintf (stream, "\tif (count++ != 0) return;\n");
@@ -2147,7 +2194,7 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
       write_list (stream, "\t\t", destructors.first);
       if (frames)
-	fprintf (stream, "\tdereg_frame,\n");
+	fprintf (stream, "\t%s,\n", deregframe_name);
       fprintf (stream, "\t};\n");
       fprintf (stream, "\tentry_pt **p;\n");
       fprintf (stream, "\tif (--count != 0) return;\n");
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index 0f4d8cb2dc8..d9ed88cb459 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -284,3 +284,59 @@
 #define SUBTARGET_DRIVER_SELF_SPECS	\
 "%{m64:-maix64} %<m64",			\
 "%{m32:-maix32} %<m32"
+
+/* Support for cdtors detected by AIX linker.
+   With -bcdtors flag, AIX linker is able to handle initialisers
+   by itself. For that, these initalisers must be named with the
+   following schema: __sinit{priority}_{name}. For destructors,
+   __sinit is replaced by __sterm.
+
+   For now, this part is enabled only when -mcdtors=aix flag is
+   passed to gcc.
+
+   The TARGET_FILE_FUNCTION_FORMAT allows to change the default name of
+   gcc constructors and destructors to one which will be understand by
+   AIX linker.
+
+   NOTE:
+   sinit/sterm functions will be triggered only if -bcdtors is passed
+   to the linker when building the binary. Even libraries built with
+   -bcdtors won't triggered those functions by themselves.
+   Ideally, if one day AIX way become the default, we would like
+   to ensure full compatibility between previously-made libraries
+   and new ones. However, this is hardly possible.
+   The main reason why this isn't working is that old libraries need
+   to be able to call constructors of new libraries using the previous
+   way, ie using GLOBAL_AIXI symbols. But if an old library loading a
+   new library is called by a new binary (thus with -bcdtors enabled),
+   it will trigger the new library's cdtors twice.
+   TODO: The only solution is to modify the wrapper created by gcc
+   around constructors and destructors so that it ensures that they
+   are called only once.
+*/
+#define FILE_SINIT_FORMAT "__sinit%s_%s"
+#define FILE_STERM_FORMAT "__sterm%s_%s"
+#define TARGET_FILE_FUNCTION_FORMAT(TYPE, BUF, SUBNAME)			\
+  do									\
+    {									\
+      if (rs6000_current_cdtors == CDTORS_AIX && (TYPE[0] == 'I'))	\
+	{								\
+	  BUF = (char *) alloca (sizeof (FILE_SINIT_FORMAT)		\
+				 + strlen (SUBNAME) + strlen (TYPE) - 2); \
+	  sprintf (BUF, FILE_SINIT_FORMAT, TYPE + 2, SUBNAME);		\
+	}								\
+      else if (rs6000_current_cdtors == CDTORS_AIX && (TYPE[0] == 'D'))	\
+	{								\
+	  BUF = (char *) alloca (sizeof (FILE_STERM_FORMAT)		\
+				 + strlen (SUBNAME) + strlen (TYPE) - 2); \
+	  sprintf (BUF, FILE_STERM_FORMAT, TYPE + 2, SUBNAME);		\
+	}								\
+      else								\
+	{								\
+	  BUF = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT)		\
+				 + strlen (SUBNAME) + strlen (TYPE));	\
+	  sprintf (BUF, FILE_FUNCTION_FORMAT, TYPE, SUBNAME);		\
+	}								\
+    }									\
+  while(0)
+
diff --git a/gcc/config/rs6000/aix64.opt b/gcc/config/rs6000/aix64.opt
index 15d863fa0a2..508e79f17f9 100644
--- a/gcc/config/rs6000/aix64.opt
+++ b/gcc/config/rs6000/aix64.opt
@@ -59,3 +59,20 @@ Driver
 
 m32
 Driver
+
+mcdtors=
+Target RejectNegative Joined Enum(rs6000_cdtors) Var(rs6000_current_cdtors)
+Select constructors format.
+
+Enum
+Name(rs6000_cdtors) Type(enum rs6000_cdtors)
+Known constructors format (for use with the -mcdtors= option):
+
+EnumValue
+Enum(rs6000_cdtors) String(aix) Value(CDTORS_AIX)
+
+EnumValue
+Enum(rs6000_cdtors) String(gcc) Value(CDTORS_GCC)
+
+TargetVariable
+enum rs6000_cdtors rs6000_current_cdtors = CDTORS_GCC
\ No newline at end of file
diff --git a/gcc/config/rs6000/aix71.h b/gcc/config/rs6000/aix71.h
index 75afa22a2eb..cd991674af8 100644
--- a/gcc/config/rs6000/aix71.h
+++ b/gcc/config/rs6000/aix71.h
@@ -176,7 +176,7 @@ do {									\
 #define LINK_SPEC64 "-b64"
 #define LINK_SPEC_COMMON "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
    %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
-   %{mpe:-binitfini:poe_remote_main} "
+   %{mpe:-binitfini:poe_remote_main} %{mcdtors=aix:-bcdtors}"
 
 #undef STARTFILE_SPEC
 #if DEFAULT_ARCH64_P
@@ -185,14 +185,18 @@ do {									\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{!maix32:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{!maix32:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #else
 #define STARTFILE_SPEC "%{!shared:\
    %{maix64:%{pg:gcrt0_64%O%s;:%{p:mcrt0_64%O%s;:crt0_64%O%s}};:\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{maix64:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{maix64:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #endif
 
 
diff --git a/gcc/config/rs6000/aix72.h b/gcc/config/rs6000/aix72.h
index 7ae25bd2a29..b4fc3040341 100644
--- a/gcc/config/rs6000/aix72.h
+++ b/gcc/config/rs6000/aix72.h
@@ -177,7 +177,7 @@ do {									\
 #define LINK_SPEC64 "-b64"
 #define LINK_SPEC_COMMON "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
    %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
-   %{mpe:-binitfini:poe_remote_main} "
+   %{mpe:-binitfini:poe_remote_main} %{mcdtors=aix:-bcdtors}"
 
 #undef STARTFILE_SPEC
 #if DEFAULT_ARCH64_P
@@ -186,14 +186,18 @@ do {									\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{!maix32:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{!maix32:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #else
 #define STARTFILE_SPEC "%{!shared:\
    %{maix64:%{pg:gcrt0_64%O%s;:%{p:mcrt0_64%O%s;:crt0_64%O%s}};:\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{maix64:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{maix64:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #endif
 
 
diff --git a/gcc/config/rs6000/aix73.h b/gcc/config/rs6000/aix73.h
index ee5858cc443..95af5611252 100644
--- a/gcc/config/rs6000/aix73.h
+++ b/gcc/config/rs6000/aix73.h
@@ -178,7 +178,7 @@ do {									\
 #define LINK_SPEC64 "-b64"
 #define LINK_SPEC_COMMON "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
    %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
-   %{mpe:-binitfini:poe_remote_main} "
+   %{mpe:-binitfini:poe_remote_main} %{mcdtors=aix:-bcdtors}"
 
 #undef STARTFILE_SPEC
 #if DEFAULT_ARCH64_P
@@ -187,14 +187,18 @@ do {									\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{!maix32:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{!maix32:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #else
 #define STARTFILE_SPEC "%{!shared:\
    %{maix64:%{pg:gcrt0_64%O%s;:%{p:mcrt0_64%O%s;:crt0_64%O%s}};:\
      %{pthread:%{pg:gcrt0_r%O%s;:%{p:mcrt0_r%O%s;:crt0_r%O%s}};:\
        %{pg:gcrt0%O%s;:%{p:mcrt0%O%s;:crt0%O%s}}}}}\
    %{maix64:%{shared:crtcxa_64_s%O%s;:crtcxa_64%O%s} crtdbase_64%O%s;:\
-     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}"
+     %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s}\
+   %{mcdtors=aix: %{maix64:%{shared:crtcdtors_64_s%O%s;:crtcdtors_64%O%s};:\
+     %{shared:crtcdtors_s%O%s;:crtcdtors%O%s}}}"
 #endif
 
 
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index 51d6c654842..ab78f31dc9d 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -147,6 +147,14 @@ enum stack_protector_guard {
   SSP_GLOBAL			/* global canary */
 };
 
+/* Constructors format for AIX32
+   aix: AIX format (__sinit/__sterm)
+   gcc: GCC format (_GLOBAL__I/_GLOBAL__F) */
+enum rs6000_cdtors {
+  CDTORS_AIX,
+  CDTORS_GCC
+};
+
 /* No enumeration is defined to index the -mcpu= values (entries in
    processor_target_table), with the type int being used instead, but
    we need to distinguish the special "native" value.  */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6d1e328571a..5b64cbb4569 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1249,7 +1249,8 @@ See RS/6000 and PowerPC Options.
 -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol
 -mstack-protector-guard-offset=@var{offset} -mprefixed -mno-prefixed @gol
 -mpcrel -mno-pcrel -mmma -mno-mmma -mrop-protect -mno-rop-protect @gol
--mprivileged -mno-privileged}
+-mprivileged -mno-privileged @gol
+-mcdtors=@var{cdtors_format}}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -28572,6 +28573,24 @@ Generate (do not generate) code that will run in privileged state.
 @opindex no-block-ops-unaligned-vsx
 Generate (do not generate) unaligned vsx loads and stores for
 inline expansion of @code{memcpy} and @code{memmove}.
+
+@item -mcdtors=@var{cdtors_format}
+@opindex mcdtors
+Specifies which format should be used to generate constructors
+and destructors on AIX.
+Valid values are: @samp{gcc} and @samp{aix}.
+
+@item -mcdtors=gcc
+@opindex mcdtors=gcc
+Generate constructors and destructors following GCC format.
+
+@item -mcdtors=aix
+@opindex mcdtors=aix
+Generate constructors and destructors following AIX format.
+This is made for interoperability with IBM XL Compiler.
+This option will not operate correctly unless the application
+and the GCC runtime are built with the option.
+
 @end table
 
 @node RX Options
diff --git a/gcc/testsuite/gcc.target/powerpc/constructor-aix.c b/gcc/testsuite/gcc.target/powerpc/constructor-aix.c
new file mode 100644
index 00000000000..65222a5e239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/constructor-aix.c
@@ -0,0 +1,12 @@
+/* { dg-do run { target powerpc*-*-aix* } } */
+/* { dg-options "-mcdtors=aix" } */
+
+int i;
+
+void hello (void) __attribute__ ((constructor));
+void hello (void) { i = 1; }
+
+int main (void) {
+  if (i != 1)
+    return 1;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 7bfd64160f4..cc0a10a3c22 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8633,6 +8633,10 @@ get_file_function_name (const char *type)
     }
 
   clean_symbol_name (q);
+
+#ifdef TARGET_FILE_FUNCTION_FORMAT
+  TARGET_FILE_FUNCTION_FORMAT(type, buf, p);
+#else
   buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
 			 + strlen (type));
 
@@ -8641,6 +8645,7 @@ get_file_function_name (const char *type)
      the program) rather than the file name (which imposes extra
      constraints).  */
   sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
+#endif
 
   return get_identifier (buf);
 }
diff --git a/libgcc/config.host b/libgcc/config.host
index 6c34b13d611..f88a7cc6b40 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -1288,7 +1288,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
 rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
 	md_unwind_header=rs6000/aix-unwind.h
 	tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble rs6000/t-aix-cxa"
-	extra_parts="crtcxa.o crtcxa_s.o crtdbase.o crtcxa_64.o crtcxa_64_s.o crtdbase_64.o"
+	extra_parts="crtcxa.o crtcxa_s.o crtdbase.o crtcxa_64.o crtcxa_64_s.o crtdbase_64.o crtcdtors.o crtcdtors_s.o crtcdtors_64.o crtcdtors_64_s.o"
 	;;
 rl78-*-elf)
 	tmake_file="$tm_file t-fdpbit rl78/t-rl78"
diff --git a/libgcc/config/rs6000/crtcdtors.c b/libgcc/config/rs6000/crtcdtors.c
new file mode 100644
index 00000000000..a60c8e30c56
--- /dev/null
+++ b/libgcc/config/rs6000/crtcdtors.c
@@ -0,0 +1,53 @@
+/* Initialization of constructors and destructors following
+   AIX format.
+   Copyright (C) 2021-2021 Free Software Foundation, Inc.
+   Written by Clément Chigot.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option) any later
+   version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SHARED
+extern void (* _cdtors[]) (void);
+extern void __run_initial_ctors (void (**) (void));
+extern void __run_final_dtors (void);
+
+void _AIX_init(void);
+void _AIX_init(void)
+{
+  /* Run CTORs now  */
+  __run_initial_ctors(&_cdtors[0]);
+
+  /* Warn exit() that we want to run dtors at the end  */
+  __run_final_dtors();
+}
+
+void (*__C_runtime_pstartup) (void) = _AIX_init;
+
+#endif
+
+/* crtcxa is compiled without -mcdtors=aix flag. Thus, a new
+   destructor must be created following AIX format and this file
+   must be compiled with -mcdtors=aix to enable it.  */
+void __init_aix_libgcc_cxa_atexit_dup (void) __attribute__ ((destructor (65535)));
+void __init_aix_libgcc_cxa_atexit_dup (void)
+{
+  __init_aix_libgcc_cxa_atexit ();
+}
diff --git a/libgcc/config/rs6000/t-aix-cxa b/libgcc/config/rs6000/t-aix-cxa
index 0e1bccb1525..e9e862909bc 100644
--- a/libgcc/config/rs6000/t-aix-cxa
+++ b/libgcc/config/rs6000/t-aix-cxa
@@ -24,3 +24,15 @@ crtcxa_64.o: $(srcdir)/config/rs6000/crtcxa.c
 
 crtcxa_64_s.o: $(srcdir)/config/rs6000/crtcxa.c
 	$(crt_compile) -maix64 -DSHARED -c $<
+
+crtcdtors.o: $(srcdir)/config/rs6000/crtcdtors.c
+	$(crt_compile) -maix32 -c $< -mcdtors=aix
+
+crtcdtors_s.o: $(srcdir)/config/rs6000/crtcdtors.c
+	$(crt_compile) -maix32 -DSHARED -c $< -mcdtors=aix
+
+crtcdtors_64.o: $(srcdir)/config/rs6000/crtcdtors.c
+	$(crt_compile) -maix64 -c $< -mcdtors=aix
+
+crtcdtors_64_s.o: $(srcdir)/config/rs6000/crtcdtors.c
+	$(crt_compile) -maix64 -DSHARED -c $< -mcdtors=aix
\ No newline at end of file
-- 
2.33.0


  reply	other threads:[~2021-11-02 13:28 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-18  7:55 CHIGOT, CLEMENT
2021-10-19 20:14 ` David Edelsohn
2021-10-21 12:39   ` CHIGOT, CLEMENT
2021-10-21 13:59     ` David Edelsohn
2021-11-02 13:28       ` CHIGOT, CLEMENT [this message]
2021-11-16  8:42         ` CHIGOT, CLEMENT

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=PA4PR02MB6686B6289F877B745915FEB7EA8B9@PA4PR02MB6686.eurprd02.prod.outlook.com \
    --to=clement.chigot@atos.net \
    --cc=dje.gcc@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).