diff mbox

[2/6] scalar-storage-order merge: C front-end

Message ID 1818790.uuKnpis75z@polaris
State New
Headers show

Commit Message

Eric Botcazou Oct. 6, 2015, 11:02 a.m. UTC
This is the C front-end + C family part.

	* doc/extend.texi (type attributes): Document scalar_storage_order.
	(Structure-Packing Pragmas): Rename into...
	(Structure-Layout Pragmas): ...this.  Document scalar_storage_order.
	* doc/invoke.texi (C Dialect Options): Document -fsso-struct
	(Warnings): Document -Wno-scalar-storage-order.
	* flag-types.h (enum scalar_storage_order_kind): New enumeration.
c-family/
	* c-common.c (c_common_attributes): Add scalar_storage_order.
	(handle_scalar_storage_order_attribute): New function.
	* c-pragma.c (global_sso): 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.opt (Wscalar-storage-order): New warning.
	(fsso-struct=): New option.
c/
	* c-decl.c (finish_struct): If the structure has reverse storage
	order, rewrite the type of array fields with scalar component.  Call
	maybe_apply_pragma_scalar_storage_order on entry.
	* c-typeck.c (build_unary_op) <ADDR_EXPR>: Remove left-overs.  Issue
	errors on bit-fields and reverse SSO here and not...
	(c_mark_addressable): ...here.
	(output_init_element): Adjust call to initializer_constant_valid_p.
	(c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER.

 doc/extend.texi     |   69 ++++++++++++++++++++++++++++++++++++++++++--------
 doc/invoke.texi     |   22 +++++++++++++++-
 flag-types.h        |    9 +++++-
 c-family/c.opt      |   17 ++++++++++++
 c-family/c-common.c |   47 ++++++++++++++++++++++++++++++++++-
 c-family/c-pragma.c |   50 +++++++++++++++++++++++++++++++++++++
 c-family/c-pragma.h |    1 
 c/c-typeck.c        |   66 ++++++++++++++++++++++++++++++++++---------------
 c/c-decl.c          |   48 +++++++++++++++++++++++++-----------
 8 files changed, 273 insertions(+), 47 deletions(-)

Comments

Jeff Law Oct. 13, 2015, 11:32 a.m. UTC | #1
On 10/06/2015 05:02 AM, Eric Botcazou wrote:
> This is the C front-end + C family part.
>
> 	* doc/extend.texi (type attributes): Document scalar_storage_order.
> 	(Structure-Packing Pragmas): Rename into...
> 	(Structure-Layout Pragmas): ...this.  Document scalar_storage_order.
> 	* doc/invoke.texi (C Dialect Options): Document -fsso-struct
> 	(Warnings): Document -Wno-scalar-storage-order.
> 	* flag-types.h (enum scalar_storage_order_kind): New enumeration.
> c-family/
> 	* c-common.c (c_common_attributes): Add scalar_storage_order.
> 	(handle_scalar_storage_order_attribute): New function.
> 	* c-pragma.c (global_sso): 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.opt (Wscalar-storage-order): New warning.
> 	(fsso-struct=): New option.
> c/
> 	* c-decl.c (finish_struct): If the structure has reverse storage
> 	order, rewrite the type of array fields with scalar component.  Call
> 	maybe_apply_pragma_scalar_storage_order on entry.
> 	* c-typeck.c (build_unary_op) <ADDR_EXPR>: Remove left-overs.  Issue
> 	errors on bit-fields and reverse SSO here and not...
> 	(c_mark_addressable): ...here.
> 	(output_init_element): Adjust call to initializer_constant_valid_p.
> 	(c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER.
>
>   doc/extend.texi     |   69 ++++++++++++++++++++++++++++++++++++++++++--------
>   doc/invoke.texi     |   22 +++++++++++++++-
>   flag-types.h        |    9 +++++-
>   c-family/c.opt      |   17 ++++++++++++
>   c-family/c-common.c |   47 ++++++++++++++++++++++++++++++++++-
>   c-family/c-pragma.c |   50 +++++++++++++++++++++++++++++++++++++
>   c-family/c-pragma.h |    1
>   c/c-typeck.c        |   66 ++++++++++++++++++++++++++++++++++---------------
>   c/c-decl.c          |   48 +++++++++++++++++++++++++-----------
>   8 files changed, 273 insertions(+), 47 deletions(-)
>
> -- Eric Botcazou
>
>
> sso-c.diff
>
>
> Index: doc/extend.texi
> ===================================================================
> --- doc/extend.texi	(.../trunk/gcc)	(revision 228112)
> +++ doc/extend.texi	(.../branches/scalar-storage-order/gcc)	(revision 228133)
> @@ -6310,6 +6310,42 @@ of the structure or union is placed to m
> +@itemize
> +@item Taking the address of a scalar field of a @code{union} or a
> +@code{struct} with reverse scalar storage order is not permitted and will
> +yield an error
Seems reasonable.  Certainly avoids a host of problems tracking this 
stuff later I bet.


> +static tree
> +handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
> +				       int flags, bool *no_add_attrs)
> +{
> +  tree id = TREE_VALUE (args);
> +  tree type;
> +
> +  if (TREE_CODE (*node) == TYPE_DECL
> +      && ! (flags & ATTR_FLAG_CXX11))
> +    node = &TREE_TYPE (*node);
> +  type = *node;
> +
> +  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
> +    error ("scalar_storage_order is not supported");
You might want to consider indicating why it's not supported.  Not that 
I expect folks to be using this on a pdp11 :-)



> Index: c/c-typeck.c
> ===================================================================
> --- c/c-typeck.c	(.../trunk/gcc)	(revision 228112)
> +++ c/c-typeck.c	(.../branches/scalar-storage-order/gcc)	(revision 228133)
> @@ -4173,18 +4173,10 @@ build_unary_op (location_t location,
>   	  goto return_build_unary_op;
>   	}
>
> -      /* For &x[y], return x+y */
> -      if (TREE_CODE (arg) == ARRAY_REF)
> -	{
> -	  tree op0 = TREE_OPERAND (arg, 0);
> -	  if (!c_mark_addressable (op0))
> -	    return error_mark_node;
> -	}
Do we still get a proper diagnostic for &x[y] where x isn't something we 
can mark addressable?

Our testsuites aren't particularly good (IMHO) at ensuring we're getting 
diags in all the cases where they're required.

No real objections, assuming that &x[y] diagnostics is still handled 
correctly somewhere.
Eric Botcazou Oct. 19, 2015, 8:34 a.m. UTC | #2
> > +  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
> > +    error ("scalar_storage_order is not supported");
> 
> You might want to consider indicating why it's not supported.  Not that
> I expect folks to be using this on a pdp11 :-)

Done, I added "because endianness is not uniform".

> > -      /* For &x[y], return x+y */
> > -      if (TREE_CODE (arg) == ARRAY_REF)
> > -	{
> > -	  tree op0 = TREE_OPERAND (arg, 0);
> > -	  if (!c_mark_addressable (op0))
> > -	    return error_mark_node;
> > -	}
> 
> Do we still get a proper diagnostic for &x[y] where x isn't something we
> can mark addressable?

Yes, c_mark_addressable is invoked on 'arg' later and the function looks into 
the prefix of an ARRAY_REF

> No real objections, assuming that &x[y] diagnostics is still handled
> correctly somewhere.

OK, thanks.
Joseph Myers Oct. 28, 2015, 4:43 p.m. UTC | #3
Why is -fsso-struct= listed only for C and C++, not ObjC and ObjC++?  
Almost all C options should be supported for ObjC and almost all C++ 
options should be supported for ObjC++ (and the existing cases that aren't 
in c.opt generally look dubious).
Jeff Law Oct. 28, 2015, 5:26 p.m. UTC | #4
On 10/28/2015 10:43 AM, Joseph Myers wrote:
> Why is -fsso-struct= listed only for C and C++, not ObjC and ObjC++?
> Almost all C options should be supported for ObjC and almost all C++
> options should be supported for ObjC++ (and the existing cases that aren't
> in c.opt generally look dubious).
I missed it in the review.  However, I think verifying that it works 
with ObjC/C++ should be done prior to adding it though.

