Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cross module inlining fails when code contains switch with string argument and at least 7 cases #4808

Open
KytoDragon opened this issue Dec 31, 2024 · 4 comments

Comments

@KytoDragon
Copy link
Contributor

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.

@JohanEngelen
Copy link
Member

Can you help out and test with a small testcase whether cross-module inlining works for static variables inside the inlined function? Thanks

@apbryan
Copy link

apbryan commented Jan 21, 2025

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

@apbryan
Copy link

apbryan commented Jan 21, 2025

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.

@apbryan
Copy link

apbryan commented Jan 22, 2025

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants