diff mbox

[scalar-storage-order] Add pragma scalar_storage_order

Message ID 1599979.cbkScWTEAA@polaris
State New
Headers show

Commit Message

Eric Botcazou July 1, 2015, 10:28 a.m. UTC
This adds a #pragma scalar_storage_order directive to the C family of 
languages that makes it possible to specify a default SSO.

Tested on x86_64-suse-linux. applied on the branch.


	* doc/extend.texi (Structure-Packing Pragmas): Rename into...
	( Structure-Layout Pragmas): ...this.  Document scalar_storage_order.
c-family/
	* c-common.c (handle_scalar_storage_order_attribute): Add the attribute
	on success and tweak.
	* c-pragma.c (enum scalar_storage_order_kind): New enumeration.
	(global_sso_kind): New variable.
	(maybe_apply_pragma_scalar_storage_order): New function.
	(handle_pragma_scalar_storage_order): Likewise.
	(init_pragma): Register scalar_storage_order.
	* c-pragma.h (maybe_apply_pragma_scalar_storage_order): Declare.
c/
	* c-decl.c (finish_struct): Call it.
cp/
	* class.c (finish_struct_1): Likewise.
testsuite/
	* c-c++-common/sso-5.c: New test.
diff mbox

Patch

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 224700)
+++ doc/extend.texi	(working copy)
@@ -18108,7 +18108,7 @@  for further explanation.
 * Darwin Pragmas::
 * Solaris Pragmas::
 * Symbol-Renaming Pragmas::
-* Structure-Packing Pragmas::
+* Structure-Layout Pragmas::
 * Weak Pragmas::
 * Diagnostic Pragmas::
 * Visibility Pragmas::
@@ -18371,8 +18371,8 @@  the name does not change.
 always the C-language name.
 @end enumerate
 
