Skip to content

Commit

Permalink
Add scalar_storage_order support to C++
Browse files Browse the repository at this point in the history
This patch adds support scalar_storage_order attribute to C++ front-end.
It treats the opposite order fields similar as the packed fields are
treated such that they will not bind to references.
For arrays, the attributes applies to the inner type rather than the array
type similar. The code is similar to how it is handled in the C front-end.

2021-04-03  Andrew Pinski   <apinski@marvell.com>

gcc/ChangeLog:

	* c-family/c-attribs.cc (handle_scalar_storage_order_attribute):
	Do not reject the C++ cases.
	* cp/class.cc (layout_nonempty_base_or_field): Fix the type of
	arrays in C++.
	* cp/call.cc (reference_binding): Treat reversed field similar as
	packed fields.
	(build_temp): Likewise.
	(convert_like_internal): Emit error code for non binding reversed
	endian field.
	* cp/cp-tree.h (clk_implicit_rval) : Add clk_reversed.
	* cp/cp-tree.c (lvalue_kind) : Handle reverse storage ordered operands.

gcc/testsuite/ChangeLog:

	* c-c++-common/sso/dump.h: Move from gcc.dg/sso to c-c++-common/sso.
	* c-c++-common/sso/init1.h: Likewise.
	* c-c++-common/sso/init13.h: Likewise.
	* c-c++-common/sso/init2.h: Likewise.
	* c-c++-common/sso/init3.h: Likewise.
	* c-c++-common/sso/init4.h: Likewise.
	* c-c++-common/sso/init5.h: Likewise.
	* c-c++-common/sso/init6.h: Likewise.
	* c-c++-common/sso/init7.h: Likewise.
	* c-c++-common/sso/init8.h: Likewise.
	* c-c++-common/sso/init9.h: Likewise.
	* c-c++-common/sso/p1.c: Likewise.
	* c-c++-common/sso/p13.c: Likewise.
	* c-c++-common/sso/p2.c: Likewise.
	* c-c++-common/sso/p3.c: Likewise.
	* c-c++-common/sso/p4.c: Likewise.
	* c-c++-common/sso/p5.c: Likewise.
	* c-c++-common/sso/p6.c: Likewise.
	* c-c++-common/sso/p7.c: Likewise.
	* c-c++-common/sso/p8.c: Likewise.
	* c-c++-common/sso/p9.c: Likewise.
	* c-c++-common/sso/q1.c: Likewise.
	* c-c++-common/sso/q13.c: Likewise.
	* c-c++-common/sso/q2.c: Likewise.
	* c-c++-common/sso/q3.c: Likewise.
	* c-c++-common/sso/q4.c: Likewise.
	* c-c++-common/sso/q5.c: Likewise.
	* c-c++-common/sso/q6.c: Likewise.
	* c-c++-common/sso/q7.c: Likewise.
	* c-c++-common/sso/q8.c: Likewise.
	* c-c++-common/sso/q9.c: Likewise.
	* c-c++-common/sso/r3.c: Likewise.
	* c-c++-common/sso/r5.c: Likewise.
	* c-c++-common/sso/r6.c: Likewise.
	* c-c++-common/sso/r7.c: Likewise.
	* c-c++-common/sso/r8.c: Likewise.
	* c-c++-common/sso/s3.c: Likewise.
	* c-c++-common/sso/s5.c: Likewise.
	* c-c++-common/sso/s6.c: Likewise.
	* c-c++-common/sso/s7.c: Likewise.
	* c-c++-common/sso/s8.c: Likewise.
	* c-c++-common/sso/t1.c: Likewise.
	* c-c++-common/sso/t13.c: Likewise.
	* c-c++-common/sso/t2.c: Likewise.
	* c-c++-common/sso/t3.c: Likewise.
	* c-c++-common/sso/t4.c: Likewise.
	* c-c++-common/sso/t5.c: Likewise.
	* c-c++-common/sso/t6.c: Likewise.
	* c-c++-common/sso/t7.c: Likewise.
	* c-c++-common/sso/t8.c: Likewise.
	* c-c++-common/sso/t9.c: Likewise.
	* c-c++-common/sso/u5.c: Likewise.
	* c-c++-common/sso/t6.c: Likewise.
	* g++.dg/sso/sso.exp: New file.
	* g++.dg/sso/auto-1.C: New file.
	* g++.dg/sso/auto-2.C: New file.
	* g++.dg/sso/auto-3.C: New file.
	* g++.dg/sso/template-reference-1.C: New file.
	* g++.dg/sso/template-reference-2.C: New file.
	* g++.dg/sso/template-reference-3.C: New file.
	* g++.dg/sso/template-reference-4.C: New file.
	* g++.dg/sso-1.C: Modified.

