Patchwork [C++] Avoid decay_conversion on inline asm "m" inputs (PR c++/55619)

login
register
mail settings
Submitter Jakub Jelinek
Date Dec. 11, 2012, 8:16 a.m.
Message ID <20121211081642.GL2315@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/205136/
State New
Headers show

Comments

Jakub Jelinek - Dec. 11, 2012, 8:16 a.m.
Hi!

As the testcase shows, for "m" or similar constraints that don't accept
registers, but do accept memory, we want to call *mark_addressable on the
operand, but the call to decay_conversion can change something that was
originally addressable into something non-addressable (be it replacement
of a const var with its initializer, or e.g. when the argument is an array).

The following patch fixes that, bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?  The C FE might need some change too (const vars
aren't an issue, but array conversions are).

2012-12-11  Jakub Jelinek  <jakub@redhat.com>

	PR c++/55619
	* semantics.c (finish_asm_stmt): Don't call decay_conversion
	on input operands that can be only in memory.

	* g++.dg/ext/asm12.C: New test.


	Jakub
Jason Merrill - Dec. 11, 2012, 4:19 p.m.
On 12/11/2012 03:16 AM, Jakub Jelinek wrote:
> +	  if (constraint_parsed && !allows_reg && allows_mem)
> +	    operand = mark_rvalue_use (TREE_VALUE (t));

This should be mark_lvalue_use, since we're using its address rather 
than its value.  OK with that change.

Jason
Jakub Jelinek - Dec. 11, 2012, 4:33 p.m.
On Tue, Dec 11, 2012 at 11:19:48AM -0500, Jason Merrill wrote:
> On 12/11/2012 03:16 AM, Jakub Jelinek wrote:
> >+	  if (constraint_parsed && !allows_reg && allows_mem)
> >+	    operand = mark_rvalue_use (TREE_VALUE (t));
> 
> This should be mark_lvalue_use, since we're using its address rather
> than its value.  OK with that change.

I guess it depends on how would make_lvalue_use differ from make_rvalue_use
in the future.  To some extent it is lvalue-ish use, but not completely,
while it is taking its address, it is fine if the operand is e.g. const,
which is wrong for lvalues.  I'll change it, it can be adjusted when
some difference between the two is actually added.

	Jakub
Jason Merrill - Dec. 11, 2012, 4:41 p.m.
On 12/11/2012 11:33 AM, Jakub Jelinek wrote:
> I guess it depends on how would make_lvalue_use differ from make_rvalue_use
> in the future.  To some extent it is lvalue-ish use, but not completely,
> while it is taking its address, it is fine if the operand is e.g. const,
> which is wrong for lvalues.

In C++ lvalues can be const.

Jason

Patch

--- gcc/cp/semantics.c.jj	2012-12-10 08:42:39.000000000 +0100
+++ gcc/cp/semantics.c	2012-12-10 15:24:20.666231490 +0100
@@ -1369,7 +1369,15 @@  finish_asm_stmt (int volatile_p, tree st
       for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t))
 	{
 	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
-	  operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error);
+	  bool constraint_parsed
+	    = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,   
+				      oconstraints, &allows_mem, &allows_reg);
+	  /* If the operand is going to end up in memory, don't call
+	     decay_conversion.  */
+	  if (constraint_parsed && !allows_reg && allows_mem)
+	    operand = mark_rvalue_use (TREE_VALUE (t));
+	  else
+	    operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error);
 
 	  /* If the type of the operand hasn't been determined (e.g.,
 	     because it involves an overloaded function), then issue
@@ -1382,8 +1390,7 @@  finish_asm_stmt (int volatile_p, tree st
 	      operand = error_mark_node;
 	    }
 
-	  if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
-				      oconstraints, &allows_mem, &allows_reg))
+	  if (constraint_parsed)
 	    {
 	      /* If the operand is going to end up in memory,
 		 mark it addressable.  */
--- gcc/testsuite/g++.dg/ext/asm12.C.jj	2012-12-10 15:28:26.313827902 +0100
+++ gcc/testsuite/g++.dg/ext/asm12.C	2012-12-10 15:28:03.000000000 +0100
@@ -0,0 +1,14 @@ 
+// PR c++/55619
+// { dg-do compile }
+
+typedef int V __attribute__ ((vector_size (4 * sizeof (int))));
+
+static const V C = { 0x201, 0, 0, 0 };
+static const int D = 0x201;
+
+void
+f ()
+{
+  __asm volatile ("" : : "m" (C));
+  __asm volatile ("" : : "m" (D));
+}