This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[csl-sol210-branch] Add some Solaris #pragmas
- From: Daniel Jacobowitz <drow at false dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Jul 2004 16:34:55 -0400
- Subject: [csl-sol210-branch] Add some Solaris #pragmas
This patch enables, for i386-pc-solaris2.10, a couple of #pragma directives:
#pragma init
#pragma fini
#pragma align
These appear to be needed for compatibility with the Solaris 10 system
headers. Committed to csl-sol210-branch; I'll submit it for mainline at a
later date, after additional testing.
Does any Sparc Solaris target need these? If so I could put them in
config/...
--
Daniel Jacobowitz
2004-07-13 Daniel Jacobowitz <dan@debian.org>
* config.gcc (i[34567]86-*-solaris2.1[0-9]): Set tm_p_file,
tmake_file, c_target_objs, and cxx_target_objs.
* config/i386/i386.c (TARGET_INSERT_ATTRIBUTES): Define to
SUBTARGET_INSERT_ATTRIBUTES.
(ix86_attribute_table): Include "init" and "fini" if
TARGET_INIT_FINI_ATTRIBUTES.
* config/i386/sol2-10.h (SUBTARGET_INSERT_ATTRIBUTES)
(REGISTER_TARGET_PRAGMAS, ASM_DECLARE_FUNCTION_SIZE)
(TARGET_INIT_FINI_ATTRIBUTES): Define.
* config/i386/sol2-10-protos.h: New file.
* config/i386/sol2-c.c: New file.
* config/i386/t-sol2-10: New file.
* doc/extend.texi (Solaris Pragmas): New section.
2004-07-13 Daniel Jacobowitz <dan@debian.org>
* gcc.dg/pragma-align-2.c: New testcase.
* gcc.dg/pragma-init-fini.c: New testcase.
* gcc.dg/pragma-align.c: Run test. Include i?86-solaris2.1[0-9]*.
Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.465.2.1
diff -u -p -r1.465.2.1 config.gcc
--- gcc/config.gcc 12 Jul 2004 14:59:19 -0000 1.465.2.1
+++ gcc/config.gcc 13 Jul 2004 19:38:50 -0000
@@ -986,7 +986,11 @@ i[34567]86-*-solaris2*)
case ${target} in
*-*-solaris2.1[0-9])
tm_file="${tm_file} i386/x86-64.h i386/sol2-10.h"
+ tm_p_file="${tm_p_file} i386/sol2-10-protos.h"
tm_defines="${tm_defines} TARGET_BI_ARCH=1"
+ tmake_file="${tmake_file} i386/t-sol2-10"
+ c_target_objs="sol2-c.o"
+ cxx_target_objs="sol2-c.o"
;;
esac
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
Index: gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.685.2.1
diff -u -p -r1.685.2.1 i386.c
--- gcc/config/i386/i386.c 12 Jul 2004 14:42:52 -0000 1.685.2.1
+++ gcc/config/i386/i386.c 13 Jul 2004 19:38:52 -0000
@@ -1075,6 +1075,11 @@ static void init_ext_80387_constants (vo
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
+#ifdef SUBTARGET_INSERT_ATTRIBUTES
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
+#endif
+
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -1598,6 +1603,10 @@ const struct attribute_spec ix86_attribu
#endif
{ "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute },
{ "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute },
+#ifdef TARGET_INIT_FINI_ATTRIBUTES
+ { "init", 0, 0, true, false, false, NULL },
+ { "fini", 0, 0, true, false, false, NULL },
+#endif
{ NULL, 0, 0, false, false, false, NULL }
};
Index: gcc/config/i386/sol2-10-protos.h
===================================================================
RCS file: gcc/config/i386/sol2-10-protos.h
diff -N gcc/config/i386/sol2-10-protos.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/config/i386/sol2-10-protos.h 13 Jul 2004 19:38:52 -0000
@@ -0,0 +1,25 @@
+/* Prototypes.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+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 2, 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.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+extern void solaris_insert_attributes (tree, tree *);
+extern void solaris_pragma_align (struct cpp_reader *);
+extern void solaris_pragma_init (struct cpp_reader *);
+extern void solaris_pragma_fini (struct cpp_reader *);
+extern void solaris_output_init_fini (FILE *, tree);
Index: gcc/config/i386/sol2-10.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/Attic/sol2-10.h,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 sol2-10.h
--- gcc/config/i386/sol2-10.h 12 Jul 2004 14:59:20 -0000 1.1.2.1
+++ gcc/config/i386/sol2-10.h 13 Jul 2004 19:38:52 -0000
@@ -35,3 +35,25 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE (TARGET_64BIT ? "int" : "long int")
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
+
+#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+
+#define REGISTER_TARGET_PRAGMAS() \
+ do { \
+ c_register_pragma (0, "align", solaris_pragma_align); \
+ c_register_pragma (0, "init", solaris_pragma_init); \
+ c_register_pragma (0, "fini", solaris_pragma_fini); \
+ } while (0)
+
+/* This is how to declare the size of a function. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ solaris_output_init_fini (FILE, DECL); \
+ } \
+ while (0)
+
+#define TARGET_INIT_FINI_ATTRIBUTES
Index: gcc/config/i386/sol2-c.c
===================================================================
RCS file: gcc/config/i386/sol2-c.c
diff -N gcc/config/i386/sol2-c.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/config/i386/sol2-c.c 13 Jul 2004 19:38:52 -0000
@@ -0,0 +1,299 @@
+/* Solaris support needed only by C/C++ frontends.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+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 2, 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.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "cpplib.h"
+#include "tree.h"
+#include "c-pragma.h"
+#include "c-tree.h"
+#include "c-incpath.h"
+#include "toplev.h"
+#include "tm_p.h"
+
+static GTY(()) tree pending_aligns, pending_inits, pending_finis;
+
+/* Handle #pragma align ALIGNMENT (VAR [, VAR]...) */
+
+void
+solaris_pragma_align (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t, x;
+ enum cpp_ttype ttype;
+ HOST_WIDE_INT low;
+
+ if (c_lex (&x) != CPP_NUMBER
+ || c_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning ("malformed %<#pragma align%>, ignoring");
+ return;
+ }
+
+ low = TREE_INT_CST_LOW (x);
+ if (TREE_INT_CST_HIGH (x) != 0
+ || (low != 1 && low != 2 && low != 4 && low != 8 && low != 16
+ && low != 32 && low != 64 && low != 128))
+ {
+ warning ("invalid alignment for %<#pragma align%>, ignoring");
+ return;
+ }
+
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma align%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ warning ("%<#pragma align%> must appear before the declaration of "
+ "%D, ignoring", decl);
+ else
+ pending_aligns = tree_cons (t, build_tree_list (NULL, x),
+ pending_aligns);
+
+ ttype = c_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma align%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (c_lex (&t) != CPP_EOF)
+ warning ("junk at end of %<#pragma align%>");
+ return;
+ }
+ else
+ {
+ warning ("malformed %<#pragma align%>");
+ return;
+ }
+ }
+}
+
+/* Handle #pragma init (function [, function]...) */
+
+void
+solaris_pragma_init (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t;
+ enum cpp_ttype ttype;
+
+ if (c_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning ("malformed %<#pragma init%>, ignoring");
+ return;
+ }
+
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma init%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ {
+ tree init_list = build_tree_list (get_identifier ("init"),
+ NULL);
+ tree attrs = tree_cons (get_identifier ("used"), NULL, init_list);
+ decl_attributes (&decl, attrs, 0);
+ }
+ else
+ pending_inits = tree_cons (t, NULL, pending_inits);
+
+ ttype = c_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma init%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (c_lex (&t) != CPP_EOF)
+ warning ("junk at end of %<#pragma init%>");
+ return;
+ }
+ else
+ {
+ warning ("malformed %<#pragma init%>");
+ return;
+ }
+ }
+}
+
+/* Handle #pragma fini (function [, function]...) */
+
+void
+solaris_pragma_fini (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t;
+ enum cpp_ttype ttype;
+
+ if (c_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning ("malformed %<#pragma fini%>, ignoring");
+ return;
+ }
+
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma fini%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ {
+ tree fini_list = build_tree_list (get_identifier ("fini"),
+ NULL);
+ tree attrs = tree_cons (get_identifier ("used"), NULL, fini_list);
+ decl_attributes (&decl, attrs, 0);
+ }
+ else
+ pending_finis = tree_cons (t, NULL, pending_finis);
+
+ ttype = c_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = c_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning ("malformed %<#pragma fini%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (c_lex (&t) != CPP_EOF)
+ warning ("junk at end of %<#pragma fini%>");
+ return;
+ }
+ else
+ {
+ warning ("malformed %<#pragma fini%>");
+ return;
+ }
+ }
+}
+
+/* Attach any pending attributes for DECL to the list in *ATTRIBUTES. */
+
+void
+solaris_insert_attributes (tree decl, tree *attributes)
+{
+ tree *x, next;
+
+ if (pending_aligns != NULL && TREE_CODE (decl) == VAR_DECL)
+ for (x = &pending_aligns; *x; x = &TREE_CHAIN (pending_aligns))
+ {
+ tree name = TREE_PURPOSE (*x);
+ tree value = TREE_VALUE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ if (lookup_attribute ("aligned", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("aligned", *attributes))
+ warning ("%Jignoring %<#pragma align%> for explicitly "
+ "aligned %<%D%>", decl, decl);
+ else
+ *attributes = tree_cons (get_identifier ("aligned"), value,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+
+ if (pending_inits != NULL && TREE_CODE (decl) == FUNCTION_DECL)
+ for (x = &pending_inits; *x; x = &TREE_CHAIN (pending_inits))
+ {
+ tree name = TREE_PURPOSE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ *attributes = tree_cons (get_identifier ("init"), NULL,
+ *attributes);
+ *attributes = tree_cons (get_identifier ("used"), NULL,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+
+ if (pending_finis != NULL && TREE_CODE (decl) == FUNCTION_DECL)
+ for (x = &pending_finis; *x; x = &TREE_CHAIN (pending_finis))
+ {
+ tree name = TREE_PURPOSE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ *attributes = tree_cons (get_identifier ("fini"), NULL,
+ *attributes);
+ *attributes = tree_cons (get_identifier ("used"), NULL,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+}
+
+/* Output initializer or finalizer entries for DECL to FILE. */
+
+void
+solaris_output_init_fini (FILE *file, tree decl)
+{
+ if (lookup_attribute ("init", DECL_ATTRIBUTES (decl)))
+ {
+ fprintf (file, "\t.section\t.init\n");
+ fprintf (file, "\tcall\t%s\n", IDENTIFIER_POINTER (DECL_NAME (decl)));
+ fprintf (file, "\t.popsection\n");
+ }
+
+ if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl)))
+ {
+ fprintf (file, "\t.section\t.fini\n");
+ fprintf (file, "\tcall\t%s\n", IDENTIFIER_POINTER (DECL_NAME (decl)));
+ fprintf (file, "\t.popsection\n");
+ }
+}
Index: gcc/config/i386/t-sol2-10
===================================================================
RCS file: gcc/config/i386/t-sol2-10
diff -N gcc/config/i386/t-sol2-10
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/config/i386/t-sol2-10 13 Jul 2004 19:38:52 -0000
@@ -0,0 +1,6 @@
+# Solaris-specific pragmas
+sol2-c.o: $(srcdir)/config/i386/sol2-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(CPPLIB_H) tree.h c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H) \
+ c-incpath.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/sol2-c.c
Index: gcc/doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.200
diff -u -p -r1.200 extend.texi
--- gcc/doc/extend.texi 7 Jul 2004 17:38:40 -0000 1.200
+++ gcc/doc/extend.texi 13 Jul 2004 19:38:54 -0000
@@ -7209,6 +7209,7 @@ for further explanation.
* ARM Pragmas::
* RS/6000 and PowerPC Pragmas::
* Darwin Pragmas::
+* Solaris Pragmas::
* Symbol-Renaming Pragmas::
@end menu
@@ -7293,6 +7294,38 @@ that of the @code{unused} attribute, exc
anywhere within the variables' scopes.
@end table
+@node Solaris Pragmas
+@subsection Solaris Pragmas
+
+The Solaris target supports @code{#pragma redefine_extname}
+(@pxref{Symbol-Renaming Pragmas}). The x86/AMD64 Solaris 10 target also
+supports additional @code{#pragma} directives for compatibility with system
+headers.
+
+@table @code
+@item align @var{alignment} (@var{variable} [, @var{variable}]...)
+@cindex pragma, align
+
+Increase the minimum alignment of each @var{variable} to @var{alignment}.
+This is the same as GCC's @code{aligned} attribute @pxref{Variable
+Attributes}).
+
+@item fini (@var{function} [, @var{function}]...)
+@cindex pragma, fini
+
+This pragma causes each listed @var{function} to be called after
+main, or during shared module unloading, by adding a call to the
+@code{.fini} section.
+
+@item init (@var{function} [, @var{function}]...)
+@cindex pragma, init
+
+This pragma causes each listed @var{function} to be called during
+initialization (before @code{main}) or during shared module loading, by
+adding a call to the @code{.init} section.
+
+@end table
+
@node Symbol-Renaming Pragmas
@subsection Symbol-Renaming Pragmas
Index: gcc/testsuite/gcc.dg/pragma-align-2.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/pragma-align-2.c
diff -N gcc/testsuite/gcc.dg/pragma-align-2.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/pragma-align-2.c 13 Jul 2004 19:38:54 -0000
@@ -0,0 +1,54 @@
+/* { dg-do run { target i?86-*-solaris2.1[0-9]* } } */
+
+void abort (void);
+
+#pragma align 1(x1)
+#pragma align 2(x2)
+#pragma align 4(x4)
+#pragma align 8(x8,y8,z8)
+#pragma align 16(x16)
+#pragma align 32(x32)
+#pragma align 64(x64)
+#pragma align 128(x128)
+
+#pragma align 8(not_defined)
+
+#pragma align 9(odd_align) /* { dg-error "invalid alignment" } */
+#pragma align 256(high_align) /* { dg-error "invalid alignment" } */
+#pragma align -1(neg_align) /* { dg-error "malformed" } */
+#pragma align bad_align /* { dg-error "malformed" } */
+#pragma align 1(bad_align /* { dg-error "malformed" } */
+
+int x, x1, x2, x4, x8, y8, z8, x16, x32, x64, x128;
+
+#pragma align 16(x) /* { dg-error "must appear before" } */
+
+int
+main ()
+{
+ if (__alignof__ (x4) < 4)
+ abort ();
+
+ if (__alignof__ (x8) < 8)
+ abort ();
+
+ if (__alignof__ (y8) < 8)
+ abort ();
+
+ if (__alignof__ (z8) < 8)
+ abort ();
+
+ if (__alignof__ (x16) < 16)
+ abort ();
+
+ if (__alignof__ (x32) < 32)
+ abort ();
+
+ if (__alignof__ (x64) < 64)
+ abort ();
+
+ if (__alignof__ (x128) < 128)
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/pragma-align.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/pragma-align.c,v
retrieving revision 1.2
diff -u -p -r1.2 pragma-align.c
--- gcc/testsuite/gcc.dg/pragma-align.c 11 Sep 2000 22:47:05 -0000 1.2
+++ gcc/testsuite/gcc.dg/pragma-align.c 13 Jul 2004 19:38:54 -0000
@@ -1,6 +1,6 @@
/* Prove that HANDLE_SYSTEMV_PRAGMA alignment handling works somewhat. */
-/* { dg-do compile { target i?86-*-linux* i?86-*-*bsd* i?86-*-sco3.2v5* } } */
+/* { dg-do run { target i?86-*-linux* i?86-*-*bsd* i?86-*-sco3.2v5* i?86-*-solaris2.1[0-9]* } } */
struct {
char one;
@@ -39,4 +39,3 @@ main()
if(sizeof(resetalign) != sizeof(defaultalign)) abort();
return 0;
}
-
Index: gcc/testsuite/gcc.dg/pragma-init-fini.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/pragma-init-fini.c
diff -N gcc/testsuite/gcc.dg/pragma-init-fini.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/pragma-init-fini.c 13 Jul 2004 19:38:54 -0000
@@ -0,0 +1,50 @@
+/* Tests for #pragma init and #pragma fini. */
+
+/* { dg-do run { target i?86-*-solaris2.1[0-9]* } } */
+
+extern void abort ();
+
+#pragma init /* { dg-error "malformed" } */
+#pragma init () /* { dg-error "malformed" } */
+#pragma init init_func /* { dg-error "malformed" } */
+
+#pragma fini /* { dg-error "malformed" } */
+#pragma fini () /* { dg-error "malformed" } */
+#pragma fini fini_func /* { dg-error "malformed" } */
+
+#pragma init (init_func, init_static_func)
+
+int glob_1, glob_2;
+
+void init_func (void)
+{
+ glob_1 = 1;
+}
+
+static void init_static_func (void)
+{
+ glob_2 = 2;
+}
+
+#pragma fini (fini_func, fini_static_func)
+
+void fini_func (void)
+{
+
+}
+
+static void fini_static_func (void)
+{
+
+}
+
+int main()
+{
+ if (glob_1 != 1)
+ abort ();
+
+ if (glob_2 != 2)
+ abort ();
+
+ return 0;
+}