diff mbox

[scalar-storage-order] Add -fsso-struct switch

Message ID 3268126.R4Uy7dkNW7@polaris
State New
Headers show

Commit Message

Eric Botcazou July 2, 2015, 3:33 p.m. UTC
This adds a -fsso-struct switch to the C family of languages that makes it 
possible to change the default scalar storage order (a nice way of shooting 
oneself in the foot if you ask me, but the Ada compiler has its own version of 
this, so that's sort of fair).  It is modelled on #pragma pack/-fpack-struct.

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


	* doc/extend.texi (Structure-Layout Pragmas): Document default value of
	scalar_storage_order and add cross-reference.
	* doc/invoke.texi (C Dialect Options): Document -fsso-struct.
	* flag-types.h (enum scalar_storage_order_kind): New enumeration.
c-family:
	* c.opt (fsso-struct=): New option.
	* c-pragma.c (enum scalar_storage_order_kind): Delete.
	(global_sso_kind): Rename into...
	(global_sso): ...this.  Do not initialize it here.
	(maybe_apply_pragma_scalar_storage_order): Adjust to renaming.
	Replace SSO_DEFAULT with SSO_NATIVE.
	(handle_pragma_scalar_storage_order): Likewise with default_sso.
	(init_pragma): Initialize global_sso to default_sso.
testsuite/
	* c-c++-common/sso-6.c: New test.
	* c-c++-common/sso-7.c: Likewise.
diff mbox

Patch

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 225237)
+++ doc/extend.texi	(working copy)
@@ -18414,8 +18414,9 @@  documented @code{__attribute__ ((scalar_
 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.
+@item @code{#pragma scalar_storage_order default} goes back to the endianness
+that was in effect when compilation started (see also command-line option
+@option{-fsso-struct=@var{endianness}} @pxref{C Dialect Options}).
 @end enumerate
 
 @node Weak Pragmas
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 224467)
+++ doc/invoke.texi	(working copy)
@@ -169,10 +169,11 @@  in the following sections.
 -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
 -fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
 -fhosted  -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol
--fms-extensions -fplan9-extensions -trigraphs -traditional -traditional-cpp @gol
+-fms-extensions -fplan9-extensions -fsso-struct=@var{endianness}
 -fallow-single-precision  -fcond-mismatch -flax-vector-conversions @gol
 -fsigned-bitfields  -fsigned-char @gol
--funsigned-bitfields  -funsigned-char}
+-funsigned-bitfields  -funsigned-char @gol
+-trigraphs -traditional -traditional-cpp}
 
 @item C++ Language Options
 @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@@ -2066,6 +2067,17 @@  These options control whether a bit-fiel
 declaration does not use either @code{signed} or @code{unsigned}.  By
 default, such a bit-field is signed, because this is consistent: the
 basic integer types such as @code{int} are signed types.
+
+@item -fsso-struct=@var{endianness}
+@opindex fsso-struct
+Set the default scalar storage order of structures, unions and classes to
+the specified endianness.  The accepted values are @samp{big-endian} and
+@samp{little-endian}.  If the option is not passed, the compiler uses the
+native endianness of the target.
+
+@strong{Warning:} the @option{-fsso-struct} switch causes GCC to generate
+code that is not binary compatible with code generated without it if the
+specified endianness is not the native endianness of the target.
 @end table
 
 @node C++ Dialect Options
Index: c-family/c.opt
===================================================================
--- c-family/c.opt	(revision 224463)
+++ c-family/c.opt	(working copy)
@@ -1402,6 +1402,19 @@  Enable C++14 sized deallocation support
 fsquangle
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
+fsso-struct=
+C C++ Joined RejectNegative Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE)
+-fsso-struct=[big-endian|little-endian] Set the default scalar storage order
+
+Enum
+Name(sso_struct) Type(enum scalar_storage_order_kind) UnknownError(unrecognized scalar storage order value %qs)
+
+EnumValue
+Enum(sso_struct) String(big-endian) Value(SSO_BIG_ENDIAN)
+
+EnumValue
+Enum(sso_struct) String(little-endian) Value(SSO_LITTLE_ENDIAN)
+
 fstats
 C++ ObjC++ Var(flag_detailed_statistics)
 Display statistics accumulated during compilation
