aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/decl.cc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-11-12 15:37:46 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2020-11-13 14:58:58 +0100
commit5d4b824faf1e5846ec684a74f93912cf347928df (patch)
tree3f315f89a5c9204937e5425580254ac995400584 /gcc/d/decl.cc
parent5fa821bba737cf3e74801c5fe4d3e87a62aa79bf (diff)
downloadgcc-5d4b824faf1e5846ec684a74f93912cf347928df.zip
gcc-5d4b824faf1e5846ec684a74f93912cf347928df.tar.gz
gcc-5d4b824faf1e5846ec684a74f93912cf347928df.tar.bz2
d: Fix ICE in finish_thunk (PR97644)
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. 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.
Diffstat (limited to 'gcc/d/decl.cc')
-rw-r--r--gcc/d/decl.cc56
1 files changed, 24 insertions, 32 deletions
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index d668715..218f358 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;