diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ca2e702508..aba1311efea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ #### Bug fixes - Fix potentially corrupt IR layouts for bit fields. (#4646, #4708) - Fix potentially corrupt IR layouts for explicitly under-aligned aggregates, a regression introduced in LDC v1.31. (#4734, #4736) +- ELF: Emit (most) instantiated symbols in COMDATs for proper link-time culling. (#3589, #4748) # LDC 1.39.0 (2024-07-04) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 656ea4f4654..36af3127369 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -259,7 +259,13 @@ LLGlobalValue::LinkageTypes DtoLinkageOnly(Dsymbol *sym) { } LinkageWithCOMDAT DtoLinkage(Dsymbol *sym) { - return {DtoLinkageOnly(sym), needsCOMDAT()}; + const auto linkage = DtoLinkageOnly(sym); + const bool inCOMDAT = needsCOMDAT() || + // ELF needs some help for ODR linkages: + // https://github.com/ldc-developers/ldc/issues/3589 + (linkage == templateLinkage && + global.params.targetTriple->isOSBinFormatELF()); + return {linkage, inCOMDAT}; } bool needsCOMDAT() { diff --git a/tests/codegen/gh3589.d b/tests/codegen/gh3589.d new file mode 100644 index 00000000000..278650cbe85 --- /dev/null +++ b/tests/codegen/gh3589.d @@ -0,0 +1,22 @@ +// UNSUPPORTED: Windows || Darwin + +// emit duplicate instantiated globals into two object files: +// RUN: %ldc -c %S/inputs/gh3589_a.d -I%S/inputs -of=%t_a.o +// RUN: %ldc -c %S/inputs/gh3589_b.d -I%S/inputs -of=%t_b.o + +// link & run: +// RUN: %ldc -I%S/inputs %t_a.o %t_b.o -run %s + +extern extern(C) __gshared { + // magic linker symbols to refer to the start and end of test_section + byte __start_test_section; + byte __stop_test_section; +} + +void main() { + import gh3589_a, gh3589_b; + assert(a_info == b_info); + + const sectionSize = cast(size_t) (&__stop_test_section - &__start_test_section); + assert(sectionSize == 4); +} diff --git a/tests/codegen/inputs/gh3589_a.d b/tests/codegen/inputs/gh3589_a.d new file mode 100644 index 00000000000..e3469c1f3ff --- /dev/null +++ b/tests/codegen/inputs/gh3589_a.d @@ -0,0 +1,2 @@ +import gh3589_templ; +shared a_info = &getInfo!0; diff --git a/tests/codegen/inputs/gh3589_b.d b/tests/codegen/inputs/gh3589_b.d new file mode 100644 index 00000000000..cad7cbf7ed1 --- /dev/null +++ b/tests/codegen/inputs/gh3589_b.d @@ -0,0 +1,2 @@ +import gh3589_templ; +shared b_info = &getInfo!0; diff --git a/tests/codegen/inputs/gh3589_templ.di b/tests/codegen/inputs/gh3589_templ.di new file mode 100644 index 00000000000..f395ad2b9ee --- /dev/null +++ b/tests/codegen/inputs/gh3589_templ.di @@ -0,0 +1,4 @@ +import ldc.attributes; +template getInfo(int I) { + @(section("test_section")) @assumeUsed shared int getInfo = I; +}