-@node Structure-Packing Pragmas
-@subsection Structure-Packing Pragmas
+@node Structure-Layout Pragmas
+@subsection Structure-Layout Pragmas
 
 For compatibility with Microsoft Windows compilers, GCC supports a
 set of @code{#pragma} directives that change the maximum alignment of
@@ -18395,17 +18395,29 @@  multiple @code{#pragma pack(@var{n})} in
 @code{#pragma pack(pop)}.
 @end enumerate
 
-Some targets, e.g.@: x86 and PowerPC, support the @code{ms_struct}
-@code{#pragma} which lays out a structure as the documented
-@code{__attribute__ ((ms_struct))}.
+Some targets, e.g.@: x86 and PowerPC, support the @code{#pragma ms_struct}
+directive which lays out structures, unions and classes subsequently defined
+as the documented @code{__attribute__ ((ms_struct))}.
+
 @enumerate
-@item @code{#pragma ms_struct on} turns on the layout for structures
-declared.
-@item @code{#pragma ms_struct off} turns off the layout for structures
-declared.
+@item @code{#pragma ms_struct on} turns on the Microsoft layout.
+@item @code{#pragma ms_struct off} turns off the Microsoft layout.
 @item @code{#pragma ms_struct reset} goes back to the default layout.
 @end enumerate
 
+Most targets also support the @code{#pragma scalar_storage_order} directive
+which lays out structures, unions and classes subsequently defined as the
+documented @code{__attribute__ ((scalar_storage_order))}.
+
+@enumerate
+@item @code{#pragma scalar_storage_order big-endian} sets the storage order
+of the scalar fields to big-endian.
+@item @code{#pragma scalar_storage_order little-endian} sets the storage order
+of the scalar fields to little-endian.
+@item @code{#pragma scalar_storage_order default} goes back to the default
+endianness.
+@end enumerate
+
 @node Weak Pragmas
 @subsection Weak Pragmas
 
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 224700)
+++ c-family/c-common.c	(working copy)
@@ -7504,8 +7504,6 @@  handle_scalar_storage_order_attribute (t
   tree id = TREE_VALUE (args);
   tree type;
 
-  *no_add_attrs = true;
-
   if (TREE_CODE (*node) == TYPE_DECL
       && ! (flags & ATTR_FLAG_CXX11))
     node = &TREE_TYPE (*node);
@@ -7521,16 +7519,10 @@  handle_scalar_storage_order_attribute (t
 
       if (TREE_CODE (id) == STRING_CST
 	  && strcmp (TREE_STRING_POINTER (id), "big-endian") == 0)
-	{
-	  if (!BYTES_BIG_ENDIAN)
-	    TYPE_REVERSE_STORAGE_ORDER (type) = 1;
-	}
+	TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
       else if (TREE_CODE (id) == STRING_CST
 	       && strcmp (TREE_STRING_POINTER (id), "little-endian") == 0)
-	{
-	  if (BYTES_BIG_ENDIAN)
-	    TYPE_REVERSE_STORAGE_ORDER (type) = 1;
-	}
+	TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
       else
 	error ("scalar_storage_order argument must be one of \"big-endian\" "
 	       "or \"little-endian\"");
@@ -7540,6 +7532,7 @@  handle_scalar_storage_order_attribute (t
 
  ignored:
   warning (OPT_Wattributes, "%qE attribute ignored", name);
+  *no_add_attrs = true;
   return NULL_TREE;
 }
 
Index: c-family/c-pragma.c
===================================================================
--- c-family/c-pragma.c	(revision 224467)
+++ c-family/c-pragma.c	(working copy)
@@ -400,6 +400,58 @@  handle_pragma_weak (cpp_reader * ARG_UNU
     }
 }
 
+enum scalar_storage_order_kind
+{
+  SSO_DEFAULT,
+  SSO_BIG_ENDIAN,
+  SSO_LITTLE_ENDIAN
+};
+
+static enum scalar_storage_order_kind global_sso_kind = SSO_DEFAULT;
+
+void
+maybe_apply_pragma_scalar_storage_order (tree type)
+{
+  if (global_sso_kind == SSO_DEFAULT)
+    return;
+
+  gcc_assert (RECORD_OR_UNION_TYPE_P (type));
+
+  if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
+    return;
+
+  if (global_sso_kind == SSO_BIG_ENDIAN)
+    TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+  else if (global_sso_kind == SSO_LITTLE_ENDIAN)
+    TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
+  else
+    gcc_unreachable ();
+}
+
+static void
+handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy))
+{
+  const char *kind_string;
+  enum cpp_ttype token;
+  tree x;
+
+  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+    error ("scalar_storage_order is not supported");
+
+  token = pragma_lex (&x);
+  if (token != CPP_NAME)
+    GCC_BAD ("missing [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+  kind_string = IDENTIFIER_POINTER (x);
+  if (strcmp (kind_string, "default") == 0)
+    global_sso_kind = SSO_DEFAULT;
+  else if (strcmp (kind_string, "big") == 0)
+    global_sso_kind = SSO_BIG_ENDIAN;
+  else if (strcmp (kind_string, "little") == 0)
+    global_sso_kind = SSO_LITTLE_ENDIAN;
+  else
+    GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+}
+
 /* GCC supports two #pragma directives for renaming the external
    symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
    compatibility with the Solaris and VMS system headers.  GCC also
@@ -1457,6 +1509,9 @@  init_pragma (void)
   c_register_pragma (0, "pack", handle_pragma_pack);
 #endif
   c_register_pragma (0, "weak", handle_pragma_weak);
+  c_register_pragma (0, "scalar_storage_order", 
+		     handle_pragma_scalar_storage_order);
+
   c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
 
   c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
Index: c-family/c-pragma.h
===================================================================
--- c-family/c-pragma.h	(revision 224463)
+++ c-family/c-pragma.h	(working copy)
@@ -211,6 +211,7 @@  extern void c_invoke_pragma_handler (uns
 extern void maybe_apply_pragma_weak (tree);
 extern void maybe_apply_pending_pragma_weaks (void);
 extern tree maybe_apply_renaming_pragma (tree, tree);
+extern void maybe_apply_pragma_scalar_storage_order (tree);
 extern void add_to_renaming_pragma_list (tree, tree);
 
 extern enum cpp_ttype pragma_lex (tree *);
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 224700)
+++ c/c-decl.c	(working copy)
@@ -7732,6 +7732,8 @@  finish_struct (location_t loc, tree t, t
       && !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
     error ("type %qT is too large", t);
 
+  maybe_apply_pragma_scalar_storage_order (t);
+
   /* Give bit-fields their proper types and rewrite the type of array fields
      with scalar component if the enclosing type has reverse storage order.  */
   for (tree field = fieldlist; field; field = DECL_CHAIN (field))
Index: testsuite/c-c++-common/sso-5.c
===================================================================
--- testsuite/c-c++-common/sso-5.c	(revision 0)
+++ testsuite/c-c++-common/sso-5.c	(revision 0)
@@ -0,0 +1,72 @@ 
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+
+#pragma scalar_storage_order /* { dg-warning "missing .big-endian.little-endian.default." } */
+
+#pragma scalar_storage_order big-endian
+
+struct S1
+{
+  int i;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) S2
+{
+  int i;
+};
+
+#pragma scalar_storage_order little-endian
+
+struct S3
+{
+  int i;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) S4
+{
+  int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S5
+{
+  int i;
+};
+
+#pragma scalar_storage_order other /* { dg-warning "expected .big-endian.little-endian.default." } */
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 0x12345678 };
+struct S4 my_s4 = { 0x12345678 };
+struct S5 my_s5 = { 0x12345678 };
+
+unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
+unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
+
+int main (void)
+{
+  if (__builtin_memcmp (&my_s1, &big_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  if (__builtin_memcmp (&my_s2, &little_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  if (__builtin_memcmp (&my_s4, &big_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  if (__builtin_memcmp (&my_s5, &little_endian_pattern, 4) != 0)
+    __builtin_abort ();
+#else
+  if (__builtin_memcmp (&my_s5, &big_endian_pattern, 4) != 0)
+    __builtin_abort ();
+#endif
+
+  return 0;
+}
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 224700)
+++ cp/class.c	(working copy)
@@ -34,6 +34,7 @@  along with GCC; see the file COPYING3.
 #include "stor-layout.h"
 #include "attribs.h"
 #include "cp-tree.h"
+#include "c-family/c-pragma.h"
 #include "flags.h"
 #include "toplev.h"
 #include "target.h"
@@ -6657,6 +6658,8 @@  finish_struct_1 (tree t)
   finish_struct_bits (t);
   set_method_tm_attributes (t);
 
+  maybe_apply_pragma_scalar_storage_order (t);
+
   /* Complete the rtl for any static member objects of the type we're
      working on and rewrite the type of array fields with scalar
      component if the enclosing type has reverse storage order.  */