Index: c-family/c-pragma.c
===================================================================
--- c-family/c-pragma.c	(revision 225237)
+++ c-family/c-pragma.c	(working copy)
@@ -400,19 +400,12 @@  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;
+static enum scalar_storage_order_kind global_sso;
 
 void
 maybe_apply_pragma_scalar_storage_order (tree type)
 {
-  if (global_sso_kind == SSO_DEFAULT)
+  if (global_sso == SSO_NATIVE)
     return;
 
   gcc_assert (RECORD_OR_UNION_TYPE_P (type));
@@ -420,9 +413,9 @@  maybe_apply_pragma_scalar_storage_order
   if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
     return;
 
-  if (global_sso_kind == SSO_BIG_ENDIAN)
+  if (global_sso == SSO_BIG_ENDIAN)
     TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
-  else if (global_sso_kind == SSO_LITTLE_ENDIAN)
+  else if (global_sso == SSO_LITTLE_ENDIAN)
     TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
   else
     gcc_unreachable ();
@@ -443,11 +436,11 @@  handle_pragma_scalar_storage_order (cpp_
     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;
+    global_sso = default_sso;
   else if (strcmp (kind_string, "big") == 0)
-    global_sso_kind = SSO_BIG_ENDIAN;
+    global_sso = SSO_BIG_ENDIAN;
   else if (strcmp (kind_string, "little") == 0)
-    global_sso_kind = SSO_LITTLE_ENDIAN;
+    global_sso = SSO_LITTLE_ENDIAN;
   else
     GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
 }
@@ -1509,8 +1502,6 @@  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);
 
@@ -1533,6 +1524,10 @@  init_pragma (void)
   REGISTER_TARGET_PRAGMAS ();
 #endif
 
+  global_sso = default_sso;
+  c_register_pragma (0, "scalar_storage_order", 
+		     handle_pragma_scalar_storage_order);
+
   /* Allow plugins to register their own pragmas. */
   invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
 }
Index: testsuite/c-c++-common/sso-6.c
===================================================================
--- testsuite/c-c++-common/sso-6.c	(revision 0)
+++ testsuite/c-c++-common/sso-6.c	(revision 0)
@@ -0,0 +1,44 @@ 
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+/* { dg-options "-fsso-struct=big-endian" } */
+
+struct S1
+{
+  int i;
+};
+
+#pragma scalar_storage_order little-endian
+
+struct S2
+{
+  int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S3
+{
+  int i;
+};
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 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, &big_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  return 0;
+}
Index: testsuite/c-c++-common/sso-7.c
===================================================================
--- testsuite/c-c++-common/sso-7.c	(revision 0)
+++ testsuite/c-c++-common/sso-7.c	(revision 0)
@@ -0,0 +1,44 @@ 
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+/* { dg-options "-fsso-struct=little-endian" } */
+
+struct S1
+{
+  int i;
+};
+
+#pragma scalar_storage_order big-endian
+
+struct S2
+{
+  int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S3
+{
+  int i;
+};
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 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, &little_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  if (__builtin_memcmp (&my_s2, &big_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
+    __builtin_abort ();
+
+  return 0;
+}
Index: flag-types.h
===================================================================
--- flag-types.h	(revision 224463)
+++ flag-types.h	(working copy)
@@ -171,7 +171,6 @@  enum stack_check_type
 
 /* Names for the different levels of -Wstrict-overflow=N.  The numeric
    values here correspond to N.  */
-
 enum warn_strict_overflow_code
 {
   /* Overflow warning that should be issued with -Wall: a questionable
@@ -201,6 +200,13 @@  enum fp_contract_mode {
   FP_CONTRACT_FAST = 2
 };
 
+/* Scalar storage order kind.  */
+enum scalar_storage_order_kind {
+  SSO_NATIVE = 0,
+  SSO_BIG_ENDIAN,
+  SSO_LITTLE_ENDIAN
+};
+
 /* Vectorizer cost-model.  */
 enum vect_cost_model {
   VECT_COST_MODEL_UNLIMITED = 0,
@@ -209,7 +215,6 @@  enum vect_cost_model {
   VECT_COST_MODEL_DEFAULT = 3
 };
 
-
 /* Different instrumentation modes.  */
 enum sanitize_code {
   /* AddressSanitizer.  */