Co-authored-by: Naveen H S <naveenh@marvell.com>
  • Loading branch information
Naveen H S authored and ouuleilei-bot committed May 25, 2023
1 parent c2d62cd commit a7b55e0
Show file tree
Hide file tree
Showing 68 changed files with 220 additions and 7 deletions.
2 changes: 1 addition & 1 deletion gcc/c-family/c-attribs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,7 @@ handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
return NULL_TREE;
}

if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ())
if (RECORD_OR_UNION_TYPE_P (type))
{
bool reverse = false;

Expand Down
17 changes: 15 additions & 2 deletions gcc/cp/call.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
= (TYPE_REF_IS_RVALUE (rto) == !is_lvalue);

if ((gl_kind & clk_bitfield) != 0
|| ((gl_kind & clk_packed) != 0 && !TYPE_PACKED (to)))
|| ((gl_kind & clk_packed) != 0 && !TYPE_PACKED (to))
|| (gl_kind & clk_reversed) != 0)
/* For the purposes of overload resolution, we ignore the fact
this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
Expand Down Expand Up @@ -8084,7 +8085,8 @@ build_temp (tree expr, tree type, int flags,
binding the field to the reference parameter to the copy constructor, and
we'll end up with an infinite loop. If we can use a bitwise copy, then
do that now. */
if ((lvalue_kind (expr) & clk_packed)
if (((lvalue_kind (expr) & clk_packed)
|| (lvalue_kind (expr) & clk_reversed))
&& CLASS_TYPE_P (TREE_TYPE (expr))
&& !type_has_nontrivial_copy_init (TREE_TYPE (expr)))
return get_target_expr (expr, complain);
Expand Down Expand Up @@ -8781,6 +8783,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
else if (lvalue & clk_packed)
error_at (loc, "cannot bind packed field %qE to %qT",
expr, ref_type);
else if (lvalue & clk_reversed)
error_at (loc, "cannot bind reversed endian field %qE to %qT",
expr, ref_type);
else
error_at (loc, "cannot bind rvalue %qE to %qT",
expr, ref_type);
Expand All @@ -8801,6 +8806,14 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
expr, ref_type);
return error_mark_node;
}
if ((lvalue & clk_reversed)
&& CLASS_TYPE_P (type)
&& type_has_nontrivial_copy_init (type))
{
error_at (loc, "cannot bind reversed endian field %qE to %qT",
expr, ref_type);
return error_mark_node;
}
if (lvalue & clk_bitfield)
{
expr = convert_bitfield_to_declared_type (expr);
Expand Down
22 changes: 22 additions & 0 deletions gcc/cp/class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4387,6 +4387,28 @@ layout_nonempty_base_or_field (record_layout_info rli,
field_p = true;
}

/* Rewrite the type of array fields with scalar component
if the enclosing type has reverse storage order */
if (TYPE_REVERSE_STORAGE_ORDER (rli->t)
&& TREE_CODE (decl) == FIELD_DECL
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
tree ftype = TREE_TYPE (decl);
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 (decl)
= cp_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
}
}

/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
same type at the same address. */
Expand Down
3 changes: 2 additions & 1 deletion gcc/cp/cp-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5464,7 +5464,8 @@ enum cp_lvalue_kind_flags {
clk_class = 4, /* A prvalue of class or array type. */
clk_bitfield = 8, /* An lvalue for a bit-field. */
clk_packed = 16, /* An lvalue for a packed field. */
clk_implicit_rval = 1<<5 /* An lvalue being treated as an xvalue. */
clk_implicit_rval = 1<<5, /* An lvalue being treated as an xvalue. */
clk_reversed = 1<<6 /* An lvalue for a reversed field. */
};