jeff
Eric Botcazou Oct. 28, 2015, 10:04 p.m. UTC | #5
> Why is -fsso-struct= listed only for C and C++, not ObjC and ObjC++?

Because it was not tested with the latter 2 languages at all and may require 
specific adjustments in the respective front-ends to work.

> Almost all C options should be supported for ObjC and almost all C++
> options should be supported for ObjC++ (and the existing cases that aren't
> in c.opt generally look dubious).

Sorry, I have zero experience with ObjC and objC++, let alone their front-end.
Mike Stump Oct. 28, 2015, 11:18 p.m. UTC | #6
On Oct 28, 2015, at 3:04 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> Why is -fsso-struct= listed only for C and C++, not ObjC and ObjC++?
> 
> Because it was not tested with the latter 2 languages at all and may require 
> specific adjustments in the respective front-ends to work.

It won’t.  Fixing the language line for the options and a make to ensure it still builds for you is enough testing.

>> Almost all C options should be supported for ObjC and almost all C++
>> options should be supported for ObjC++ (and the existing cases that aren't
>> in c.opt generally look dubious).
> 
> Sorry, I have zero experience with ObjC and objC++, let alone their front-end.

None is needed.  One merely copies the string as found on other options for your new options, and you’re done.  Indeed, the default should be to always include the objective languages unless one goes out of their way to exclude them.
Joseph Myers Oct. 28, 2015, 11:36 p.m. UTC | #7
On Wed, 28 Oct 2015, Mike Stump wrote:

> On Oct 28, 2015, at 3:04 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> >> Why is -fsso-struct= listed only for C and C++, not ObjC and ObjC++?
> > 
> > Because it was not tested with the latter 2 languages at all and may require 
> > specific adjustments in the respective front-ends to work.
> 
> It won’t.  Fixing the language line for the options and a make to ensure 
> it still builds for you is enough testing.

There *can* be cases where one knows that updates would be needed to 
support a new feature for ObjC and ObjC++.  But those are the exception 
rather than the rule and should have a specific comment explaining what 
the issue is and what would need to be done to enable the feature for 
them.  I don't see why that would apply in this case, so I think just 
adding the languages in c.opt should be enough.  (Cf. for C11 _Atomic:

        case RID_ATOMIC:
          /* C parser handling of Objective-C constructs needs
             checking for correct lvalue-to-rvalue conversions, and
             the code in build_modify_expr handling various
             Objective-C cases, and that in build_unary_op handling
             Objective-C cases for increment / decrement, also needs
             updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
             and objc_types_are_equivalent may also need updates.  */
          if (c_dialect_objc ())
            sorry ("%<_Atomic%> in Objective-C");

but no other C11 feature needed any such disabling for ObjC.  [_Atomic has 
similar disabling for OpenMP, again because of parser constructs involving 
lvalue-to-rvalue conversions that would need updating to generate proper 
atomic loads via convert_lvalue_to_rvalue or otherwise.])
Eric Botcazou Oct. 30, 2015, 8:56 a.m. UTC | #8
> It won’t.  Fixing the language line for the options and a make to ensure it
> still builds for you is enough testing.

I was talking about the feature itself though, not about the option per se.  
The feature is tested for C & C++ but not for ObjC & ObjC++ so there might be 
surprises.

> None is needed.  One merely copies the string as found on other options for
> your new options, and you’re done.  Indeed, the default should be to always
> include the objective languages unless one goes out of their way to exclude
> them.

