[lld] r322415 - [WebAssembly] Add COMDAT support
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 12 14:25:17 PST 2018
Author: sbc
Date: Fri Jan 12 14:25:17 2018
New Revision: 322415
URL: http://llvm.org/viewvc/llvm-project?rev=322415&view=rev
Log:
[WebAssembly] Add COMDAT support
See https://bugs.llvm.org/show_bug.cgi?id=35533, and D40844
Things covered:
* Removing duplicate data segments (as determined by COMDATs emitted
by the frontend)
* Removing duplicate globals and functions in COMDATs
* Checking that each time a COMDAT is seen it has the same symbols
as at other times (ie it's a stronger check than simply giving all
the symbols in the COMDAT weak linkage)
Patch by Nicholas Wilson!
Differential Revision: https://reviews.llvm.org/D40845
Added:
lld/trunk/test/wasm/Inputs/comdat1.ll
lld/trunk/test/wasm/Inputs/comdat2.ll
lld/trunk/test/wasm/comdats.ll
Modified:
lld/trunk/test/wasm/relocatable.ll
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
lld/trunk/wasm/SymbolTable.cpp
lld/trunk/wasm/SymbolTable.h
lld/trunk/wasm/Writer.cpp
Added: lld/trunk/test/wasm/Inputs/comdat1.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/comdat1.ll?rev=322415&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/comdat1.ll (added)
+++ lld/trunk/test/wasm/Inputs/comdat1.ll Fri Jan 12 14:25:17 2018
@@ -0,0 +1,11 @@
+$inlineFn = comdat any
+ at constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)
+define linkonce_odr i32 @inlineFn() comdat {
+entry:
+ ret i32 ptrtoint ([3 x i8]* @constantData to i32)
+}
+
+define i32 @callInline1() {
+entry:
+ ret i32 ptrtoint (i32 ()* @inlineFn to i32)
+}
Added: lld/trunk/test/wasm/Inputs/comdat2.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/comdat2.ll?rev=322415&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/comdat2.ll (added)
+++ lld/trunk/test/wasm/Inputs/comdat2.ll Fri Jan 12 14:25:17 2018
@@ -0,0 +1,11 @@
+$inlineFn = comdat any
+ at constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)
+define linkonce_odr i32 @inlineFn() comdat {
+entry:
+ ret i32 ptrtoint ([3 x i8]* @constantData to i32)
+}
+
+define i32 @callInline2() {
+entry:
+ ret i32 ptrtoint (i32 ()* @inlineFn to i32)
+}
Added: lld/trunk/test/wasm/comdats.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/comdats.ll?rev=322415&view=auto
==============================================================================
--- lld/trunk/test/wasm/comdats.ll (added)
+++ lld/trunk/test/wasm/comdats.ll Fri Jan 12 14:25:17 2018
@@ -0,0 +1,70 @@
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat1.ll -o %t1.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat2.ll -o %t2.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+declare i32 @inlineFn()
+
+define void @_start() local_unnamed_addr {
+entry:
+ %call = call i32 @inlineFn()
+ ret void
+}
+
+; CHECK: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: inlineFn
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: callInline1
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: callInline2
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
+; CHECK-NEXT: - Type: ELEM
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1
+; CHECK-NEXT: Functions: [ 1 ]
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 1081808080001A0B
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 4180888080000B
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 4181808080000B
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 4181808080000B
+; CHECK-NEXT: - Index: 4
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 0B
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Content: '616263'
Modified: lld/trunk/test/wasm/relocatable.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/relocatable.ll?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/test/wasm/relocatable.ll (original)
+++ lld/trunk/test/wasm/relocatable.ll Fri Jan 12 14:25:17 2018
@@ -17,6 +17,13 @@ declare i32 @foo_import() local_unnamed_
@func_addr2 = hidden global i32()* @foo_import, align 4
@data_addr1 = hidden global i64* @data_import, align 8
+$func_comdat = comdat any
+ at data_comdat = weak_odr constant [3 x i8] c"abc", comdat($func_comdat)
+define linkonce_odr i32 @func_comdat() comdat {
+entry:
+ ret i32 ptrtoint ([3 x i8]* @data_comdat to i32)
+}
+
; CHECK: --- !WASM
; CHECK-NEXT: FileHeader:
; CHECK-NEXT: Version: 0x00000001
@@ -49,7 +56,7 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: GlobalType: I32
; CHECK-NEXT: GlobalMutable: false
; CHECK-NEXT: - Type: FUNCTION
-; CHECK-NEXT: FunctionTypes: [ 0, 2 ]
+; CHECK-NEXT: FunctionTypes: [ 0, 2, 2 ]
; CHECK-NEXT: - Type: TABLE
; CHECK-NEXT: Tables:
; CHECK-NEXT: - ElemType: ANYFUNC
@@ -73,18 +80,24 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 8
+; CHECK-NEXT: Value: 20
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 12
+; CHECK-NEXT: Value: 8
; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 12
+; CHECK-NEXT: - Index: 5
+; CHECK-NEXT: Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 16
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
@@ -94,18 +107,24 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: - Name: my_func
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
+; CHECK-NEXT: - Name: func_comdat
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 4
; CHECK-NEXT: - Name: hello_str
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
-; CHECK-NEXT: - Name: func_addr1
+; CHECK-NEXT: - Name: data_comdat
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: func_addr2
+; CHECK-NEXT: - Name: func_addr1
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 3
-; CHECK-NEXT: - Name: data_addr1
+; CHECK-NEXT: - Name: func_addr2
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 4
+; CHECK-NEXT: - Name: data_addr1
+; CHECK-NEXT: Kind: GLOBAL
+; CHECK-NEXT: Index: 5
; CHECK-NEXT: - Type: ELEM
; CHECK-NEXT: Segments:
; CHECK-NEXT: - Offset:
@@ -123,6 +142,9 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
; CHECK-NEXT: Index: 1
; CHECK-NEXT: Offset: 0x00000013
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: Offset: 0x0000001F
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Locals:
@@ -130,6 +152,9 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1081808080001A41010B
+; CHECK-NEXT: - Index: 4
+; CHECK-NEXT: Locals:
+; CHECK-NEXT: Body: 4194808080000B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Relocations:
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
@@ -166,26 +191,43 @@ declare i32 @foo_import() local_unnamed_
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 16
; CHECK-NEXT: Content: '00000000'
+; CHECK-NEXT: - SectionOffset: 45
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 20
+; CHECK-NEXT: Content: '616263'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
-; CHECK-NEXT: DataSize: 20
+; CHECK-NEXT: DataSize: 23
; CHECK-NEXT: SegmentInfo:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .rodata.hello_str
; CHECK-NEXT: Alignment: 1
-; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: Flags: [ ]
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: .data.func_addr1
; CHECK-NEXT: Alignment: 4
-; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: Flags: [ ]
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Name: .data.func_addr2
; CHECK-NEXT: Alignment: 4
-; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: Flags: [ ]
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: .data.data_addr1
; CHECK-NEXT: Alignment: 8
-; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Index: 4
+; CHECK-NEXT: Name: .rodata.data_comdat
+; CHECK-NEXT: Alignment: 1
+; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: Comdats:
+; CHECK-NEXT: - Name: func_comdat
+; CHECK-NEXT: Entries:
+; CHECK-NEXT: - Kind: FUNCTION
+; CHECK-NEXT: Index: 4
+; CHECK-NEXT: - Kind: DATA
+; CHECK-NEXT: Index: 4
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
; CHECK-NEXT: FunctionNames:
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Fri Jan 12 14:25:17 2018
@@ -47,6 +47,9 @@ public:
uint32_t getOutputOffset() const { return OutputOffset; }
+ virtual StringRef getComdat() const = 0;
+
+ bool Discarded = false;
std::vector<OutputRelocation> OutRelocations;
protected:
@@ -93,6 +96,7 @@ public:
uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; }
uint32_t endVA() const { return startVA() + getSize(); }
StringRef getName() const { return Segment.Data.Name; }
+ StringRef getComdat() const override { return Segment.Data.Comdat; }
int32_t OutputSegmentOffset = 0;
@@ -100,6 +104,7 @@ protected:
uint32_t getInputSectionOffset() const override {
return Segment.SectionOffset;
}
+
const WasmSegment &Segment;
const OutputSegment *OutputSeg = nullptr;
};
@@ -116,7 +121,7 @@ public:
const uint8_t *getData() const override {
return File->CodeSection->Content.data() + getInputSectionOffset();
}
-
+ StringRef getComdat() const override { return Function->Comdat; }
uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
bool hasOutputIndex() const { return OutputIndex.hasValue(); };
void setOutputIndex(uint32_t Index);
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Fri Jan 12 14:25:17 2018
@@ -170,6 +170,11 @@ InputFunction *ObjFile::getFunction(cons
return Functions[FunctionIndex];
}
+bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {
+ StringRef Comdat = Chunk->getComdat();
+ return !Comdat.empty() && Symtab->findComdat(Comdat) != this;
+}
+
void ObjFile::initializeSymbols() {
Symbols.reserve(WasmObj->getNumberOfSymbols());
@@ -187,15 +192,23 @@ void ObjFile::initializeSymbols() {
FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size());
GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size());
+ ArrayRef<WasmFunction> Funcs = WasmObj->functions();
+ ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
+ ArrayRef<WasmSignature> Types = WasmObj->types();
+ ArrayRef<WasmGlobal> Globals = WasmObj->globals();
+
+ for (const auto &C : WasmObj->comdats())
+ Symtab->addComdat(C, this);
+
+ FunctionSymbols.resize(NumFunctionImports + Funcs.size());
+ GlobalSymbols.resize(NumGlobalImports + Globals.size());
+
for (const WasmSegment &S : WasmObj->dataSegments()) {
InputSegment *Seg = make<InputSegment>(S, this);
Seg->copyRelocations(*DataSection);
Segments.emplace_back(Seg);
}
- ArrayRef<WasmFunction> Funcs = WasmObj->functions();
- ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
- ArrayRef<WasmSignature> Types = WasmObj->types();
for (size_t I = 0; I < Funcs.size(); ++I) {
const WasmFunction &Func = Funcs[I];
const WasmSignature &Sig = Types[FuncTypes[I]];
@@ -210,21 +223,35 @@ void ObjFile::initializeSymbols() {
const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
Symbol *S;
switch (WasmSym.Type) {
+ case WasmSymbol::SymbolType::FUNCTION_EXPORT: {
+ InputFunction *Function = getFunction(WasmSym);
+ if (!isExcludedByComdat(Function)) {
+ S = createDefined(WasmSym, Symbol::Kind::DefinedFunctionKind, nullptr,
+ Function);
+ break;
+ } else {
+ Function->Discarded = true;
+ LLVM_FALLTHROUGH; // Exclude function, and add the symbol as undefined
+ }
+ }
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
S = createUndefined(WasmSym, Symbol::Kind::UndefinedFunctionKind,
getFunctionSig(WasmSym));
break;
+ case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
+ InputSegment *Segment = getSegment(WasmSym);
+ if (!isExcludedByComdat(Segment)) {
+ S = createDefined(WasmSym, Symbol::Kind::DefinedGlobalKind,
+ Segment, nullptr, getGlobalValue(WasmSym));
+ break;
+ } else {
+ Segment->Discarded = true;
+ LLVM_FALLTHROUGH; // Exclude global, and add the symbol as undefined
+ }
+ }
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
S = createUndefined(WasmSym, Symbol::Kind::UndefinedGlobalKind);
break;
- case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- S = createDefined(WasmSym, Symbol::Kind::DefinedGlobalKind,
- getSegment(WasmSym), nullptr, getGlobalValue(WasmSym));
- break;
- case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- S = createDefined(WasmSym, Symbol::Kind::DefinedFunctionKind, nullptr,
- getFunction(WasmSym));
- break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
// These are for debugging only, no need to create linker symbols for them
continue;
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Fri Jan 12 14:25:17 2018
@@ -33,6 +33,7 @@ using llvm::wasm::WasmRelocation;
namespace lld {
namespace wasm {
+class InputChunk;
class InputFunction;
class InputSegment;
@@ -122,6 +123,7 @@ private:
const WasmSignature *getFunctionSig(const WasmSymbol &Sym) const;
uint32_t getGlobalValue(const WasmSymbol &Sym) const;
InputFunction *getFunction(const WasmSymbol &Sym) const;
+ bool isExcludedByComdat(InputChunk *Chunk) const;
// List of all symbols referenced or defined by this file.
std::vector<Symbol *> Symbols;
Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Fri Jan 12 14:25:17 2018
@@ -237,3 +237,19 @@ void SymbolTable::addLazy(ArchiveFile *F
F->addMember(Sym);
}
}
+
+bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
+ DEBUG(dbgs() << "addComdat: " << Name << "\n");
+ ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
+ if (File) {
+ DEBUG(dbgs() << "COMDAT already defined\n");
+ return false;
+ }
+ File = F;
+ return true;
+}
+
+ObjFile *SymbolTable::findComdat(StringRef Name) const {
+ auto It = ComdatMap.find(CachedHashStringRef(Name));
+ return It == ComdatMap.end() ? nullptr : It->second;
+}
Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Fri Jan 12 14:25:17 2018
@@ -47,6 +47,7 @@ public:
ArrayRef<Symbol *> getSymbols() const { return SymVector; }
Symbol *find(StringRef Name);
+ ObjFile *findComdat(StringRef Name) const;
Symbol *addDefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags,
InputFile *F, const InputSegment *Segment = nullptr,
@@ -58,10 +59,12 @@ public:
Symbol *addDefinedFunction(StringRef Name, const WasmSignature *Type,
uint32_t Flags);
void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
+ bool addComdat(StringRef Name, ObjFile *);
private:
std::pair<Symbol *, bool> insert(StringRef Name);
+ llvm::DenseMap<llvm::CachedHashStringRef, ObjFile *> ComdatMap;
llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap;
std::vector<Symbol *> SymVector;
};
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=322415&r1=322414&r2=322415&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Fri Jan 12 14:25:17 2018
@@ -25,6 +25,7 @@
#include "llvm/Support/LEB128.h"
#include <cstdarg>
+#include <map>
#define DEBUG_TYPE "lld"
@@ -427,6 +428,42 @@ void Writer::createLinkingSection() {
SubSection.finalizeContents();
SubSection.writeToStream(OS);
}
+
+ struct ComdatEntry { unsigned Kind; uint32_t Index; };
+ std::map<StringRef,std::vector<ComdatEntry>> Comdats;
+
+ for (const InputFunction *F : DefinedFunctions) {
+ StringRef Comdat = F->getComdat();
+ if (!Comdat.empty())
+ Comdats[Comdat].emplace_back(
+ ComdatEntry{WASM_COMDAT_FUNCTION, F->getOutputIndex()});
+ }
+ for (uint32_t I = 0; I < Segments.size(); ++I) {
+ const auto &InputSegments = Segments[I]->InputSegments;
+ if (InputSegments.empty())
+ continue;
+ StringRef Comdat = InputSegments[0]->getComdat();
+ for (const InputSegment *IS : InputSegments)
+ assert(IS->getComdat() == Comdat);
+ if (!Comdat.empty())
+ Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
+ }
+
+ if (!Comdats.empty()) {
+ SubSection SubSection(WASM_COMDAT_INFO);
+ writeUleb128(SubSection.getStream(), Comdats.size(), "num comdats");
+ for (const auto &C : Comdats) {
+ writeStr(SubSection.getStream(), C.first, "comdat name");
+ writeUleb128(SubSection.getStream(), 0, "comdat flags"); // flags for future use
+ writeUleb128(SubSection.getStream(), C.second.size(), "num entries");
+ for (const ComdatEntry &Entry : C.second) {
+ writeUleb128(SubSection.getStream(), Entry.Kind, "entry kind");
+ writeUleb128(SubSection.getStream(), Entry.Index, "entry index");
+ }
+ }
+ SubSection.finalizeContents();
+ SubSection.writeToStream(OS);
+ }
}
// Create the custom "name" section containing debug symbol names.
@@ -654,6 +691,8 @@ void Writer::assignIndexes() {
for (ObjFile *File : Symtab->ObjectFiles) {
DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
for (InputFunction *Func : File->Functions) {
+ if (Func->Discarded)
+ continue;
DefinedFunctions.emplace_back(Func);
Func->setOutputIndex(FunctionIndex++);
}
@@ -689,6 +728,8 @@ static StringRef getOutputDataSegmentNam
void Writer::createOutputSegments() {
for (ObjFile *File : Symtab->ObjectFiles) {
for (InputSegment *Segment : File->Segments) {
+ if (Segment->Discarded)
+ continue;
StringRef Name = getOutputDataSegmentName(Segment->getName());
OutputSegment *&S = SegmentMap[Name];
if (S == nullptr) {
More information about the llvm-commits
mailing list