https://gcc.gnu.org/g:ec3a01024dd86c51d1e563df9395123765cf548d

commit r12-10202-gec3a01024dd86c51d1e563df9395123765cf548d
Author: Iain Buclaw <ibuc...@gdcproject.org>
Date:   Sun Mar 10 17:49:06 2024 +0100

    d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285]
    
    The way that the target hook preferPassByRef is implemented, it relied
    on the GCC "back-end" tree type to determine whether or not to use `ref'
    ABI for D `in' parameters; e.g: prefer by value if it is expected that
    the target will pass the type around in registers.
    
    Building the GCC tree type depends on the AST type being complete - all
    semantic processing is finished - but as this hook is called from the
    front-end, this will not be the case for forward referenced or
    self-referencing types.
    
    The consensus in upstream is that `in' parameters should always be
    implicitly `ref', but as the front-end does not yet support all types
    being rvalue references, limit this just static arrays and structs.
    
            PR d/112285
            PR d/112290
    
    gcc/d/ChangeLog:
    
            * d-target.cc (Target::preferPassByRef): Return true for all static
            array and struct types.
    
    gcc/testsuite/ChangeLog:
    
            * gdc.dg/pr112285.d: New test.
            * gdc.dg/pr112290.d: New test.
            * gdc.test/compilable/previewin.d: Adjust testcase.
    
    (cherry picked from commit 025ff57c19efae6c8d76df6b93e7d9827017acc9)

Diff:
---
 gcc/d/d-target.cc                             | 25 +++++--------------------
 gcc/testsuite/gdc.dg/pr112285.d               | 13 +++++++++++++
 gcc/testsuite/gdc.dg/pr112290.d               | 15 +++++++++++++++
 gcc/testsuite/gdc.test/compilable/previewin.d |  6 ------
 4 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d4350e593e4..f80ea466e24 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -586,31 +586,16 @@ Target::supportsLinkerDirective (void) const
 }
 
 /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to
-   be passed by reference or by valie.  This is used only when compiling with
+   be passed by reference or by value.  This is used only when compiling with
    `-fpreview=in' enabled.  */
 
 bool
 Target::preferPassByRef (Type *param_type)
 {
-  if (param_type->size () == SIZE_INVALID)
+  /* See note in Target::isReturnOnStack.  */
+  Type *tb = param_type->toBasetype ();
+  if (tb->size () == SIZE_INVALID)
     return false;
 
-  tree type = build_ctype (param_type);
-
-  /* Prefer a `ref' if the type is an aggregate, and its size is greater than
-     its alignment.  */
-  if (AGGREGATE_TYPE_P (type)
-      && (!valid_constant_size_p (TYPE_SIZE_UNIT (type))
-         || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0))
-    return true;
-
-  /* If the back-end is always going to pass this by invisible reference.  */
-  if (pass_by_reference (NULL, function_arg_info (type, true)))
-    return true;
-
-  /* If returning the parameter means the caller will do RVO.  */
-  if (targetm.calls.return_in_memory (type, NULL_TREE))
-    return true;
-
-  return false;
+  return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray);
 }
diff --git a/gcc/testsuite/gdc.dg/pr112285.d b/gcc/testsuite/gdc.dg/pr112285.d
new file mode 100644
index 00000000000..5ca100a74a9
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr112285.d
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-additional-options "-fpreview=in" }
+struct S112285
+{
+}
+
+class C112285
+{
+    S112285 s;
+    void f112285(in C112285)
+    {
+    }
+}
diff --git a/gcc/testsuite/gdc.dg/pr112290.d b/gcc/testsuite/gdc.dg/pr112290.d
new file mode 100644
index 00000000000..7456fc21be1
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr112290.d
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-additional-options "-fpreview=in" }
+struct S112290a
+{
+    S112290b* p;
+    bool opEquals(in S112290a)
+    {
+        return p == p;
+    }
+}
+
+struct S112290b
+{
+    string s;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/previewin.d 
b/gcc/testsuite/gdc.test/compilable/previewin.d
index 8926fbd6aa7..558005c5280 100644
--- a/gcc/testsuite/gdc.test/compilable/previewin.d
+++ b/gcc/testsuite/gdc.test/compilable/previewin.d
@@ -79,14 +79,11 @@ version (Win64)
 {
     void checkReal(in real p)
     {
-        // ref for x87 real, value for double-precision real
-        static assert(__traits(isRef, p) == (real.sizeof > 8));
     }
 
     struct RGB { ubyte r, g, b; }
     void checkNonPowerOf2(in RGB p)
     {
-        static assert(__traits(isRef, p));
     }
 }
 else version (X86_64) // Posix x86_64
@@ -94,7 +91,6 @@ else version (X86_64) // Posix x86_64
     struct Empty {} // 1 dummy byte passed on the stack
     void checkEmptyStruct(in Empty p)
     {
-        static assert(!__traits(isRef, p));
     }
 
     static if (is(__vector(double[4])))
@@ -102,7 +98,6 @@ else version (X86_64) // Posix x86_64
         struct AvxVectorWrapper { __vector(double[4]) a; } // 256 bits
         void checkAvxVector(in AvxVectorWrapper p)
         {
-            static assert(!__traits(isRef, p));
         }
     }
 }
@@ -111,6 +106,5 @@ else version (AArch64)
     alias HVA = __vector(float[4])[4]; // can be passed in 4 vector registers
     void checkHVA(in HVA p)
     {
-        static assert(!__traits(isRef, p));
     }
 }

Reply via email to