OK, I can enable the option for ObjC & ObjC++ but this comes with no warranty.
Mike Stump Oct. 30, 2015, 2:47 p.m. UTC | #9
On Oct 30, 2015, at 1:56 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> It won’t.  Fixing the language line for the options and a make to ensure it
>> still builds for you is enough testing.
> 
> I was talking about the feature itself though, not about the option per se.  
> The feature is tested for C & C++ but not for ObjC & ObjC++ so there might be 
> surprises.

We welcome such testing, qualification and bug fixing; not a strict requirement on submissions as far as I know.  Some things won’t work well without a concerted effort, and I don’t think it is fair to contributors to require they learn Objective-C/C++ to make such a contribution.  All we generally ask for is that what works today, remain working.  This usually just means leave the existing hooks in and as code moves around, one has to move the hook around.  Whenever a feature conflicts with an Objective feature, I think a nice rule of thumb is that cost is born by the Objective people.  We don’t want to make life any more difficult on anyone else.

> OK, I can enable the option for ObjC & ObjC++ but this comes with no warranty.

Yeah, that’s standard operating procedure.
diff mbox

Patch

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(.../trunk/gcc)	(revision 228112)
+++ doc/extend.texi	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -6310,6 +6310,42 @@  of the structure or union is placed to m
 attached to an @code{enum} definition, it indicates that the smallest
 integral type should be used.
 
+@item scalar_storage_order ("@var{endianness}")
+@cindex @code{scalar_storage_order} type attribute
+When attached to a @code{union} or a @code{struct}, this attribute sets
+the storage order, aka endianness, of the scalar fields of the type, as
+well as the array fields whose component is scalar.  The supported
+endianness are @code{big-endian} and @code{little-endian}.  The attribute
+has no effects on fields which are themselves a @code{union}, a @code{struct}
+or an array whose component is a @code{union} or a @code{struct}, and it is
+possible to have fields with a different scalar storage order than the
+enclosing type.
+
+This attribute is supported only for targets that use a uniform default
+scalar storage order (fortunately, most of them), i.e. targets that store
+the scalars either all in big-endian or all in little-endian.
+
+Additional restrictions are enforced for types with the reverse scalar
+storage order with regard to the scalar storage order of the target:
+
+@itemize
+@item Taking the address of a scalar field of a @code{union} or a
+@code{struct} with reverse scalar storage order is not permitted and will
+yield an error
+@item Taking the address of an array field, whose component is scalar, of
+a @code{union} or a @code{struct} with reverse scalar storage order is
+permitted but will yield a warning, unless @option{-Wno-scalar-storage-order}
+is specified
+@item Taking the address of a @code{union} or a @code{struct} with reverse
+scalar storage order is permitted
+@end itemize
+
+These restrictions exist because the storage order attribute is lost when
+the address of a scalar or the address of an array with scalar component
+is taken, so storing indirectly through this address will generally not work.
+The second case is nevertheless allowed to be able to perform a block copy
+from or to the array.
+
 @item transparent_union
 @cindex @code{transparent_union} type attribute
 
@@ -18326,7 +18362,7 @@  for further explanation.
 * Darwin Pragmas::
 * Solaris Pragmas::
 * Symbol-Renaming Pragmas::
-* Structure-Packing Pragmas::
+* Structure-Layout Pragmas::
 * Weak Pragmas::
 * Diagnostic Pragmas::
 * Visibility Pragmas::
@@ -18602,8 +18638,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
@@ -18626,17 +18662,30 @@  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 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
 @subsection Weak Pragmas
 
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(.../trunk/gcc)	(revision 228112)
+++ doc/invoke.texi	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -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}.
@@ -278,6 +279,7 @@  Objective-C and Objective-C++ Dialects}.
 -Wshift-overflow -Wshift-overflow=@var{n} @gol
 -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
 -Wsign-compare  -Wsign-conversion -Wfloat-conversion @gol
+-Wno-scalar-storage-order @gol
 -Wsizeof-pointer-memaccess  -Wsizeof-array-argument @gol
 -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
 -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@@ -2069,6 +2071,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
@@ -5087,6 +5100,11 @@  This includes conversions from real to i
 real to lower precision real values.  This option is also enabled by
 @option{-Wconversion}.
 
+@item -Wno-scalar-storage-order
+@opindex -Wno-scalar-storage-order
+@opindex -Wscalar-storage-order
+Do not warn on suspicious constructs involving reverse scalar storage order.
+
 @item -Wsized-deallocation @r{(C++ and Objective-C++ only)}
 @opindex Wsized-deallocation
 @opindex Wno-sized-deallocation
Index: flag-types.h
===================================================================
--- flag-types.h	(.../trunk/gcc)	(revision 228112)
+++ flag-types.h	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -158,7 +158,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
@@ -188,6 +187,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,
@@ -196,7 +202,6 @@  enum vect_cost_model {
   VECT_COST_MODEL_DEFAULT = 3
 };
 
-
 /* Different instrumentation modes.  */
 enum sanitize_code {
   /* AddressSanitizer.  */
Index: c-family/c.opt
===================================================================
--- c-family/c.opt	(.../trunk/gcc)	(revision 228112)
+++ c-family/c.opt	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -784,6 +784,10 @@  Wreturn-type
 C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
 Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
 
+Wscalar-storage-order
+C ObjC C++ ObjC++ Init(1) Warning
+Warn on suspicious constructs involving reverse scalar storage order
+
 Wselector
 ObjC ObjC++ Var(warn_selector) Warning
 Warn if a selector has multiple methods
@@ -1447,6 +1451,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-common.c
===================================================================
--- c-family/c-common.c	(.../trunk/gcc)	(revision 228112)
+++ c-family/c-common.c	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -344,6 +344,8 @@  static tree handle_no_reorder_attribute
 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
 static tree handle_transparent_union_attribute (tree *, tree, tree,
 						int, bool *);
+static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
+						   int, bool *);
 static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
 static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
 static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
@@ -692,6 +694,8 @@  const struct attribute_spec c_common_att
   /* The same comments as for noreturn attributes apply to const ones.  */
   { "const",                  0, 0, true,  false, false,
 			      handle_const_attribute, false },
