diff mbox series

[committed] d: Fix ICE in finish_thunk (PR97644)

Message ID 20201113140604.1974689-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Fix ICE in finish_thunk (PR97644) | expand

Commit Message

Iain Buclaw Nov. 13, 2020, 2:06 p.m. UTC
Hi,

Because this what the upstream reference compiler did, thunks for the D
front-end were associated with the class definition, so were forced
code-gen even if the target function was extern.  This has now been
changed so there are now only generated if there is a function
definition, fixing the ICE that occurred in PR 97644, which was caused
by calling expand_thunk() early.

Bootstrapped and regression tested on x86_64-linux-gnu, and committed to
mainline.

Regards
Iain.

---
gcc/d/ChangeLog:

	PR d/97644
	* dmd/MERGE: Merge upstream dmd 95044d8e4.
	* d-target.cc (TargetCPP::thunkMangle): New function.
	* decl.cc (finish_thunk): Don't force expand thunks for external
	functions.
	(make_thunk): Emit thunks only if the function has a definition.
	Generate correct mangling for thunks to C++ classes.

gcc/testsuite/ChangeLog:

	* gdc.dg/pr92216.d: Update scan-assember.
---
 gcc/d/d-target.cc              |  9 ++++++
 gcc/d/decl.cc                  | 56 +++++++++++++++-------------------
 gcc/d/dmd/MERGE                |  2 +-
 gcc/d/dmd/cppmangle.c          | 20 +++++++++++-
 gcc/d/dmd/mangle.h             |  1 +
 gcc/d/dmd/target.h             |  2 ++
 gcc/testsuite/gdc.dg/pr92216.d |  4 +--
 7 files changed, 58 insertions(+), 36 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 692fce6a655..cd136524eb9 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -329,6 +329,15 @@  TargetCPP::typeInfoMangle (ClassDeclaration *cd)
   return cppTypeInfoMangleItanium (cd);
 }
 
+/* Get mangle name of a this-adjusting thunk to the function declaration FD
+   at call offset OFFSET for C++ linkage.  */
+
+const char *
+TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
+{
+  return cppThunkMangleItanium (fd, offset);
+}
+
 /* For a vendor-specific type, return a string containing the C++ mangling.
    In all other cases, return NULL.  */
 
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index d668715af59..218f35838fd 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1693,26 +1693,6 @@  finish_thunk (tree thunk, tree function)
 
   if (DECL_ONE_ONLY (function))
     thunk_node->add_to_same_comdat_group (funcn);
-
-  /* Target assemble_mi_thunk doesn't work across section boundaries
-     on many targets, instead force thunk to be expanded in gimple.  */
-  if (DECL_EXTERNAL (function))
-    {
-      /* cgraph::expand_thunk writes over current_function_decl, so if this
-	 could ever be in use by the codegen pass, we want to know about it.  */
-      gcc_assert (current_function_decl == NULL_TREE);
-
-      if (!stdarg_p (TREE_TYPE (thunk)))
-	{
-	  thunk_node->create_edge (funcn, NULL, thunk_node->count);
-	  expand_thunk (thunk_node, false, true);
-	}
-
-      /* Tell the back-end to not bother inlining the function, this is
-	 assumed not to work as it could be referencing symbols outside
-	 of the current compilation unit.  */
-      DECL_UNINLINABLE (function) = 1;
-    }
 }
 
 /* Return a thunk to DECL.  Thunks adjust the incoming `this' pointer by OFFSET.
@@ -1789,12 +1769,11 @@  make_thunk (FuncDeclaration *decl, int offset)
 
   DECL_CONTEXT (thunk) = d_decl_context (decl);
 
-  /* Thunks inherit the public access of the function they are targetting.
-     When the function is outside the current compilation unit however, then the
-     thunk must be kept private to not conflict.  */
-  TREE_PUBLIC (thunk) = TREE_PUBLIC (function) && !DECL_EXTERNAL (function);
-
-  DECL_EXTERNAL (thunk) = 0;
+  /* Thunks inherit the public access of the function they are targeting.
+     Thunks are connected to the definitions of the functions, so thunks are
+     not produced for external functions.  */
+  TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+  DECL_EXTERNAL (thunk) = DECL_EXTERNAL (function);
 
   /* Thunks are always addressable.  */
   TREE_ADDRESSABLE (thunk) = 1;
@@ -1806,18 +1785,31 @@  make_thunk (FuncDeclaration *decl, int offset)
   DECL_COMDAT (thunk) = DECL_COMDAT (function);
   DECL_WEAK (thunk) = DECL_WEAK (function);
 
