diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-11-12 15:37:46 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-11-13 14:58:58 +0100 |
commit | 5d4b824faf1e5846ec684a74f93912cf347928df (patch) | |
tree | 3f315f89a5c9204937e5425580254ac995400584 /gcc/d/decl.cc | |
parent | 5fa821bba737cf3e74801c5fe4d3e87a62aa79bf (diff) | |
download | gcc-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.cc | 56 |
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; |