Hi!

At expansion time, we in various cases choose to assign_temp and ICE
in that case on any expressions with TREE_ADDRESSABLE types.  We don't want
to create any temporaries for such types, the var needs to live in memory
and if the constraint doesn't allow mem, we should just reject it as
invalid.

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

2018-05-06  Jakub Jelinek  <ja...@redhat.com>

        PR c++/85659
        * cfgexpand.c (expand_asm_stmt): Don't create a temporary if
        the type is addressable.  Don't force op into register if it has
        BLKmode.

        * g++.dg/ext/asm14.C: New test.
        * g++.dg/ext/asm15.C: New test.
        * g++.dg/ext/asm16.C: New test.

--- gcc/cfgexpand.c.jj  2018-03-27 12:54:43.000000000 +0200
+++ gcc/cfgexpand.c     2018-05-05 13:28:44.037551377 +0200
@@ -3044,14 +3044,14 @@ expand_asm_stmt (gasm *stmt)
 
       generating_concat_p = 0;
 
-      if ((TREE_CODE (val) == INDIRECT_REF
-          && allows_mem)
+      if ((TREE_CODE (val) == INDIRECT_REF && allows_mem)
          || (DECL_P (val)
              && (allows_mem || REG_P (DECL_RTL (val)))
              && ! (REG_P (DECL_RTL (val))
                    && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
          || ! allows_reg
-         || is_inout)
+         || is_inout
+         || TREE_ADDRESSABLE (type))
        {
          op = expand_expr (val, NULL_RTX, VOIDmode,
                            !allows_reg ? EXPAND_MEMORY : EXPAND_WRITE);
@@ -3060,7 +3060,7 @@ expand_asm_stmt (gasm *stmt)
 
          if (! allows_reg && !MEM_P (op))
            error ("output number %d not directly addressable", i);
-         if ((! allows_mem && MEM_P (op))
+         if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode)
              || GET_CODE (op) == CONCAT)
            {
              rtx old_op = op;
--- gcc/testsuite/g++.dg/ext/asm14.C.jj 2018-05-05 13:15:50.099258834 +0200
+++ gcc/testsuite/g++.dg/ext/asm14.C    2018-05-05 13:19:09.717327528 +0200
@@ -0,0 +1,10 @@
+// PR c++/85659
+// { dg-do compile }
+
+struct S { S (); ~S (); int s; };
+
+void
+foo (S &s)
+{
+  __asm volatile ("" : "+m,r" (s) : : "memory");
+}
--- gcc/testsuite/g++.dg/ext/asm15.C.jj 2018-05-05 13:15:56.656261090 +0200
+++ gcc/testsuite/g++.dg/ext/asm15.C    2018-05-05 13:19:15.125329389 +0200
@@ -0,0 +1,10 @@
+// PR c++/85659
+// { dg-do compile }
+
+struct S { S (); ~S (); int s; };
+
+void
+foo (S &s)
+{
+  __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "" }
+}
--- gcc/testsuite/g++.dg/ext/asm16.C.jj 2018-05-05 13:28:03.448530441 +0200
+++ gcc/testsuite/g++.dg/ext/asm16.C    2018-05-05 13:28:21.068539532 +0200
@@ -0,0 +1,10 @@
+// PR c++/85659
+// { dg-do compile }
+
+struct S { S (); ~S (); int s[64]; } s;
+
+void
+foo ()
+{
+  __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "" }
+}

        Jakub

Reply via email to