diff --git a/lld/test/wasm/Inputs/comdat1.s b/lld/test/wasm/Inputs/comdat1.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/Inputs/comdat1.s @@ -0,0 +1,12 @@ + .section .text.foo,"G",@,foo,comdat + .globl foo + .type foo,@function +foo: + .functype foo () -> () + return + end_function + + .section .debug_foo,"G",@,foo,comdat + .int32 1 + .section .debug_foo,"G",@,duplicate,comdat + .int64 234 diff --git a/lld/test/wasm/Inputs/comdat2.s b/lld/test/wasm/Inputs/comdat2.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/Inputs/comdat2.s @@ -0,0 +1,12 @@ + .section .text.foo,"G",@,foo,comdat + .weak foo + .type foo,@function +foo: + .functype foo () -> () + return + end_function + + .section .debug_foo,"G",@,foo,comdat + .int32 2 + .section .debug_foo,"G",@,duplicate,comdat + .int64 234 diff --git a/lld/test/wasm/comdat-sections.s b/lld/test/wasm/comdat-sections.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/comdat-sections.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc -triple=wasm32 -filetype=obj %p/Inputs/comdat1.s -o %t1.o +# RUN: llvm-mc -triple=wasm32 -filetype=obj %p/Inputs/comdat2.s -o %t2.o +# RUN: llvm-mc -triple=wasm32 -filetype=obj %s -o %t.o +# RUN: wasm-ld --no-gc-sections -o %t.wasm %t.o %t1.o %t2.o +# RUN: obj2yaml %t.wasm | FileCheck %s + + + .globl _start + .type _start,@function +_start: + .functype _start () -> () + call foo + end_function + + +# .section .debug_foo,"G",@,abc123,comdat +# .int32 42 +# .section .debug_foo,"G",@,duplicate,comdat +# .int64 234 + + .functype foo () -> () diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -341,6 +341,12 @@ } } + ArrayRef comdats = wasmObj->linkingData().Comdats; + for (StringRef comdat : comdats) { + bool isNew = ignoreComdats || symtab->addComdat(comdat); + keptComdats.push_back(isNew); + } + uint32_t sectionIndex = 0; // Bool for each symbol, true if called directly. This allows us to implement @@ -360,7 +366,9 @@ assert(!dataSection); dataSection = §ion; } else if (section.Type == WASM_SEC_CUSTOM) { - customSections.emplace_back(make(section, this)); + auto *customSec = make(section, this); + customSec->discarded = isExcludedByComdat(customSec); + customSections.emplace_back(customSec); customSections.back()->setRelocations(section.Relocations); customSectionsByIndex[sectionIndex] = customSections.back(); } @@ -374,11 +382,6 @@ typeMap.resize(getWasmObj()->types().size()); typeIsUsed.resize(getWasmObj()->types().size(), false); - ArrayRef comdats = wasmObj->linkingData().Comdats; - for (StringRef comdat : comdats) { - bool isNew = ignoreComdats || symtab->addComdat(comdat); - keptComdats.push_back(isNew); - } // Populate `Segments`. for (const WasmSegment &s : wasmObj->dataSegments()) { @@ -487,6 +490,10 @@ case WASM_SYMBOL_TYPE_SECTION: { InputSection *section = customSectionsByIndex[sym.Info.ElementIndex]; assert(sym.isBindingLocal()); + // Need to return null if discarded here? data and func only do that when + // binding is not local. + if (section->discarded) + return nullptr; return make(flags, section, this); } case WASM_SYMBOL_TYPE_EVENT: {