+  { "scalar_storage_order",   1, 1, false, false, false,
+			      handle_scalar_storage_order_attribute, false },
   { "transparent_union",      0, 0, false, false, false,
 			      handle_transparent_union_attribute, false },
   { "constructor",            0, 1, true,  false, false,
@@ -7636,6 +7640,48 @@  handle_const_attribute (tree *node, tree
   return NULL_TREE;
 }
 
+/* Handle a "scalar_storage_order" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
+				       int flags, bool *no_add_attrs)
+{
+  tree id = TREE_VALUE (args);
+  tree type;
+
+  if (TREE_CODE (*node) == TYPE_DECL
+      && ! (flags & ATTR_FLAG_CXX11))
+    node = &TREE_TYPE (*node);
+  type = *node;
+
+  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+    error ("scalar_storage_order is not supported");
+
+  if (RECORD_OR_UNION_TYPE_P (type))
+    {
+      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+	goto ignored;
+
+      if (TREE_CODE (id) == STRING_CST
+	  && strcmp (TREE_STRING_POINTER (id), "big-endian") == 0)
+	TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+      else if (TREE_CODE (id) == STRING_CST
+	       && strcmp (TREE_STRING_POINTER (id), "little-endian") == 0)
+	TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
+      else
+	error ("scalar_storage_order argument must be one of \"big-endian\" "
+	       "or \"little-endian\"");
+
+      return NULL_TREE;
+    }
+
+ ignored:
+  warning (OPT_Wattributes, "%qE attribute ignored", name);
+  *no_add_attrs = true;
+  return NULL_TREE;
+}
+
 /* Handle a "transparent_union" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -7648,7 +7694,6 @@  handle_transparent_union_attribute (tree
 
   *no_add_attrs = true;
 
-
   if (TREE_CODE (*node) == TYPE_DECL
       && ! (flags & ATTR_FLAG_CXX11))
     node = &TREE_TYPE (*node);
Index: c-family/c-pragma.c
===================================================================
--- c-family/c-pragma.c	(.../trunk/gcc)	(revision 228112)
+++ c-family/c-pragma.c	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -394,6 +394,51 @@  handle_pragma_weak (cpp_reader * ARG_UNU
     }
 }
 
+static enum scalar_storage_order_kind global_sso;
+
+void
+maybe_apply_pragma_scalar_storage_order (tree type)
+{
+  if (global_sso == SSO_NATIVE)
+    return;
+
+  gcc_assert (RECORD_OR_UNION_TYPE_P (type));
+
+  if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
+    return;
+
+  if (global_sso == SSO_BIG_ENDIAN)
+    TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+  else if (global_sso == 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 = default_sso;
+  else if (strcmp (kind_string, "big") == 0)
+    global_sso = SSO_BIG_ENDIAN;
+  else if (strcmp (kind_string, "little") == 0)
+    global_sso = 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
@@ -1485,6 +1530,7 @@  init_pragma (void)
   c_register_pragma (0, "pack", handle_pragma_pack);
 #endif
   c_register_pragma (0, "weak", handle_pragma_weak);
+
   c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
 
   c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
@@ -1506,6 +1552,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: c-family/c-pragma.h
===================================================================
--- c-family/c-pragma.h	(.../trunk/gcc)	(revision 228112)
+++ c-family/c-pragma.h	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -210,6 +210,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 *, location_t *loc = NULL);
Index: c/c-typeck.c
===================================================================
--- c/c-typeck.c	(.../trunk/gcc)	(revision 228112)
+++ c/c-typeck.c	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -4173,18 +4173,10 @@  build_unary_op (location_t location,
 	  goto return_build_unary_op;
 	}
 
-      /* For &x[y], return x+y */
-      if (TREE_CODE (arg) == ARRAY_REF)
-	{
-	  tree op0 = TREE_OPERAND (arg, 0);
-	  if (!c_mark_addressable (op0))
-	    return error_mark_node;
-	}
-
       /* Anything not already handled and not a true memory reference
 	 or a non-lvalue array is an error.  */
-      else if (typecode != FUNCTION_TYPE && !flag
-	       && !lvalue_or_else (location, arg, lv_addressof))
+      if (typecode != FUNCTION_TYPE && !flag
+	  && !lvalue_or_else (location, arg, lv_addressof))
 	return error_mark_node;
 
       /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -4222,6 +4214,39 @@  build_unary_op (location_t location,
 	  argtype = c_build_qualified_type (argtype, quals);
 	}
 
+      switch (TREE_CODE (arg))
+	{
+	case COMPONENT_REF:
+	  if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+	    {
+	      error ("cannot take address of bit-field %qD",
+		     TREE_OPERAND (arg, 1));
+	      return error_mark_node;
+	    }
+
+	  /* ... fall through ...  */
+
+	case ARRAY_REF:
+	  if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
+	    {
+	      if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
+		  && !VECTOR_TYPE_P (TREE_TYPE (arg)))
+		{
+		  error ("cannot take address of scalar with reverse storage "
+			 "order");
+		  return error_mark_node;
+		}
+
+	      if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
+		  && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
+		warning (OPT_Wscalar_storage_order, "address of array with "
+			"reverse scalar storage order requested");
+	    }
+
+	default:
+	  break;
+	}
+
       if (!c_mark_addressable (arg))
 	return error_mark_node;
 
@@ -4364,15 +4389,6 @@  c_mark_addressable (tree exp)
     switch (TREE_CODE (x))
       {
       case COMPONENT_REF:
-	if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
-	  {
-	    error
-	      ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
-	    return false;
-	  }
-
-	/* ... fall through ...  */
-
       case ADDR_EXPR:
       case ARRAY_REF:
       case REALPART_EXPR:
@@ -8423,7 +8439,11 @@  output_init_element (location_t loc, tre
     constructor_erroneous = 1;
   else if (!TREE_CONSTANT (value))
     constructor_constant = 0;
-  else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
+  else if (!initializer_constant_valid_p (value,
+					  TREE_TYPE (value),
+					  AGGREGATE_TYPE_P (constructor_type)
+					  && TYPE_REVERSE_STORAGE_ORDER
+					     (constructor_type))
 	   || ((TREE_CODE (constructor_type) == RECORD_TYPE
 		|| TREE_CODE (constructor_type) == UNION_TYPE)
 	       && DECL_C_BIT_FIELD (field)
@@ -12661,6 +12681,12 @@  c_build_qualified_type (tree type, int t
                 = build_array_type (TYPE_CANONICAL (element_type),
                                     domain? TYPE_CANONICAL (domain)
                                           : NULL_TREE);
+              if (TYPE_REVERSE_STORAGE_ORDER (type))
+                {
+                  unqualified_canon
+                    = build_distinct_type_copy (unqualified_canon);
+                  TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
+                }
               TYPE_CANONICAL (t)
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(.../trunk/gcc)	(revision 228112)
+++ c/c-decl.c	(.../branches/scalar-storage-order/gcc)	(revision 228133)
@@ -7723,6 +7723,8 @@  finish_struct (location_t loc, tree t, t
 
   TYPE_FIELDS (t) = fieldlist;
 
+  maybe_apply_pragma_scalar_storage_order (t);
+
   layout_type (t);
 
   if (TYPE_SIZE_UNIT (t)
@@ -7731,27 +7733,45 @@  finish_struct (location_t loc, tree t, t
       && !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
     error ("type %qT is too large", t);
 
-  /* Give bit-fields their proper types.  */
-  {
-    tree *fieldlistp = &fieldlist;
-    while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
-	  && TREE_TYPE (*fieldlistp) != error_mark_node)
+  /* 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))
+    {
+      if (TREE_CODE (field) == FIELD_DECL
+	  && DECL_INITIAL (field)
+	  && TREE_TYPE (field) != error_mark_node)
 	{
 	  unsigned HOST_WIDE_INT width
-	    = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
-	  tree type = TREE_TYPE (*fieldlistp);
+	    = tree_to_uhwi (DECL_INITIAL (field));
+	  tree type = TREE_TYPE (field);
 	  if (width != TYPE_PRECISION (type))
 	    {
-	      TREE_TYPE (*fieldlistp)
+	      TREE_TYPE (field)
 		= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
-	      DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+	      DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
+	    }
+	  DECL_INITIAL (field) = 0;
+	}
+      else if (TYPE_REVERSE_STORAGE_ORDER (t)
+	       && TREE_CODE (field) == FIELD_DECL
+	       && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
+	{
+	  tree ftype = TREE_TYPE (field);
+	  tree ctype = strip_array_types (ftype);
+	  if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode)
+	    {
+	      tree fmain_type = TYPE_MAIN_VARIANT (ftype);
+	      tree *typep = &fmain_type;
+	      do {
+		*typep = build_distinct_type_copy (*typep);
+		TYPE_REVERSE_STORAGE_ORDER (*typep) = 1;
+		typep = &TREE_TYPE (*typep);
+	      } while (TREE_CODE (*typep) == ARRAY_TYPE);
+	      TREE_TYPE (field)
+		= c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
 	    }
-	  DECL_INITIAL (*fieldlistp) = 0;
 	}
-      else
-	fieldlistp = &DECL_CHAIN (*fieldlistp);
-  }
+    }
 
   /* Now we have the truly final field list.
      Store it in this type and in the variants.  */