/* This type is used for parameters and variables which hold
Expand Down
5 changes: 4 additions & 1 deletion gcc/cp/tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ lvalue_kind (const_tree ref)
}
else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
op1_lvalue_kind |= clk_packed;
else if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0)))
&& TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (ref, 0))))
op1_lvalue_kind |= clk_reversed;

return op1_lvalue_kind;

Expand Down Expand Up @@ -342,7 +345,7 @@ lvalue_kind (const_tree ref)
/* It can't be both a pseudo-lvalue and a non-addressable lvalue.
A COND_EXPR of those should be wrapped in a TARGET_EXPR. */
if ((op1_lvalue_kind & (clk_rvalueref|clk_class))
&& (op1_lvalue_kind & (clk_bitfield|clk_packed)))
&& (op1_lvalue_kind & (clk_bitfield|clk_packed|clk_reversed)))
op1_lvalue_kind = clk_none;
return op1_lvalue_kind;
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* { dg-do run } */
/* { dg-additional-options "-fext-numeric-literals" { target c++ } } */

#include <stdio.h>

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* { dg-do run } */
/* { dg-additional-options "-fext-numeric-literals" { target c++ } } */

#include <stdio.h>

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* { dg-do run } */
/* { dg-additional-options "-fext-numeric-literals" { target c++ } } */

#include <stdio.h>

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion gcc/testsuite/g++.dg/sso-1.C
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/* { dg-do compile } */

struct __attribute__((scalar_storage_order("little-endian"))) Rec /* { dg-warning "attribute ignored" } */
struct __attribute__((scalar_storage_order("little-endian"))) Rec /* { dg-bogus "attribute ignored" } */
{
int i;
};
17 changes: 17 additions & 0 deletions gcc/testsuite/g++.dg/sso/auto-1.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* { dg-do compile { target c++11 } } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif

void f(Rec *a)
{
auto t = a->p;
}
17 changes: 17 additions & 0 deletions gcc/testsuite/g++.dg/sso/auto-2.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* { dg-do compile { target c++14 } } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif

decltype(auto) f(Rec *a)
{
return a->p;
}
17 changes: 17 additions & 0 deletions gcc/testsuite/g++.dg/sso/auto-3.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* { dg-do compile { target c++14 } } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif

decltype(auto) f(Rec *a)
{
return (a->p); /* { dg-error "" } */
}
44 changes: 44 additions & 0 deletions gcc/testsuite/g++.dg/sso/sso.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright (C) 2013-2017 Free Software Foundation, Inc.

# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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 COPYING3. If not see
# <http://www.gnu.org/licenses/>.

# Load support procs.
load_lib g++-dg.exp
load_lib torture-options.exp

if { ![check_effective_target_int32] } {
return
}

# Initialize `dg'.
torture-init
dg-init

set SSO_TORTURE_OPTIONS [list \
{ -O0 } \
{ -O1 -fno-inline } \
{ -O2 } \
{ -O3 -finline-functions } \
{ -Os } \
{ -Og -g } ]

set-torture-options $SSO_TORTURE_OPTIONS

# Main loop.
g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/sso/*.c ]] "" ""

# All done.
dg-finish
torture-finish
19 changes: 19 additions & 0 deletions gcc/testsuite/g++.dg/sso/template-reference-1.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* { dg-do compile } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif
template <typename T> void g(const T &);


void f(Rec *a)
{
g(a->p);
}
19 changes: 19 additions & 0 deletions gcc/testsuite/g++.dg/sso/template-reference-2.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* { dg-do compile } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif
template <typename T> void g(T &);


void f(Rec *a)
{
g(a->p); /* { dg-error "" } */
}
19 changes: 19 additions & 0 deletions gcc/testsuite/g++.dg/sso/template-reference-3.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* { dg-do compile { target c++11 } } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif
template <typename T> void g(T &&);


void f(Rec *a)
{
g(a->p); /* { dg-error "" } */
}
19 changes: 19 additions & 0 deletions gcc/testsuite/g++.dg/sso/template-reference-4.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* { dg-do compile } */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int p;
};
#endif
template <typename T> void g(T &);


void f(Rec *a)
{
g( (a->p)); /* { dg-error "" } */
}
2 changes: 1 addition & 1 deletion gcc/testsuite/gcc.dg/sso/sso.exp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ set SSO_TORTURE_OPTIONS [list \
set-torture-options $SSO_TORTURE_OPTIONS

# Main loop.
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] "" ""
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/sso/*.c ]] "" ""

# All done.
dg-finish
Expand Down

0 comments on commit a7b55e0

Please sign in to comment.