diff mbox series

tree-inline: Fix up __builtin_va_arg_pack handling [PR100898]

Message ID 20210606174444.GE7746@tucnak
State New
Headers show
Series tree-inline: Fix up __builtin_va_arg_pack handling [PR100898] | expand

Commit Message

Jakub Jelinek June 6, 2021, 5:44 p.m. UTC
Hi!

The following testcase ICEs, because gimple_call_arg_ptr (..., 0)
asserts that there is at least one argument, while we were using
it even if we didn't copy anything just to get a pointer from/to which
the zero arguments should be copied.

Fixed by guarding the memcpy calls.  Also, the code was calling
gimple_call_num_args too many times - 5 times instead of 2, so the patch
adds two temporaries for those.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-06-06  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/100898
	* tree-inline.c (copy_bb): Only use gimple_call_arg_ptr if memcpy
	should copy any arguments.  Don't call gimple_call_num_args
	on id->call_stmt or call_stmt more than once.

	* g++.dg/ext/va-arg-pack-3.C: New test.


	Jakub

Comments

Richard Biener June 7, 2021, 6:16 a.m. UTC | #1
On Sun, 6 Jun 2021, Jakub Jelinek wrote:

> Hi!
> 
> The following testcase ICEs, because gimple_call_arg_ptr (..., 0)
> asserts that there is at least one argument, while we were using
> it even if we didn't copy anything just to get a pointer from/to which
> the zero arguments should be copied.
> 
> Fixed by guarding the memcpy calls.  Also, the code was calling
> gimple_call_num_args too many times - 5 times instead of 2, so the patch
> adds two temporaries for those.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2021-06-06  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR middle-end/100898
> 	* tree-inline.c (copy_bb): Only use gimple_call_arg_ptr if memcpy
> 	should copy any arguments.  Don't call gimple_call_num_args
> 	on id->call_stmt or call_stmt more than once.
> 
> 	* g++.dg/ext/va-arg-pack-3.C: New test.
> 
> --- gcc/tree-inline.c.jj	2021-06-04 11:15:26.000000000 +0200
> +++ gcc/tree-inline.c	2021-06-04 15:15:07.358413674 +0200
> @@ -2090,27 +2090,29 @@ copy_bb (copy_body_data *id, basic_block
>  	      tree p;
>  	      gcall *new_call;
>  	      vec<tree> argarray;
> -	      size_t nargs = gimple_call_num_args (id->call_stmt);
> -	      size_t n;
> +	      size_t nargs_caller = gimple_call_num_args (id->call_stmt);
> +	      size_t nargs = nargs_caller;
>  
>  	      for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
>  		nargs--;
>  
>  	      /* Create the new array of arguments.  */
> -	      n = nargs + gimple_call_num_args (call_stmt);
> +	      size_t nargs_callee = gimple_call_num_args (call_stmt);
> +	      size_t n = nargs + nargs_callee;
>  	      argarray.create (n);
>  	      argarray.safe_grow_cleared (n, true);
>  
>  	      /* Copy all the arguments before '...'  */
> -	      memcpy (argarray.address (),
> -		      gimple_call_arg_ptr (call_stmt, 0),
> -		      gimple_call_num_args (call_stmt) * sizeof (tree));
> +	      if (nargs_callee)
> +		memcpy (argarray.address (),
> +			gimple_call_arg_ptr (call_stmt, 0),
> +			nargs_callee * sizeof (tree));
>  
>  	      /* Append the arguments passed in '...'  */
> -	      memcpy (argarray.address () + gimple_call_num_args (call_stmt),
> -		      gimple_call_arg_ptr (id->call_stmt, 0)
> -		      + (gimple_call_num_args (id->call_stmt) - nargs),
> -		      nargs * sizeof (tree));
> +	      if (nargs)
> +		memcpy (argarray.address () + nargs_callee,
> +			gimple_call_arg_ptr (id->call_stmt, 0)
> +			+ (nargs_caller - nargs), nargs * sizeof (tree));
>  
>  	      new_call = gimple_build_call_vec (gimple_call_fn (call_stmt),
>  						argarray);
> --- gcc/testsuite/g++.dg/ext/va-arg-pack-3.C.jj	2021-06-04 15:32:28.213079130 +0200
> +++ gcc/testsuite/g++.dg/ext/va-arg-pack-3.C	2021-06-04 15:31:29.777883575 +0200
> @@ -0,0 +1,18 @@
> +// PR middle-end/100898
> +
> +int a;
> +int bar (int, ...);
> +
> +static inline __attribute__((always_inline)) int
> +foo (...)
> +{
> +  while (a)
> +    return bar (0, __builtin_va_arg_pack ());
> +  return 0;
> +}
> +
> +void
> +baz (void)
> +{
> +  foo ();
> +}
> 
> 	Jakub
> 
>
diff mbox series

Patch

--- gcc/tree-inline.c.jj	2021-06-04 11:15:26.000000000 +0200
+++ gcc/tree-inline.c	2021-06-04 15:15:07.358413674 +0200
@@ -2090,27 +2090,29 @@  copy_bb (copy_body_data *id, basic_block
 	      tree p;
 	      gcall *new_call;
 	      vec<tree> argarray;
-	      size_t nargs = gimple_call_num_args (id->call_stmt);
-	      size_t n;
+	      size_t nargs_caller = gimple_call_num_args (id->call_stmt);
+	      size_t nargs = nargs_caller;
 
 	      for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
 		nargs--;
 
 	      /* Create the new array of arguments.  */
-	      n = nargs + gimple_call_num_args (call_stmt);
+	      size_t nargs_callee = gimple_call_num_args (call_stmt);
+	      size_t n = nargs + nargs_callee;
 	      argarray.create (n);
 	      argarray.safe_grow_cleared (n, true);
 
 	      /* Copy all the arguments before '...'  */
-	      memcpy (argarray.address (),
-		      gimple_call_arg_ptr (call_stmt, 0),
-		      gimple_call_num_args (call_stmt) * sizeof (tree));
+	      if (nargs_callee)
+		memcpy (argarray.address (),
+			gimple_call_arg_ptr (call_stmt, 0),
+			nargs_callee * sizeof (tree));
 
 	      /* Append the arguments passed in '...'  */
-	      memcpy (argarray.address () + gimple_call_num_args (call_stmt),
-		      gimple_call_arg_ptr (id->call_stmt, 0)
-		      + (gimple_call_num_args (id->call_stmt) - nargs),
-		      nargs * sizeof (tree));
+	      if (nargs)
+		memcpy (argarray.address () + nargs_callee,
+			gimple_call_arg_ptr (id->call_stmt, 0)
+			+ (nargs_caller - nargs), nargs * sizeof (tree));
 
 	      new_call = gimple_build_call_vec (gimple_call_fn (call_stmt),
 						argarray);
--- gcc/testsuite/g++.dg/ext/va-arg-pack-3.C.jj	2021-06-04 15:32:28.213079130 +0200
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-3.C	2021-06-04 15:31:29.777883575 +0200
@@ -0,0 +1,18 @@ 
+// PR middle-end/100898
+
+int a;
+int bar (int, ...);
+
+static inline __attribute__((always_inline)) int
+foo (...)
+{
+  while (a)
+    return bar (0, __builtin_va_arg_pack ());
+  return 0;
+}
+
+void
+baz (void)
+{
+  foo ();
+}