Thread overview
DMD64 2.095.1 unresolved _D4core8internal7switch___T14__switch_error in optimized build only
Apr 09, 2021
x3g6h7k8
Apr 09, 2021
MoonlightSentinel
Apr 09, 2021
x3g6h7k8
Apr 10, 2021
x3g6h7k8
April 09, 2021

Working on a project with some dozen source files and an external dependency on botan building with integrated dub.
There is only minimal templating used on my side.
Using DMD 64bit 2.095.1 I get the following error:

app_win_dmd_a64_rel.obj : error LNK2019: unresolved external symbol _D4core8internal7switch___T14__switch_errorZQrFNaNbNiNfAyamZv referenced in function _D3std3uni__T21genericDecodeGraphemeVbi0Z__TQBfTAxwZQBnFNaNbNiNfKQrZv

.dub\build\mainapp_win_dmd_a64_rel-release-windows-x86_64-dmd_v2.095.1-dirty-76A12175597E4044EE0E049BBF1AC35D\app_win_dmd_a64_rel.exe : fatal error LNK1120: 1 unresolved externals

The interesting point is this happens only in optimized builds. In debug builds everything is fine.
It happens both with Windows DMD64 and Linux DMD64.

Dub compile options in debug:

dmd -m64 -c -of.dub\build\app_win_dmd_...\app_win_dmd_a64_dbg.obj -debug -g -wi -de ...

Dub compile options in optimized:

dmd -m64 -c -of.dub\build\app_win_dmd_...\app_win_dmd_a64_rel.obj -inline -O -wi -de ...

template genericDecodeGrapheme(bool getValue) seems to sit in
dmd2\src\phobos\std\uni\package.d
and has a switch in it.

What's going on here?

I could imagine the following:

  1. The optimizer does some lowering or similar and chooses a different code path not used in debug builds.
  2. Something is different with name mangling in debug/optimized builds.

Is this a known problem already? Didn't found something about it.
Anyone with an idea how to cope with it?

Currently I don't have a reduced test case for this and may not be able to create one shortly.

Thanks

April 09, 2021

On Friday, 9 April 2021 at 11:36:21 UTC, x3g6h7k8 wrote:

>

The interesting point is this happens only in optimized builds. In debug builds everything is fine.

Looks like DMD skips the codegen for this template instance because it erroneously assumes that the template is already emitted in another object file.
This decision is probably affected by some code in a debug statement which makes it work when compiling with -debug.

You can try to compile the release version with -allinst.

April 09, 2021

On Friday, 9 April 2021 at 12:41:02 UTC, MoonlightSentinel wrote:

>

On Friday, 9 April 2021 at 11:36:21 UTC, x3g6h7k8 wrote:

>

The interesting point is this happens only in optimized builds. In debug builds everything is fine.

Looks like DMD skips the codegen for this template instance because it erroneously assumes that the template is already emitted in another object file.
This decision is probably affected by some code in a debug statement which makes it work when compiling with -debug.

You can try to compile the release version with -allinst.

After posting my message I found this one by chance:
https://forum.dlang.org/post/lixbkcxtalzplziwbssq@forum.dlang.org

It seems to be a different problem but has the same missing symbol (among others). So I tried the given solution there, doing a clean slate, removing project .dub/ and home dub/. This changed nothing on my side.

Thereafter I removed the "inline" from the regular dub release buildOptions. With this change an executable was created.

Then I saw your reply. So far I can see there is no debug statement in my own code. However could it be that unittest blocks could trigger a similar behavior?

An observation I made now was that compiling unit tests with ["optimize", "inline"] in an extra buildType were working fine too.

Lastly I tried your suggestion with -allinst. This made no difference, same linking error.

So for the time being I will stick to not using "inline", this should be not a big problem.

Thank you very much for your input to this problem.

April 10, 2021

On Friday, 9 April 2021 at 14:59:16 UTC, x3g6h7k8 wrote:

>

Thereafter I removed the "inline" from the regular dub release buildOptions. With this change an executable was created.

Seems I missed that I also removed the -release switch, which was the important one. It works with or w/o inline.
Instead of removing -release it's also possible to add -check=switch=off.
Using optimize w/o -release has given me some headache with active out-contracts in the Base64 module (Base64.encode(bytes)) leading to 0xc0000005 after a seemingly corrupted stack. Unfortunately I can't really reproduce this in a small example. Maybe this was simply the place where another problem manifested itself.