public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aoliva/heads/strub)] strub type checking
@ 2021-08-04  8:55 Alexandre Oliva
  0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Oliva @ 2021-08-04  8:55 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:208e30374d1133458a6a12546a8daa791c75016a

commit 208e30374d1133458a6a12546a8daa791c75016a
Author: Alexandre Oliva <oliva@gnu.org>
Date:   Wed Aug 4 05:52:43 2021 -0300

    strub type checking

Diff:


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [gcc(refs/users/aoliva/heads/strub)] strub type checking
@ 2021-08-04 12:46 Alexandre Oliva
  0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Oliva @ 2021-08-04 12:46 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0f88209aa4540dba4b31b7926f0b098685ac8aae

commit 0f88209aa4540dba4b31b7926f0b098685ac8aae
Author: Alexandre Oliva <oliva@adacore.com>
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 %<strub%> 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 %<noipa%>",
+		"%qD is not eligible for %<strub%>"
+		" because of attribute %<noipa%>",
 		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 %<strub%>"
 		" because of attribute %<noclone%>",
 		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 %<strub%> 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 %<strub%> 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 %<strub%>",
 		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 %<strub%>,"
+		    " but no viable %<strub%> 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",
+		    "%<strub%> 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-%<strub%> call in %<strub%> 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-%<strub%> %qD in %<strub%> context %qD",
+			e->callee->decl, node->decl);
+	    else
+	      error_at (gimple_location (e->call_stmt),
+			"calling %<always_inline%> %<strub%> %qD"
+			" in non-%<strub%> 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 %<strub%>",
 		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 %<strub%>",
 		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 %<strub%>",
 		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 %<strub%>",
 		  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" } } */


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [gcc(refs/users/aoliva/heads/strub)] strub type checking
@ 2021-08-04  9:04 Alexandre Oliva
  0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Oliva @ 2021-08-04  9:04 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:396d2d0536e89b78ace8ce2f806031e8dfcdcb35

commit 396d2d0536e89b78ace8ce2f806031e8dfcdcb35
Author: Alexandre Oliva <oliva@gnu.org>
Date:   Wed Aug 4 05:52:43 2021 -0300

    strub type checking

Diff:
---
 gcc/ipa-strub.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/ipa-strub.c b/gcc/ipa-strub.c
index e302f0ec1c5..81d961ac44e 100644
--- a/gcc/ipa-strub.c
+++ b/gcc/ipa-strub.c
@@ -429,12 +429,12 @@ can_strub_internally_p (cgraph_node *node, bool report = false)
 		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;
 }


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-08-04 12:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-04  8:55 [gcc(refs/users/aoliva/heads/strub)] strub type checking Alexandre Oliva
2021-08-04  9:04 Alexandre Oliva
2021-08-04 12:46 Alexandre Oliva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).