d: Fix FAIL in gdc.dg/runnable.d on X32 targets (PR94609)
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 19 Apr 2020 07:54:25 +0000 (09:54 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 19 Apr 2020 07:54:25 +0000 (09:54 +0200)
Patch fixes test failure seen on X32 where a nested struct was passed in
registers, rather than via invisible reference.  Now, all non-POD
structs are passed by invisible reference, not just those with a
user-defined copy constructor/destructor.

gcc/d/ChangeLog:

PR d/94609
* d-codegen.cc (argument_reference_p): Don't check TREE_ADDRESSABLE.
(type_passed_as): Build reference type if TREE_ADDRESSABLE.
* d-convert.cc (convert_for_argument): Build explicit TARGET_EXPR if
needed for arguments passed by invisible reference.
* types.cc (TypeVisitor::visit (TypeStruct *)): Mark all structs that
are not POD as TREE_ADDRESSABLE.

gcc/d/ChangeLog
gcc/d/d-codegen.cc
gcc/d/d-convert.cc
gcc/d/types.cc

index 6544b3d324e2b38139503475ff760f1306baeede..6c3eb89c4d71d279869852fb7371a91175b1b490 100644 (file)
@@ -1,3 +1,13 @@
+2020-04-19  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       PR d/94609
+       * d-codegen.cc (argument_reference_p): Don't check TREE_ADDRESSABLE.
+       (type_passed_as): Build reference type if TREE_ADDRESSABLE.
+       * d-convert.cc (convert_for_argument): Build explicit TARGET_EXPR if
+       needed for arguments passed by invisible reference.
+       * types.cc (TypeVisitor::visit (TypeStruct *)): Mark all structs that
+       are not POD as TREE_ADDRESSABLE.
+
 2020-04-13  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        * Make-lang.in (D_FRONTEND_OBJS): Remove d/argtypes.o.
index 66af2b4da308a59da95768f28a97ff15a7952674..8dc1ab264f84547c34bf4d6e30e014d976b3313f 100644 (file)
@@ -180,10 +180,6 @@ argument_reference_p (Parameter *arg)
   if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
     return true;
 
-  tree type = build_ctype (arg->type);
-  if (TREE_ADDRESSABLE (type))
-    return true;
-
   return false;
 }
 
@@ -211,7 +207,7 @@ type_passed_as (Parameter *arg)
   tree type = build_ctype (arg->type);
 
   /* Parameter is passed by reference.  */
-  if (argument_reference_p (arg))
+  if (TREE_ADDRESSABLE (type) || argument_reference_p (arg))
     return build_reference_type (type);
 
   return type;
index 533bbabd168c5d5dc6aae9f45b62f67a087757a9..9ee149b8386330519fa6e021ad2e51c512fe96d8 100644 (file)
@@ -677,6 +677,21 @@ convert_for_argument (tree expr, Parameter *arg)
       /* Front-end shouldn't automatically take the address.  */
       return convert (type_passed_as (arg), build_address (expr));
     }
+  else if (TREE_ADDRESSABLE (TREE_TYPE (expr)))
+    {
+      /* Type is a struct passed by invisible reference.  */
+      Type *t = arg->type->toBasetype ();
+      gcc_assert (t->ty == Tstruct);
+      StructDeclaration *sd = ((TypeStruct *) t)->sym;
+
+      /* Nested structs also have ADDRESSABLE set, but if the type has
+        neither a copy constructor nor a destructor available, then we
+        need to take care of copying its value before passing it.  */
+      if (!sd->postblit && !sd->dtor)
+       expr = force_target_expr (expr);
+
+      return convert (type_passed_as (arg), build_address (expr));
+    }
 
   return expr;
 }
index e0e770af325d914c503b81f43fcdf03149810b33..f6ae5740f010a0deb32ddd4fe4abf8f153f14a99 100644 (file)
@@ -915,7 +915,7 @@ public:
     /* For structs with a user defined postblit or a destructor,
        also set TREE_ADDRESSABLE on the type and all variants.
        This will make the struct be passed around by reference.  */
-    if (t->sym->postblit || t->sym->dtor)
+    if (!t->sym->isPOD ())
       {
        for (tree tv = t->ctype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))
          TREE_ADDRESSABLE (tv) = 1;