From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2140) id 4170A397B837; Wed, 4 Aug 2021 12:46:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4170A397B837 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alexandre Oliva To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/aoliva/heads/strub)] strub type checking X-Act-Checkin: gcc X-Git-Author: Alexandre Oliva X-Git-Refname: refs/users/aoliva/heads/strub X-Git-Oldrev: 5e4f646737086ddf6bdae3810b3595c2e8f95a42 X-Git-Newrev: 0f88209aa4540dba4b31b7926f0b098685ac8aae Message-Id: <20210804124626.4170A397B837@sourceware.org> Date: Wed, 4 Aug 2021 12:46:26 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Aug 2021 12:46:26 -0000 https://gcc.gnu.org/g:0f88209aa4540dba4b31b7926f0b098685ac8aae commit 0f88209aa4540dba4b31b7926f0b098685ac8aae Author: Alexandre Oliva Date: Wed Aug 4 09:45:32 2021 -0300 strub type checking Diff: --- gcc/ipa-strub.c | 65 ++--- gcc/testsuite/c-c++-common/strub-O2.c | 2 +- gcc/testsuite/c-c++-common/strub-O2fni.c | 6 +- gcc/testsuite/c-c++-common/strub-O3fni.c | 4 +- gcc/testsuite/c-c++-common/strub-Og.c | 2 +- gcc/testsuite/c-c++-common/strub-Os.c | 2 +- gcc/testsuite/c-c++-common/strub-all1.c | 4 +- gcc/testsuite/c-c++-common/strub-at-calls1.c | 4 +- gcc/testsuite/c-c++-common/strub-default1.c | 4 +- gcc/testsuite/c-c++-common/strub-internal1.c | 4 +- .../c-c++-common/torture/strub-callable1.c | 13 + .../c-c++-common/torture/strub-callable2.c | 264 +++++++++++++++++++++ gcc/testsuite/c-c++-common/torture/strub-const1.c | 18 ++ gcc/testsuite/c-c++-common/torture/strub-const2.c | 22 ++ gcc/testsuite/c-c++-common/torture/strub-const3.c | 13 + gcc/testsuite/c-c++-common/torture/strub-const4.c | 17 ++ gcc/testsuite/c-c++-common/torture/strub-data5.c | 4 +- gcc/testsuite/c-c++-common/torture/strub-pure1.c | 18 ++ gcc/testsuite/c-c++-common/torture/strub-pure2.c | 22 ++ gcc/testsuite/c-c++-common/torture/strub-pure3.c | 13 + gcc/testsuite/c-c++-common/torture/strub-pure4.c | 17 ++ 21 files changed, 473 insertions(+), 45 deletions(-) diff --git a/gcc/ipa-strub.c b/gcc/ipa-strub.c index e302f0ec1c5..41ff473411a 100644 --- a/gcc/ipa-strub.c +++ b/gcc/ipa-strub.c @@ -263,7 +263,7 @@ calls_builtin_apply_args_p (cgraph_node *node, bool report = false) break; sorry_at (gimple_location (e->call_stmt), - "at-calls strub does not support call to %qD", + "at-calls % does not support call to %qD", cdecl); } @@ -292,7 +292,8 @@ can_strub_p (cgraph_node *node, bool report = false) return result; sorry_at (DECL_SOURCE_LOCATION (node->decl), - "%qD is not eligible for strub because of attribute %", + "%qD is not eligible for %" + " because of attribute %", node->decl); } @@ -352,7 +353,7 @@ can_strub_internally_p (cgraph_node *node, bool report = false) return result; sorry_at (DECL_SOURCE_LOCATION (node->decl), - "%qD is not eligible for internal strub" + "%qD is not eligible for internal %" " because of attribute %", node->decl); } @@ -372,7 +373,7 @@ can_strub_internally_p (cgraph_node *node, bool report = false) return result; sorry_at (gimple_location (e->call_stmt), - "internal strub does not support call to %qD", + "internal % does not support call to %qD", cdecl); } @@ -411,7 +412,7 @@ can_strub_internally_p (cgraph_node *node, bool report = false) return result; sorry_at (gimple_location (label_stmt), - "internal strub does not support user labels"); + "internal % does not support user labels"); } } @@ -425,16 +426,16 @@ can_strub_internally_p (cgraph_node *node, bool report = false) return result; sorry_at (DECL_SOURCE_LOCATION (node->decl), - "%qD has too many arguments for internal strub", + "%qD has too many arguments for internal %", node->decl); } - if (result) - /* Since we're not changing the function identity proper, just - moving its full implementation, we *could* disable - fun->cannot_be_copied_reason and/or temporarily drop a noclone - attribute. */ - gcc_checking_assert (tree_versionable_function_p (node->decl)); + /* Since we're not changing the function identity proper, just + moving its full implementation, we *could* disable + fun->cannot_be_copied_reason and/or temporarily drop a noclone + attribute. */ + gcc_checking_assert (!result || !node->has_gimple_body_p () + || tree_versionable_function_p (node->decl)); return result; } @@ -698,7 +699,8 @@ compute_strub_mode (cgraph_node *node, tree strub_attr) { gcc_checking_assert (analyze_body); error_at (DECL_SOURCE_LOCATION (node->decl), - "%qD requires strub, but no viable strub mode was found", + "%qD requires %," + " but no viable % mode was found", node->decl); break; } @@ -751,7 +753,7 @@ set_strub_mode_to (cgraph_node *node, enum strub_mode mode) && mode == STRUB_INLINABLE)) { error_at (DECL_SOURCE_LOCATION (node->decl), - "strub mode %i selected for %qD, when %i was requested", + "% mode %i selected for %qD, when %i was requested", (int) mode, node->decl, (int) get_strub_mode_from_attr (attr)); if (node->alias) @@ -979,7 +981,7 @@ verify_strub () if (callee_mode == STRUB_DISABLED || callee_mode == STRUB_INTERNAL) error_at (gimple_location (e->call_stmt), - "indirect non-strub call in strub context %qD", + "indirect non-% call in % context %qD", node->decl); } @@ -987,9 +989,17 @@ verify_strub () { gcc_checking_assert (!e->indirect_unknown_callee); if (!strub_callable_from_p (e->callee, node)) - error_at (gimple_location (e->call_stmt), - "calling non-strub %qD in strub context %qD", - e->callee->decl, node->decl); + { + if (get_strub_mode (e->callee) != STRUB_INLINABLE) + error_at (gimple_location (e->call_stmt), + "calling non-% %qD in % context %qD", + e->callee->decl, node->decl); + else + error_at (gimple_location (e->call_stmt), + "calling % % %qD" + " in non-% context %qD", + e->callee->decl, node->decl); + } } } @@ -1067,7 +1077,7 @@ public: /* Use a distinct ptr_type_node to denote the watermark, so that we can recognize it in arg lists and avoid modifying types twice. */ - DEF_TYPE (wmt, build_distinct_type_copy (ptr_type_node)) + DEF_TYPE (wmt, build_variant_type_copy (ptr_type_node)) DEF_TYPE (pwmt, build_pointer_type (get_wmt ())) @@ -1507,7 +1517,7 @@ pass_ipa_strub::adjust_at_calls_type (tree type) tree qpwmptrt = get_qpwmt (); while (*tlist && TREE_VALUE (*tlist) != void_type_node) { - /* The type has alreayd been adjusted. */ + /* The type has already been adjusted. */ if (TREE_VALUE (*tlist) == qpwmptrt) return named_args; named_args++; @@ -1909,7 +1919,7 @@ pass_ipa_strub::execute (function *) if (!DECL_STRUCT_FUNCTION (onode->decl)) { inform (DECL_SOURCE_LOCATION (onode->decl), - "not splitting struct-less function %qD for stack scrubbing", + "not splitting struct-less function %qD for %", onode->decl); continue; } @@ -1917,7 +1927,7 @@ pass_ipa_strub::execute (function *) if (!onode->lowered) { inform (DECL_SOURCE_LOCATION (onode->decl), - "not splitting non-lowered function %qD for stack scrubbing", + "not splitting non-lowered function %qD for %", onode->decl); continue; } @@ -1929,7 +1939,7 @@ pass_ipa_strub::execute (function *) if (!tree_versionable_function_p (onode->decl)) { inform (DECL_SOURCE_LOCATION (onode->decl), - "%qD cannot be split for stack scrubbing", + "%qD cannot be split for %", onode->decl); continue; } @@ -1982,7 +1992,7 @@ pass_ipa_strub::execute (function *) if (!nnode) { error_at (DECL_SOURCE_LOCATION (onode->decl), - "failed to split %qD for stack scrubbing", + "failed to split %qD for %", onode->decl); continue; } @@ -2582,9 +2592,10 @@ pass_ipa_strub::execute (function *) else if (fndecl && is_stdarg && fndecl_built_in_p (fndecl, BUILT_IN_VA_START)) { - if (builtin_decl_explicit (BUILT_IN_VA_START) != fndecl) - sorry_at (gimple_location (call), - "nonstandard stdarg conventions"); + /* Using a non-default stdarg ABI makes the function ineligible + for internal strub. */ + gcc_checking_assert (builtin_decl_explicit (BUILT_IN_VA_START) + == fndecl); tree bvacopy = builtin_decl_explicit (BUILT_IN_VA_COPY); gimple_call_set_fndecl (call, bvacopy); tree arg = vaptr; diff --git a/gcc/testsuite/c-c++-common/strub-O2.c b/gcc/testsuite/c-c++-common/strub-O2.c index 9cc39e763b1..7848c46d179 100644 --- a/gcc/testsuite/c-c++-common/strub-O2.c +++ b/gcc/testsuite/c-c++-common/strub-O2.c @@ -13,4 +13,4 @@ int f() { /* { dg-final { scan-rtl-dump-not "strub_enter" "expand" } } */ /* { dg-final { scan-rtl-dump-not "strub_update" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_leave" "expand" } } */ -/* { dg-final { scan-rtl-dump "\n\[(\]call_insn\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ +/* { dg-final { scan-rtl-dump "\[(\]call\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ diff --git a/gcc/testsuite/c-c++-common/strub-O2fni.c b/gcc/testsuite/c-c++-common/strub-O2fni.c index 51cae845d5f..85a8f76785e 100644 --- a/gcc/testsuite/c-c++-common/strub-O2fni.c +++ b/gcc/testsuite/c-c++-common/strub-O2fni.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fstrub=default -fdump-rtl-expand -fno-inline-functions" } */ +/* { dg-options "-O2 -fstrub=default -fdump-rtl-expand -fno-inline" } */ -/* With -fno-inline-functions, none of the strub builtins are inlined. */ +/* With -fno-inline, none of the strub builtins are inlined. */ int __attribute__ ((__strub__)) var; @@ -12,4 +12,4 @@ int f() { /* { dg-final { scan-rtl-dump "strub_enter" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_update" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_leave" "expand" } } */ -/* { dg-final { scan-rtl-dump-not "\n\[(\]call_insn\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "\[(\]call\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ diff --git a/gcc/testsuite/c-c++-common/strub-O3fni.c b/gcc/testsuite/c-c++-common/strub-O3fni.c index 8f67b613be8..a2eedfd96b2 100644 --- a/gcc/testsuite/c-c++-common/strub-O3fni.c +++ b/gcc/testsuite/c-c++-common/strub-O3fni.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-O3 -fstrub=default -fdump-rtl-expand -fno-inline" } */ -/* With -fno-inline-functions, none of the strub builtins are inlined. */ +/* With -fno-inline, none of the strub builtins are inlined. */ int __attribute__ ((__strub__)) var; @@ -12,4 +12,4 @@ int f() { /* { dg-final { scan-rtl-dump "strub_enter" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_update" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_leave" "expand" } } */ -/* { dg-final { scan-rtl-dump-not "\n\[(\]call_insn\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "\[(\]call\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ diff --git a/gcc/testsuite/c-c++-common/strub-Og.c b/gcc/testsuite/c-c++-common/strub-Og.c index 6f60349573f..e5cb1f60541 100644 --- a/gcc/testsuite/c-c++-common/strub-Og.c +++ b/gcc/testsuite/c-c++-common/strub-Og.c @@ -13,4 +13,4 @@ int f() { /* { dg-final { scan-rtl-dump-not "strub_enter" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_update" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_leave" "expand" } } */ -/* { dg-final { scan-rtl-dump-not "\n\[(\]call_insn\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "\[(\]call\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ diff --git a/gcc/testsuite/c-c++-common/strub-Os.c b/gcc/testsuite/c-c++-common/strub-Os.c index 5d1c08a7528..194aacc2c05 100644 --- a/gcc/testsuite/c-c++-common/strub-Os.c +++ b/gcc/testsuite/c-c++-common/strub-Os.c @@ -15,4 +15,4 @@ int f() { /* { dg-final { scan-rtl-dump-not "strub_enter" "expand" } } */ /* { dg-final { scan-rtl-dump-not "strub_update" "expand" } } */ /* { dg-final { scan-rtl-dump "strub_leave" "expand" } } */ -/* { dg-final { scan-rtl-dump-not "\n\[(\]call_insn\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "\[(\]call\[^\n\]*strub_leave.*\n\[(\]code_label" "expand" } } */ diff --git a/gcc/testsuite/c-c++-common/strub-all1.c b/gcc/testsuite/c-c++-common/strub-all1.c index 54daf84656c..46e84bf6560 100644 --- a/gcc/testsuite/c-c++-common/strub-all1.c +++ b/gcc/testsuite/c-c++-common/strub-all1.c @@ -3,9 +3,9 @@ /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub. */ -static void +static inline void __attribute__ ((__always_inline__)) -h() { /* { dg-warning "might not be inlinable" } */ +h() { } /* g becomes STRUB_AT_CALLS, because of the flag. */ diff --git a/gcc/testsuite/c-c++-common/strub-at-calls1.c b/gcc/testsuite/c-c++-common/strub-at-calls1.c index 0d1b9fce833..d964b07ae5d 100644 --- a/gcc/testsuite/c-c++-common/strub-at-calls1.c +++ b/gcc/testsuite/c-c++-common/strub-at-calls1.c @@ -3,9 +3,9 @@ /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub. */ -static void +static inline void __attribute__ ((__always_inline__)) -h() { /* { dg-warning "might not be inlinable" } */ +h() { } /* g becomes STRUB_AT_CALLS, because of the flag. */ diff --git a/gcc/testsuite/c-c++-common/strub-default1.c b/gcc/testsuite/c-c++-common/strub-default1.c index a1e1803aadc..2dfdb948e7b 100644 --- a/gcc/testsuite/c-c++-common/strub-default1.c +++ b/gcc/testsuite/c-c++-common/strub-default1.c @@ -6,9 +6,9 @@ static int __attribute__ ((__strub__)) var; /* h becomes STRUB_STRUB_INLINABLE, because of the use of the strub variable, and the always_inline flag. It would get inlined before pass_ipa_strub, if it weren't for the error. */ -static void +static inline void __attribute__ ((__always_inline__)) -h() { /* { dg-warning "might not be inlinable" } */ +h() { var++; } diff --git a/gcc/testsuite/c-c++-common/strub-internal1.c b/gcc/testsuite/c-c++-common/strub-internal1.c index b9bd787df0a..a74658c9ac9 100644 --- a/gcc/testsuite/c-c++-common/strub-internal1.c +++ b/gcc/testsuite/c-c++-common/strub-internal1.c @@ -3,9 +3,9 @@ /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub. */ -static void +static inline void __attribute__ ((__always_inline__)) -h() { /* { dg-warning "might not be inlinable" } */ +h() { } /* g becomes STRUB_INTERNAL because of the flag, and gets split into diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable1.c b/gcc/testsuite/c-c++-common/torture/strub-callable1.c new file mode 100644 index 00000000000..45965f275c9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-callable1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub -fno-inline" } */ + +/* Check that strub and non-strub functions can be called from non-strub + contexts, and that strub and callable functions can be called from strub + contexts. */ + +#define OMIT_IMPERMISSIBLE_CALLS 1 +#include "strub-callable2.c" + +/* { dg-final { scan-ipa-dump-times "strub_enter" 45 "strub" } } */ +/* { dg-final { scan-ipa-dump-times "strub_update" 4 "strub" } } */ +/* { dg-final { scan-ipa-dump-times "strub_leave" 45 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable2.c b/gcc/testsuite/c-c++-common/torture/strub-callable2.c new file mode 100644 index 00000000000..38935e3270b --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-callable2.c @@ -0,0 +1,264 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default" } */ + +/* Check that impermissible (cross-strub-context) calls are reported. */ + +extern int __attribute__ ((__strub__ (3))) xcallable (void); +extern int __attribute__ ((__strub__ (2))) xinternal (void); +extern int __attribute__ ((__strub__ (1))) xat_calls (void); +extern int __attribute__ ((__strub__ (0))) xdisabled (void); + +int __attribute__ ((__strub__ (3))) callable (void); +int __attribute__ ((__strub__ (2))) internal (void); +int __attribute__ ((__strub__ (1))) at_calls (void); +int __attribute__ ((__strub__ (0))) disabled (void); + +int __attribute__ ((__strub__)) var; +int var_user (void); + +static inline int __attribute__ ((__always_inline__, __strub__ (3))) +icallable (void); +static inline int __attribute__ ((__always_inline__, __strub__ (2))) +iinternal (void); +static inline int __attribute__ ((__always_inline__, __strub__ (1))) +iat_calls (void); +static inline int __attribute__ ((__always_inline__, __strub__ (0))) +idisabled (void); +static inline int __attribute__ ((__always_inline__)) +ivar_user (void); + +static inline int __attribute__ ((__always_inline__, __strub__ (3))) +i_callable (void) { return 0; } +static inline int __attribute__ ((__always_inline__, __strub__ (2))) +i_internal (void) { return var; } +static inline int __attribute__ ((__always_inline__, __strub__ (1))) +i_at_calls (void) { return var; } +static inline int __attribute__ ((__always_inline__, __strub__ (0))) +i_disabled (void) { return 0; } +static inline int __attribute__ ((__always_inline__)) +i_var_user (void) { return var; } + +#define CALLS_GOOD_FOR_STRUB_CONTEXT(ISEP) \ + do { \ + ret += i ## ISEP ## at_calls (); \ + ret += i ## ISEP ## internal (); \ + ret += i ## ISEP ## var_user (); \ + } while (0) + +#define CALLS_GOOD_FOR_NONSTRUB_CONTEXT(ISEP) \ + do { \ + ret += internal (); \ + ret += disabled (); \ + ret += var_user (); \ + \ + ret += i ## ISEP ## disabled (); \ + \ + ret += xinternal (); \ + ret += xdisabled (); \ + } while (0) + +#define CALLS_GOOD_FOR_EITHER_CONTEXT(ISEP) \ + do { \ + ret += i ## ISEP ## callable (); \ + \ + ret += callable (); \ + ret += at_calls (); \ + \ + ret += xat_calls (); \ + ret += xcallable (); \ + } while (0) + +/* Not a strub context, so it can call anything. + Explicitly declared as callable even from within strub contexts. */ +int __attribute__ ((__strub__ (3))) +callable (void) { + int ret = 0; + + /* CALLS_GOOD_FOR_STRUB_CONTEXT(); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += iat_calls (); /* { dg-error "in non-.strub. context" } */ + ret += iinternal (); /* { dg-error "in non-.strub. context" } */ + ret += ivar_user (); /* { dg-error "in non-.strub. context" } */ +#endif + CALLS_GOOD_FOR_EITHER_CONTEXT(); + CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); + + return ret; +} + +/* Internal strubbing means the body is a strub context, so it can only call + strub functions, and it's not itself callable from strub functions. */ +int __attribute__ ((__strub__ (2))) +internal (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(); + CALLS_GOOD_FOR_EITHER_CONTEXT(); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += idisabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} + +int __attribute__ ((__strub__ (1))) +at_calls (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(); + CALLS_GOOD_FOR_EITHER_CONTEXT(); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += idisabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} + +int __attribute__ ((__strub__ (0))) +disabled () { + int ret = 0; + + /* CALLS_GOOD_FOR_STRUB_CONTEXT(); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += iat_calls (); /* { dg-error "in non-.strub. context" } */ + ret += iinternal (); /* { dg-error "in non-.strub. context" } */ + ret += ivar_user (); /* { dg-error "in non-.strub. context" } */ +#endif + CALLS_GOOD_FOR_EITHER_CONTEXT(); + CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); + + return ret; +} + +int +var_user (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(); + CALLS_GOOD_FOR_EITHER_CONTEXT(); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += idisabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} + +int +icallable (void) +{ + int ret = 0; + + /* CALLS_GOOD_FOR_STRUB_CONTEXT(_); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += i_at_calls (); /* { dg-error "in non-.strub. context" } */ + ret += i_internal (); /* { dg-error "in non-.strub. context" } */ + ret += i_var_user (); /* { dg-error "in non-.strub. context" } */ +#endif + CALLS_GOOD_FOR_EITHER_CONTEXT(_); + CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); + + return ret; +} + +int +iinternal (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(_); + CALLS_GOOD_FOR_EITHER_CONTEXT(_); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += i_disabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} + +int +iat_calls (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(_); + CALLS_GOOD_FOR_EITHER_CONTEXT(_); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += i_disabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} + +int +idisabled () { + int ret = 0; + + /* CALLS_GOOD_FOR_STRUB_CONTEXT(_); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += i_at_calls (); /* { dg-error "in non-.strub. context" } */ + ret += i_internal (); /* { dg-error "in non-.strub. context" } */ + ret += i_var_user (); /* { dg-error "in non-.strub. context" } */ +#endif + CALLS_GOOD_FOR_EITHER_CONTEXT(_); + CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); + + return ret; +} + +int +ivar_user (void) { + int ret = var; + + CALLS_GOOD_FOR_STRUB_CONTEXT(_); + CALLS_GOOD_FOR_EITHER_CONTEXT(_); + /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */ +#if !OMIT_IMPERMISSIBLE_CALLS + ret += internal (); /* { dg-error "in .strub. context" } */ + ret += disabled (); /* { dg-error "in .strub. context" } */ + ret += var_user (); /* { dg-error "in .strub. context" } */ + + ret += i_disabled (); /* { dg-error "in .strub. context" } */ + + ret += xinternal (); /* { dg-error "in .strub. context" } */ + ret += xdisabled (); /* { dg-error "in .strub. context" } */ +#endif + + return ret; +} diff --git a/gcc/testsuite/c-c++-common/torture/strub-const1.c b/gcc/testsuite/c-c++-common/torture/strub-const1.c new file mode 100644 index 00000000000..100fb0c59a9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-const1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub const function call, we issue an asm statement + to make sure the watermark passed to it is held in memory before the call, + and another to make sure it is not assumed to be unchanged. */ + +int __attribute__ ((__strub__, __const__)) +f() { + return 0; +} + +int +g() { + return f(); +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-const2.c b/gcc/testsuite/c-c++-common/torture/strub-const2.c new file mode 100644 index 00000000000..9e818ac9748 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-const2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub implicitly-const function call, we issue an + asm statement to make sure the watermark passed to it is held in memory + before the call, and another to make sure it is not assumed to be + unchanged. */ + +int __attribute__ ((__strub__)) +#if ! __OPTIMIZE__ +__attribute__ ((__const__)) +#endif +f() { + return 0; +} + +int +g() { + return f(); +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-const3.c b/gcc/testsuite/c-c++-common/torture/strub-const3.c new file mode 100644 index 00000000000..d40e8aa45cb --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-const3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub const wrapping call, we issue an asm statement + to make sure the watermark passed to it is held in memory before the call, + and another to make sure it is not assumed to be unchanged. */ + +int __attribute__ ((__strub__ (2), __const__)) +f() { + return 0; +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-const4.c b/gcc/testsuite/c-c++-common/torture/strub-const4.c new file mode 100644 index 00000000000..d4cbdaf10f3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-const4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub implicitly-const wrapping call, we issue an + asm statement to make sure the watermark passed to it is held in memory + before the call, and another to make sure it is not assumed to be + unchanged. */ + +int __attribute__ ((__strub__ (2))) +#if ! __OPTIMIZE__ +__attribute__ ((__const__)) +#endif +f() { + return 0; +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-data5.c b/gcc/testsuite/c-c++-common/torture/strub-data5.c index 251790d4bbb..e0ee6cbddda 100644 --- a/gcc/testsuite/c-c++-common/torture/strub-data5.c +++ b/gcc/testsuite/c-c++-common/torture/strub-data5.c @@ -7,9 +7,9 @@ typedef int __attribute__ ((__strub__)) strub_int; strub_int *ptr; int *f () { - return ptr; /* { dg-warn "incompatible" } */ + return ptr; /* { dg-warning "incompatible" } */ } strub_int *g () { - return f (); /* { dg-warn "incompatible" } */ + return f (); /* { dg-warning "incompatible" } */ } diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure1.c b/gcc/testsuite/c-c++-common/torture/strub-pure1.c new file mode 100644 index 00000000000..cb223da6efc --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-pure1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub pure function call, we issue an asm statement + to make sure the watermark passed to it is not assumed to be unchanged. */ + +int __attribute__ ((__strub__, __pure__)) +f() { + static int i; /* Stop it from being detected as const. */ + return i; +} + +int +g() { + return f(); +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure2.c b/gcc/testsuite/c-c++-common/torture/strub-pure2.c new file mode 100644 index 00000000000..67d1434b1f8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-pure2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub implicitly-pure function call, we issue an asm + statement to make sure the watermark passed to it is not assumed to be + unchanged. */ + +int __attribute__ ((__strub__)) +#if ! __OPTIMIZE__ /* At -O0, implicit pure detection doesn't run. */ +__attribute__ ((__pure__)) +#endif +f() { + static int i; /* Stop it from being detected as const. */ + return i; +} + +int +g() { + return f(); +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure3.c b/gcc/testsuite/c-c++-common/torture/strub-pure3.c new file mode 100644 index 00000000000..59f02ea901f --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-pure3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub pure wrapping call, we issue an asm statement + to make sure the watermark passed to it is not assumed to be unchanged. */ + +int __attribute__ ((__strub__ (2), __pure__)) +f() { + static int i; /* Stop it from being detected as const. */ + return i; +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */ diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure4.c b/gcc/testsuite/c-c++-common/torture/strub-pure4.c new file mode 100644 index 00000000000..973e909217d --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/strub-pure4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrub=default -fdump-ipa-strub" } */ + +/* Check that, along with a strub implicitly-pure wrapping call, we issue an asm + statement to make sure the watermark passed to it is not assumed to be + unchanged. */ + +int __attribute__ ((__strub__ (2))) +#if ! __OPTIMIZE__ /* At -O0, implicit pure detection doesn't run. */ +__attribute__ ((__pure__)) +#endif +f() { + static int i; /* Stop it from being detected as const. */ + return i; +} + +/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */