diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-02-07 09:30:58 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-02-17 12:49:32 -0800 |
commit | f7279941c6631f049360687029f464205c878bb4 (patch) | |
tree | 44fa8417f1c27fb6d520a0357aaacf704ce8d35c /gcc | |
parent | 1ed49e03e6ad9dc02dd460705125d7f579d05aeb (diff) | |
download | gcc-hjl/pr60336/x86.tar.gz |
Add TYPE_EMPTY_RECORD for C++ empty classhjl/pr60336/x86
Empty record should be returned and passed the same way in C and C++.
This patch overloads a bit, side_effects_flag, in tree_base for C++
empty class. Middle-end and x86 backend are updated to ignore empty
records for parameter passing and function value return. Other targets
may need similar changes.
get_ref_base_and_extent is changed to set bitsize to 0 for empty records
so that when ref_maybe_used_by_call_p_1 calls get_ref_base_and_extent to
get 0 as the maximum size on empty record. Otherwise, find_tail_calls
won't perform tail call optimization for functions with empty record
parameters, as shown in g++.dg/pr60336-1.C and g++.dg/pr60336-2.C.
A new cxx target hook, function_skip_empty_class_p, is added, which
defaults to return false. This ABI change is enabled only if the ABI
level is at least 10, which is updated in GCC 6, and the target hook
TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P returns true.
gcc/
PR c++/60336
PR middle-end/67239
PR target/68355
* calls.c (initialize_argument_information): Warn empty record
if they are used in a variable argument list or aren't the last
arguments. Replace targetm.calls.function_arg,
targetm.calls.function_incoming_arg and
targetm.calls.function_arg_advance with function_arg,
function_incoming_arg and function_arg_advance.
(expand_call): Replace targetm.calls.function_arg,
targetm.calls.function_incoming_arg and
targetm.calls.function_arg_advance with function_arg,
function_incoming_arg and function_arg_advance.
(emit_library_call_value_1): Likewise.
(store_one_arg): Use 0 for empty record size. Don't
push 0 size argument onto stack.
(must_pass_in_stack_var_size_or_pad): Return false for empty
record.
* dse.c (get_call_args): Replace targetm.calls.function_arg
and targetm.calls.function_arg_advance with function_arg and
function_arg_advance.
* explow.c (hard_function_value): Use 0 for empty record size.
* expr.c (block_move_libcall_safe_for_call_parm): Replace
targetm.calls.function_arg and targetm.calls.function_arg_advance
with function_arg and function_arg_advance.
(copy_blkmode_to_reg): Use 0 for empty record size.
* function.c (aggregate_value_p): Replace
targetm.calls.return_in_memory with return_in_memory.
(assign_parm_data_all): Add warn_empty_record.
(assign_parms_augmented_arg_list): Set warn_empty_record if
empty records are used in a variable argument list or aren't
the last arguments.
(assign_parm_find_entry_rtl): Warn empty record if
warn_empty_record is set. Replace
targetm.calls.function_incoming_arg with function_incoming_arg.
(assign_parms): Only warn empty record once. Replace
targetm.calls.function_arg_advance with function_arg_advance.
(gimplify_parameters): Replace targetm.calls.function_arg_advance
with function_arg_advance.
(locate_and_pad_parm): Use 0 for empty record size.
(warn_empty_record): New function.
(function_arg_advance): New wrapper function.
(function_arg): Likewise.
(function_incoming_arg): Likewise.
(return_in_memory): Likewise.
* lto-streamer-out.c (hash_tree): Call hstate.add_flag with
TYPE_EMPTY_RECORD for types.
* print-tree.c (print_node): Also handle TYPE_EMPTY_RECORD.
* ubsan.c (ubsan_type_descriptor): Likewise.
* target.def (cxx): Add function_skip_empty_class_p.
* target.h (function_arg_advance): New prototype.
(function_arg): Likewise.
(function_incoming_arg): Likewise.
(return_in_memory): Likewise.
* targhooks.c (std_gimplify_va_arg_expr): Use 0 for empty record
size.
* tree-dfa.c (get_ref_base_and_extent): Likewise.
* tree-core.h (tree_base): Mention TYPE_EMPTY_RECORD in comments
for side_effects_flag.
* tree-streamer-in.c (unpack_ts_base_value_fields): Stream in
TYPE_EMPTY_RECORD for types.
* tree-streamer-out.c (pack_ts_base_value_fields): Stream out
TYPE_EMPTY_RECORD for types.
* tree.h (TYPE_EMPTY_RECORD): New.
(type_is_empty_record_p): New static inline function.
* var-tracking.c (prepare_call_arguments): Replace
targetm.calls.function_arg and targetm.calls.function_arg_advance
with function_arg and function_arg_advance.
* config/i386/i386.c (ix86_gimplify_va_arg): Use 0 for empty
record size.
(TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P): New hook to return true.
* doc/tm.texi.in (TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P): New
hook.
* doc/tm.texi: Regenerated.
gcc/c
PR c++/60336
PR middle-end/67239
PR target/68355
* c-aux-info.c (gen_type): Add TYPE_EMPTY_RECORD check.
gcc/cp/
PR c++/60336
PR middle-end/67239
PR target/68355
* class.c (is_empty_collection): New function.
(is_empty_record): Likewise.
(finish_struct_1): Set TYPE_EMPTY_RECORD with return value from
is_empty_record () if the ABI level is at least 10.
gcc/lto/
PR c++/60336
PR middle-end/67239
PR target/68355
* lto.c (compare_tree_sccs_1): Call compare_values with
TYPE_EMPTY_RECORD for types.
gcc/testsuite/
PR c++/60336
PR middle-end/67239
PR target/68355
* g++.dg/abi/empty12.C: New test.
* g++.dg/abi/empty12.h: Likewise.
* g++.dg/abi/empty12a.c: Likewise.
* g++.dg/abi/empty13.C: Likewise.
* g++.dg/abi/empty13.h: Likewise.
* g++.dg/abi/empty13a.c: Likewise.
* g++.dg/abi/empty14.C: Likewise.
* g++.dg/abi/empty14.h: Likewise.
* g++.dg/abi/empty14a.c: Likewise.
* g++.dg/abi/empty15.C: Likewise.
* g++.dg/abi/empty15.h: Likewise.
* g++.dg/abi/empty15a.c: Likewise.
* g++.dg/abi/empty16.C: Likewise.
* g++.dg/abi/empty16.h: Likewise.
* g++.dg/abi/empty16a.c: Likewise.
* g++.dg/abi/empty17.C: Likewise.
* g++.dg/abi/empty17.h: Likewise.
* g++.dg/abi/empty17a.c: Likewise.
* g++.dg/pr60336-1.C: Likewise.
* g++.dg/pr60336-2.C: Likewise.
* g++.dg/pr60336-3.C: Likewise.
* g++.dg/pr60336-4.C: Likewise.
* g++.dg/pr60336-5.C: Likewise.
* g++.dg/pr60336-6.C: Likewise.
* g++.dg/pr60336-7.C: Likewise.
* g++.dg/pr60336-8.C: Likewise.
* g++.dg/pr60336-9.C: Likewise.
* g++.dg/pr60336-10.C: Likewise.
* g++.dg/pr60336-11.C: Likewise.
* g++.dg/pr60336-12.C: Likewise.
* g++.dg/pr68355.C: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.c | 3 | ||||
-rw-r--r-- | gcc/cp/class.c | 3 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 6 | ||||
-rw-r--r-- | gcc/doc/tm.texi.in | 2 | ||||
-rw-r--r-- | gcc/target.def | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty12.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty13.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty14.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty15.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty16.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty17.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-10.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-11.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-12.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-3.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-6.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-7.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-8.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr60336-9.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr68355.C | 2 |
23 files changed, 42 insertions, 18 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 2a9cda619ae..4d4150f7c10 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -54598,6 +54598,9 @@ ix86_addr_space_zero_address_valid (addr_space_t as) #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE ix86_promote_function_mode +#undef TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P +#define TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P hook_bool_void_true + #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE ix86_override_options_after_change diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f34b1ef647f..b674208ef8f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6885,6 +6885,9 @@ is_empty_type (tree type) static bool is_really_empty_type (tree type) { + if (!targetm.cxx.function_skip_empty_class_p ()) + return false; + if (type == error_mark_node) return false; diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 8b3bccda967..32639565bc5 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10238,6 +10238,12 @@ modified value and perform any other actions necessary to support the backend's targeted operating system. @end deftypefn +@deftypefn {Target Hook} bool TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P (void) +This hook should return true if no memory slot nor register should be +used to pass or return an object of empty C++ class. The default is to +return @code{false}. +@end deftypefn + @deftypefn {Target Hook} bool TARGET_CXX_CDTOR_RETURNS_THIS (void) This hook should return @code{true} if constructors and destructors return the address of the object created/destroyed. The default is to return diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f31c763991c..8d82175c7b7 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7392,6 +7392,8 @@ floating-point support; they are not included in this mechanism. @hook TARGET_CXX_IMPORT_EXPORT_CLASS +@hook TARGET_CXX_FUNCTION_SKIP_EMPTY_CLASS_P + @hook TARGET_CXX_CDTOR_RETURNS_THIS @hook TARGET_CXX_KEY_METHOD_MAY_BE_INLINE diff --git a/gcc/target.def b/gcc/target.def index 5c8e4e16cc1..9e21696f791 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5393,6 +5393,16 @@ modified value and perform any other actions necessary to support the\n\ backend's targeted operating system.", int, (tree type, int import_export), NULL) +/* Returns true if no memory slot nor register should be used to pass + or return an object of empty C++ class. */ +DEFHOOK +(function_skip_empty_class_p, + "This hook should return true if no memory slot nor register should be\n\ +used to pass or return an object of empty C++ class. The default is to\n\ +return @code{false}.", + bool, (void), + hook_bool_void_false) + /* Returns true if constructors and destructors return "this". */ DEFHOOK (cdtor_returns_this, diff --git a/gcc/testsuite/g++.dg/abi/empty12.C b/gcc/testsuite/g++.dg/abi/empty12.C index db2fd24f6db..c2e4dc7461c 100644 --- a/gcc/testsuite/g++.dg/abi/empty12.C +++ b/gcc/testsuite/g++.dg/abi/empty12.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c" } // { dg-additional-sources "empty12a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/abi/empty13.C b/gcc/testsuite/g++.dg/abi/empty13.C index d1e094685de..d2e297edbb2 100644 --- a/gcc/testsuite/g++.dg/abi/empty13.C +++ b/gcc/testsuite/g++.dg/abi/empty13.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c -fabi-version=9" } // { dg-additional-sources "empty13a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/abi/empty14.C b/gcc/testsuite/g++.dg/abi/empty14.C index d32eed77d66..48ee1f845e6 100644 --- a/gcc/testsuite/g++.dg/abi/empty14.C +++ b/gcc/testsuite/g++.dg/abi/empty14.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c" } // { dg-additional-sources "empty14a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/abi/empty15.C b/gcc/testsuite/g++.dg/abi/empty15.C index 507a0cd2345..7bb6055ef7c 100644 --- a/gcc/testsuite/g++.dg/abi/empty15.C +++ b/gcc/testsuite/g++.dg/abi/empty15.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c" } // { dg-additional-sources "empty15a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/abi/empty16.C b/gcc/testsuite/g++.dg/abi/empty16.C index 42705137475..a4e7870e14b 100644 --- a/gcc/testsuite/g++.dg/abi/empty16.C +++ b/gcc/testsuite/g++.dg/abi/empty16.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c" } // { dg-additional-sources "empty16a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/abi/empty17.C b/gcc/testsuite/g++.dg/abi/empty17.C index 472708365ac..bfcd7c915cd 100644 --- a/gcc/testsuite/g++.dg/abi/empty17.C +++ b/gcc/testsuite/g++.dg/abi/empty17.C @@ -1,5 +1,5 @@ // PR c++/60336 -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-x c" } // { dg-additional-sources "empty17a.c" } // { dg-prune-output "command line option" } diff --git a/gcc/testsuite/g++.dg/pr60336-1.C b/gcc/testsuite/g++.dg/pr60336-1.C index af0863887a0..946f8accda2 100644 --- a/gcc/testsuite/g++.dg/pr60336-1.C +++ b/gcc/testsuite/g++.dg/pr60336-1.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } diff --git a/gcc/testsuite/g++.dg/pr60336-10.C b/gcc/testsuite/g++.dg/pr60336-10.C index 6c9c990dad6..57707fca749 100644 --- a/gcc/testsuite/g++.dg/pr60336-10.C +++ b/gcc/testsuite/g++.dg/pr60336-10.C @@ -1,4 +1,4 @@ -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } #include <stdarg.h> diff --git a/gcc/testsuite/g++.dg/pr60336-11.C b/gcc/testsuite/g++.dg/pr60336-11.C index c92f3d43a5b..32000b2ebe5 100644 --- a/gcc/testsuite/g++.dg/pr60336-11.C +++ b/gcc/testsuite/g++.dg/pr60336-11.C @@ -1,4 +1,4 @@ -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } #include <stdarg.h> diff --git a/gcc/testsuite/g++.dg/pr60336-12.C b/gcc/testsuite/g++.dg/pr60336-12.C index 83a7bb0cfa0..febcc6fcf2e 100644 --- a/gcc/testsuite/g++.dg/pr60336-12.C +++ b/gcc/testsuite/g++.dg/pr60336-12.C @@ -1,4 +1,4 @@ -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } #include <stdarg.h> diff --git a/gcc/testsuite/g++.dg/pr60336-2.C b/gcc/testsuite/g++.dg/pr60336-2.C index 386c82a68c4..8ec5bae7d77 100644 --- a/gcc/testsuite/g++.dg/pr60336-2.C +++ b/gcc/testsuite/g++.dg/pr60336-2.C @@ -1,4 +1,4 @@ -// { dg-do run } +// { dg-do run { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } #include <stdarg.h> diff --git a/gcc/testsuite/g++.dg/pr60336-3.C b/gcc/testsuite/g++.dg/pr60336-3.C index 3afdc8d81ca..d39d84c96d7 100644 --- a/gcc/testsuite/g++.dg/pr60336-3.C +++ b/gcc/testsuite/g++.dg/pr60336-3.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } struct dummy { struct{}__attribute__((aligned (4))) a[7]; }; diff --git a/gcc/testsuite/g++.dg/pr60336-5.C b/gcc/testsuite/g++.dg/pr60336-5.C index b0c76ad5aa2..a051f6e6105 100644 --- a/gcc/testsuite/g++.dg/pr60336-5.C +++ b/gcc/testsuite/g++.dg/pr60336-5.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } diff --git a/gcc/testsuite/g++.dg/pr60336-6.C b/gcc/testsuite/g++.dg/pr60336-6.C index 58796519334..22728d364fd 100644 --- a/gcc/testsuite/g++.dg/pr60336-6.C +++ b/gcc/testsuite/g++.dg/pr60336-6.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } diff --git a/gcc/testsuite/g++.dg/pr60336-7.C b/gcc/testsuite/g++.dg/pr60336-7.C index 0e5d2ef2f11..5fc8320c7de 100644 --- a/gcc/testsuite/g++.dg/pr60336-7.C +++ b/gcc/testsuite/g++.dg/pr60336-7.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } diff --git a/gcc/testsuite/g++.dg/pr60336-8.C b/gcc/testsuite/g++.dg/pr60336-8.C index e4487cf8f25..7b02039ef48 100644 --- a/gcc/testsuite/g++.dg/pr60336-8.C +++ b/gcc/testsuite/g++.dg/pr60336-8.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2" } struct dummy { struct{} a[7][3]; }; diff --git a/gcc/testsuite/g++.dg/pr60336-9.C b/gcc/testsuite/g++.dg/pr60336-9.C index 4ad333f6b9c..3d768c06f14 100644 --- a/gcc/testsuite/g++.dg/pr60336-9.C +++ b/gcc/testsuite/g++.dg/pr60336-9.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } diff --git a/gcc/testsuite/g++.dg/pr68355.C b/gcc/testsuite/g++.dg/pr68355.C index 1354fc497b5..5c2f0da3fd3 100644 --- a/gcc/testsuite/g++.dg/pr68355.C +++ b/gcc/testsuite/g++.dg/pr68355.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target i?86-*-* x86_64-*-* } } // { dg-options "-O2 -std=c++11 -fno-pic" } // { dg-require-effective-target fpic } |