-  tree target_name = DECL_ASSEMBLER_NAME (function);
-  unsigned identlen = IDENTIFIER_LENGTH (target_name) + 14;
-  const char *ident = XNEWVEC (const char, identlen);
-  snprintf (CONST_CAST (char *, ident), identlen,
-	    "_DT%u%s", offset, IDENTIFIER_POINTER (target_name));
+  /* When the thunk is for an extern C++ function, let C++ do the thunk
+     generation and just reference the symbol as extern, instead of
+     forcing a D local thunk to be emitted.  */
+  const char *ident;
+
+  if (decl->linkage == LINKcpp)
+    ident = target.cpp.thunkMangle (decl, offset);
+  else
+    {
+      tree target_name = DECL_ASSEMBLER_NAME (function);
+      unsigned identlen = IDENTIFIER_LENGTH (target_name) + 14;
+      ident = XNEWVEC (const char, identlen);
+
+      snprintf (CONST_CAST (char *, ident), identlen,
+		"_DTi%u%s", offset, IDENTIFIER_POINTER (target_name));
+    }
 
   DECL_NAME (thunk) = get_identifier (ident);
   SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));
 
   d_keep (thunk);
+  free (CONST_CAST (char *, ident));
 
-  finish_thunk (thunk, function);
+  if (!DECL_EXTERNAL (function))
+    finish_thunk (thunk, function);
 
   /* Add it to the list of thunks associated with the function.  */
   DECL_LANG_THUNKS (thunk) = NULL_TREE;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 39e424f2a98..e2a0bab2e4a 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-bec5973b0203c95adbda2a049ccdf3cd3a4378f6
+95044d8e45a4320f07d9c75b4eb30e55688a8195
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index b361d37f75d..3f571fcb14b 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -582,13 +582,21 @@  class CppMangleVisitor : public Visitor
         //printf("mangle_function(%s)\n", d->toChars());
         /*
          * <mangled-name> ::= _Z <encoding>
+         */
+        buf->writestring("_Z");
+        this->mangle_function_encoding(d);
+    }
+
+    void mangle_function_encoding(FuncDeclaration *d)
+    {
+        //printf("mangle_function_encoding(%s)\n", d->toChars());
+        /*
          * <encoding> ::= <function name> <bare-function-type>
          *            ::= <data name>
          *            ::= <special-name>
          */
         TypeFunction *tf = (TypeFunction *)d->type;
 
-        buf->writestring("_Z");
         if (getFuncTemplateDecl(d))
         {
             /* It's an instance of a function template
@@ -1132,3 +1140,13 @@  const char *cppTypeInfoMangleItanium(Dsymbol *s)
     v.cpp_mangle_name(s, false);
     return buf.extractChars();
 }
+
+const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset)
+{
+    //printf("cppThunkMangleItanium(%s)\n", fd.toChars());
+    OutBuffer buf;
+    buf.printf("_ZThn%u_", offset);  // "Th" means thunk, "n%u" is the call offset
+    CppMangleVisitor v(&buf, fd->loc);
+    v.mangle_function_encoding(fd);
+    return buf.extractChars();
+}
diff --git a/gcc/d/dmd/mangle.h b/gcc/d/dmd/mangle.h
index 77801abb5f6..c60f4a73440 100644
--- a/gcc/d/dmd/mangle.h
+++ b/gcc/d/dmd/mangle.h
@@ -20,6 +20,7 @@  struct OutBuffer;
 // In cppmangle.c
 const char *toCppMangleItanium(Dsymbol *s);
 const char *cppTypeInfoMangleItanium(Dsymbol *s);
+const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
 
 // In cppmanglewin.c
 const char *toCppMangleMSVC(Dsymbol *s);
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index c34826af304..f2a55d6a134 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -19,6 +19,7 @@ 
 class ClassDeclaration;
 class Dsymbol;
 class Expression;
+class FuncDeclaration;
 class Parameter;
 class Type;
 class TypeTuple;
@@ -38,6 +39,7 @@  struct TargetCPP
 
     const char *toMangle(Dsymbol *s);
     const char *typeInfoMangle(ClassDeclaration *cd);
+    const char *thunkMangle(FuncDeclaration *fd, int offset);
     const char *typeMangle(Type *t);
     Type *parameterType(Parameter *p);
     bool fundamentalType(const Type *t, bool& isFundamental);
diff --git a/gcc/testsuite/gdc.dg/pr92216.d b/gcc/testsuite/gdc.dg/pr92216.d
index 6a87025a7d0..3aff160f799 100644
--- a/gcc/testsuite/gdc.dg/pr92216.d
+++ b/gcc/testsuite/gdc.dg/pr92216.d
@@ -1,8 +1,8 @@ 
 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92216
 // { dg-options "-I $srcdir/gdc.dg" }
 // { dg-do compile }
-// { dg-final { scan-assembler "_DT(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv\[: \t\n\]" } }
-// { dg-final { scan-assembler-not "(.globl|.global)\[ 	\]+_DT(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv" } }
+// { dg-final { scan-assembler "_DTi(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv\[: \t\n\]" } }
+// { dg-final { scan-assembler-not "(.globl|.global)\[ 	\]+_DTi(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv" } }
 module pr92216;
 
 private import imports.pr92216;