ldc
ldc copied to clipboard
cross module inlining fails when code contains switch with string argument and at least 7 cases
The following code
int main(string[] a) {
switch (a[0]) {
case "one":
return 1;
case "two":
return 2;
case "three":
return 3;
case "four":
return 4;
case "five":
return 5;
case "six":
return 6;
case "seven":
return 7;
default:
return 0;
}
}
when compiled with these options:
ldc2 -enable-inlining --enable-cross-module-inlining=true -Isource source\main.d -ofd-test.exe -link-internally
results in the following error:
lld-link: error: undefined symbol: _D4core8internal7switch___T8__switchTyaVxAyaa3_6f6e65VxQoa3_736978VxQBba3_74776fVxQBpa4_66697665VxQCfa4_666f7572VxQCva5_736576656eVxQDna5_7468726565ZQEsFNaNbNiNfMxQEsZ5casesyG7Aa
>>> referenced by d-test.obj:(_D4core8internal7switch___T8__switchTyaVxAyaa3_6f6e65VxQoa3_736978VxQBba3_74776fVxQBpa4_66697665VxQCfa4_666f7572VxQCva5_736576656eVxQDna5_7468726565ZQEsFNaNbNiNfMxQEsZi)
Error: linking with LLD failed
The identifier in question is defined in druntime here. Tested on Windows 10 with LDC 1.40.0.
Can you help out and test with a small testcase whether cross-module inlining works for static variables inside the inlined function? Thanks
I can confirm this bug on linux as well. I also confirmed the bug is present in the case when all of the variables are static ones inside of the function (though I now realize this is probably not what you meant):
(ldc-1.40.0)alex@compy programming/ldc-bug-test cat source/app.d 22:25:09 25-01-20
import std.stdio;
int main(string[] args)
{
static immutable string ONE = "one";
static immutable string TWO = "two";
static immutable string THREE = "three";
static immutable string FOUR = "four";
static immutable string FIVE = "five";
static immutable string SIX = "six";
static immutable string SEVEN = "seven";
static immutable string testcase="asdf";
//switch (args[0]) {
switch (testcase) {
case ONE:
return 1;
case TWO:
return 2;
case THREE:
return 3;
case FOUR:
return 4;
case FIVE:
return 5;
case SIX:
return 6;
case SEVEN:
return 7;
default:
return 0;
}
}
(ldc-1.40.0)alex@compy programming/ldc-bug-test dub build --verbose --compiler=ldc2 --force -b release 2>&1 | ddemangle
Note: Failed to determine version of package ldc-bug-test at .. Assuming ~master.
Generating using build
Configuring dependent ldc-bug-test, deps:
Starting Performing "release" build using ldc2 for x86_64.
Building ldc-bug-test ~master: building configuration [application]
ldc2 -release -enable-inlining -Hkeep-all-bodies -O3 -w --oq -od=/home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ/obj -d-version=Have_ldc_bug_test -Isource/ source/app.d --enable-cross-module-inlining -c -of/home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ/ldc-bug-test.o -vcolumns
Linking ldc-bug-test
ldc2 -of/home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ/ldc-bug-test /home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ/ldc-bug-test.o -L--no-as-needed
/usr/bin/ld: /home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ/ldc-bug-test.o: in function `_Dmain':
app.d:(.text._Dmain+0xb): undefined reference to `immutable(char[][7]) core.internal.switch_.__switch!(immutable(char), "one", "six", "two", "five", "four", "seven", "three").__switch(scope const(immutable(char)[])).cases'
collect2: error: ld returned 1 exit status
Error: /usr/bin/cc failed with status: 1
FAIL /home/alex/.dub/cache/ldc-bug-test/~master/build/application-release-Q_nYxZRIsAfltX3Ha9-VnQ ldc-bug-test executable
Error ldc2 failed with exit code 1.
(ldc-1.40.0)alex@compy programming/ldc-bug-test ldc2 --version 22:25:14 25-01-20
LDC - the LLVM D compiler (1.40.0):
based on DMD v2.110.0 and LLVM 19.1.3
built with LDC - the LLVM D compiler (1.40.0)
Default target: x86_64-unknown-linux-gnu
Host CPU: znver4
http://dlang.org - http://wiki.dlang.org/LDC
Registered Targets:
aarch64 - AArch64 (little endian)
aarch64_32 - AArch64 (little endian ILP32)
aarch64_be - AArch64 (big endian)
amdgcn - AMD GCN GPUs
arm - ARM
arm64 - ARM64 (little endian)
arm64_32 - ARM64 (little endian ILP32)
armeb - ARM (big endian)
avr - Atmel AVR Microcontroller
bpf - BPF (host endian)
bpfeb - BPF (big endian)
bpfel - BPF (little endian)
hexagon - Hexagon
lanai - Lanai
loongarch32 - 32-bit LoongArch
loongarch64 - 64-bit LoongArch
mips - MIPS (32-bit big endian)
mips64 - MIPS (64-bit big endian)
mips64el - MIPS (64-bit little endian)
mipsel - MIPS (32-bit little endian)
msp430 - MSP430 [experimental]
nvptx - NVIDIA PTX 32-bit
nvptx64 - NVIDIA PTX 64-bit
ppc32 - PowerPC 32
ppc32le - PowerPC 32 LE
ppc64 - PowerPC 64
ppc64le - PowerPC 64 LE
r600 - AMD GPUs HD2XXX-HD6XXX
riscv32 - 32-bit RISC-V
riscv64 - 64-bit RISC-V
sparc - Sparc
sparcel - Sparc LE
sparcv9 - Sparc V9
spirv - SPIR-V Logical
spirv32 - SPIR-V 32-bit
spirv64 - SPIR-V 64-bit
systemz - SystemZ
thumb - Thumb
thumbeb - Thumb (big endian)
ve - VE
wasm32 - WebAssembly 32-bit
wasm64 - WebAssembly 64-bit
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
xcore - XCore
xtensa - Xtensa 32
Here is what I think you actually wanted:
alex@compy programming/ldc-bug-test2 tree 22:57:55 25-01-20
.
├── dub.sdl
├── foo
│ ├── dub.sdl
│ ├── libfoo.a
│ └── source
│ └── foo.d
├── ldc-bug-test2
└── source
└── app.d
4 directories, 6 files
alex@compy programming/ldc-bug-test2 cat dub.sdl 22:57:57 25-01-20
name "ldc-bug-test2"
description "A minimal D application."
authors "alex"
copyright "Copyright © 2025, alex"
license "MPL-2.0"
dflags "--enable-cross-module-inlining" platform="ldc"
dependency "foo" path="./foo"
alex@compy programming/ldc-bug-test2 cat source/app.d 22:58:04 25-01-20
import std.stdio;
import foo;
void main()
{
int a = doFoo!(["one", "two"])(1);
writeln(a);
}
alex@compy programming/ldc-bug-test2 cat foo/dub.sdl 22:58:11 25-01-20
name "foo"
description "A minimal D application."
authors "alex"
copyright "Copyright © 2025, alex"
license "MPL-2.0"
alex@compy programming/ldc-bug-test2 cat foo/source/foo.d 22:58:19 25-01-20
module foo.foo;
import std.math;
int doFoo(labels...)(int a)
{
//static immutable int[labels.length] b; // does not compile when line uncommented
immutable int[labels.length] b; //compiles
return a + b[0];
}
alex@compy programming/ldc-bug-test2 dub clean 22:58:30 25-01-20
Cleaning artifacts for package ldc-bug-test2 at /home/alex/.dub/cache/ldc-bug-test2/~master
alex@compy programming/ldc-bug-test2 dub build --compiler=ldc2 -b release 2>&1 --verbose | ddemangle 22:59:11 25-01-20
Note: Failed to determine version of package ldc-bug-test2 at .. Assuming ~master.
Version selection for dependency foo (foo) of ldc-bug-test2 is missing.
Adding local foo in /home/alex/programming/ldc-bug-test2/foo
Note: Failed to determine version of package foo at .. Assuming ~master.
Found dependency foo @./foo
Generating using build
Configuring dependent ldc-bug-test2, deps:"foo"
Configuring dependent foo, deps:
Starting Performing "release" build using ldc2 for x86_64.
Up-to-date foo ~master: target for configuration [library] is up to date.
Using existing build in /home/alex/.dub/cache/foo/~master/build/library-release-HSpfiB7qMGgJmWdFzlw2rQ.
Copying target from /home/alex/.dub/cache/foo/~master/build/library-release-HSpfiB7qMGgJmWdFzlw2rQ/libfoo.a to /home/alex/programming/ldc-bug-test2/foo
Target '/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2' doesn't exist, need rebuild.
Building ldc-bug-test2 ~master: building configuration [application]
ldc2 -release -enable-inlining -Hkeep-all-bodies -O3 -w --oq -od=/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/obj -d-version=Have_ldc_bug_test2 -d-version=Have_foo -Isource/ -Ifoo/source/ source/app.d --enable-cross-module-inlining -c -of/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o -vcolumns
Linking ldc-bug-test2
ldc2 -of/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2 /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o ../../.dub/cache/foo/~master/build/library-release-HSpfiB7qMGgJmWdFzlw2rQ/libfoo.a -L--no-as-needed
/usr/bin/ld: /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o: in function `_Dmain':
app.d:(.text._Dmain+0x8): undefined reference to `immutable(int[1]) foo.foo.doFoo!(["one", "two"]).doFoo(int).b'
collect2: error: ld returned 1 exit status
Error: /usr/bin/cc failed with status: 1
FAIL /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g ldc-bug-test2 executable
Error ldc2 failed with exit code 1.
When dub is run with --combined, the project does compile:
## Without --combined
alex@compy programming/ldc-bug-test2 dub clean 20:50:43 25-01-21
Cleaning artifacts for package ldc-bug-test2 at /home/alex/.dub/cache/ldc-bug-test2/~master
alex@compy programming/ldc-bug-test2 dub build -b release --compiler=ldc2 20:50:45 25-01-21
Starting Performing "release" build using ldc2 for x86_64.
Building foo ~master: building configuration [library]
Building ldc-bug-test2 ~master: building configuration [application]
Linking ldc-bug-test2
/usr/bin/ld: /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o: in function `_Dmain':
app.d:(.text._Dmain+0x8): undefined reference to `_D3foo__T5doFooVAAyaA2a3_6f6e65a3_74776fZQBgFiZ1byG1i'
collect2: error: ld returned 1 exit status
Error: /usr/bin/cc failed with status: 1
Error ldc2 failed with exit code 1.
## With combined
alex@compy programming/ldc-bug-test2 dub clean 20:50:49 25-01-21
Cleaning artifacts for package ldc-bug-test2 at /home/alex/.dub/cache/ldc-bug-test2/~master
alex@compy programming/ldc-bug-test2 dub build -b release --compiler=ldc2 --combined 20:50:52 25-01-21
Starting Performing "release" build using ldc2 for x86_64.
Building ldc-bug-test2 ~master: building configuration [application]
Linking ldc-bug-test2
EDIT: --combined verbose output:
alex@compy programming/ldc-bug-test2 dub clean 20:50:57 25-01-21
Cleaning artifacts for package ldc-bug-test2 at /home/alex/.dub/cache/ldc-bug-test2/~master
alex@compy programming/ldc-bug-test2 dub build -b release --compiler=ldc2 --combined --verbose 20:54:54 25-01-21
Note: Failed to determine version of package ldc-bug-test2 at .. Assuming ~master.
Version selection for dependency foo (foo) of ldc-bug-test2 is missing.
Adding local foo in /home/alex/programming/ldc-bug-test2/foo
Note: Failed to determine version of package foo at .. Assuming ~master.
Found dependency foo @./foo
Generating using build
Configuring dependent ldc-bug-test2, deps:
Starting Performing "release" build using ldc2 for x86_64.
Target '/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2' doesn't exist, need rebuild.
Building ldc-bug-test2 ~master: building configuration [application]
ldc2 -release -enable-inlining -Hkeep-all-bodies -O3 -w --oq -od=/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/obj -d-version=Have_ldc_bug_test2 -d-version=Have_foo -Isource/ -Ifoo/source/ source/app.d foo/source/foo.d --enable-cross-module-inlining -c -of/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o -vcolumns
Linking ldc-bug-test2
ldc2 -of/home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2 /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2.o -L--no-as-needed
Copying target from /home/alex/.dub/cache/ldc-bug-test2/~master/build/application-release-NexKB60AKoQrI6295VyB-g/ldc-bug-test2 to /home/alex/programming/ldc-bug-test2