[lld] r362769 - [WebAssembly] Fix for discarded init functions
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 6 23:00:46 PDT 2019
Author: sbc
Date: Thu Jun 6 23:00:46 2019
New Revision: 362769
URL: http://llvm.org/viewvc/llvm-project?rev=362769&view=rev
Log:
[WebAssembly] Fix for discarded init functions
When a function is excluded via comdat we shouldn't add it to the
final list of init functions.
Differential Revision: https://reviews.llvm.org/D62983
Modified:
lld/trunk/test/wasm/Inputs/comdat1.ll
lld/trunk/test/wasm/Inputs/comdat2.ll
lld/trunk/test/wasm/comdats.ll
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/MarkLive.cpp
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/Writer.cpp
Modified: lld/trunk/test/wasm/Inputs/comdat1.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/comdat1.ll?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/test/wasm/Inputs/comdat1.ll (original)
+++ lld/trunk/test/wasm/Inputs/comdat1.ll Thu Jun 6 23:00:46 2019
@@ -1,13 +1,22 @@
target triple = "wasm32-unknown-unknown"
-$inlineFn = comdat any
- at constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)
-define linkonce_odr i32 @inlineFn() comdat {
-entry:
+$foo = comdat any
+
+ at constantData = constant [3 x i8] c"abc", comdat($foo)
+
+define i32 @comdatFn() comdat($foo) {
ret i32 ptrtoint ([3 x i8]* @constantData to i32)
}
-define i32 @callInline1() {
-entry:
- ret i32 ptrtoint (i32 ()* @inlineFn to i32)
+define internal void @do_init() comdat($foo) {
+ ret void
+}
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void
+()*, i8* } { i32 65535, void ()* @do_init, i8* null }]
+
+; Everything above this is part of the `foo` comdat group
+
+define i32 @callComdatFn1() {
+ ret i32 ptrtoint (i32 ()* @comdatFn to i32)
}
Modified: lld/trunk/test/wasm/Inputs/comdat2.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/comdat2.ll?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/test/wasm/Inputs/comdat2.ll (original)
+++ lld/trunk/test/wasm/Inputs/comdat2.ll Thu Jun 6 23:00:46 2019
@@ -1,13 +1,22 @@
target triple = "wasm32-unknown-unknown"
-$inlineFn = comdat any
- at constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)
-define linkonce_odr i32 @inlineFn() comdat {
-entry:
+$foo = comdat any
+
+ at constantData = constant [3 x i8] c"abc", comdat($foo)
+
+define i32 @comdatFn() comdat($foo) {
ret i32 ptrtoint ([3 x i8]* @constantData to i32)
}
-define i32 @callInline2() {
-entry:
- ret i32 ptrtoint (i32 ()* @inlineFn to i32)
+define internal void @do_init() comdat($foo) {
+ ret void
+}
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void
+()*, i8* } { i32 65535, void ()* @do_init, i8* null }]
+
+; Everything above this is part of the `foo` comdat group
+
+define i32 @callComdatFn2() {
+ ret i32 ptrtoint (i32 ()* @comdatFn to i32)
}
Modified: lld/trunk/test/wasm/comdats.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/comdats.ll?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/test/wasm/comdats.ll (original)
+++ lld/trunk/test/wasm/comdats.ll Thu Jun 6 23:00:46 2019
@@ -6,11 +6,11 @@
target triple = "wasm32-unknown-unknown"
-declare i32 @inlineFn()
+declare i32 @comdatFn()
-define void @_start() local_unnamed_addr {
+define void @_start() {
entry:
- %call = call i32 @inlineFn()
+ %call = call i32 @comdatFn()
ret void
}
@@ -36,16 +36,16 @@ entry:
; CHECK-NEXT: - Name: _start
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 0
-; CHECK-NEXT: - Name: inlineFn
+; CHECK-NEXT: - Name: comdatFn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: constantData
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
-; CHECK-NEXT: - Name: callInline1
+; CHECK-NEXT: - Name: callComdatFn1
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: callInline2
+; CHECK-NEXT: - Name: callComdatFn2
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Type: ELEM
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Thu Jun 6 23:00:46 2019
@@ -64,9 +64,12 @@ public:
// If GC is disabled, all sections start out as live by default.
unsigned Live : 1;
+ // Signals the chunk was discarded by COMDAT handling.
+ unsigned Discarded : 1;
+
protected:
InputChunk(ObjFile *F, Kind K)
- : File(F), Live(!Config->GcSections), SectionKind(K) {}
+ : File(F), Live(!Config->GcSections), Discarded(false), SectionKind(K) {}
virtual ~InputChunk() = default;
virtual ArrayRef<uint8_t> data() const = 0;
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Thu Jun 6 23:00:46 2019
@@ -306,14 +306,17 @@ void ObjFile::parse(bool IgnoreComdats)
TypeIsUsed.resize(getWasmObj()->types().size(), false);
ArrayRef<StringRef> Comdats = WasmObj->linkingData().Comdats;
- for (unsigned I = 0; I < Comdats.size(); ++I) {
- bool IsNew = IgnoreComdats || Symtab->addComdat(Comdats[I]);
+ for (StringRef Comdat : Comdats) {
+ bool IsNew = IgnoreComdats || Symtab->addComdat(Comdat);
KeptComdats.push_back(IsNew);
}
// Populate `Segments`.
- for (const WasmSegment &S : WasmObj->dataSegments())
- Segments.emplace_back(make<InputSegment>(S, this));
+ for (const WasmSegment &S : WasmObj->dataSegments()) {
+ auto* Seg = make<InputSegment>(S, this);
+ Seg->Discarded = isExcludedByComdat(Seg);
+ Segments.emplace_back(Seg);
+ }
setRelocs(Segments, DataSection);
// Populate `Functions`.
@@ -322,9 +325,11 @@ void ObjFile::parse(bool IgnoreComdats)
ArrayRef<WasmSignature> Types = WasmObj->types();
Functions.reserve(Funcs.size());
- for (size_t I = 0, E = Funcs.size(); I != E; ++I)
- Functions.emplace_back(
- make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this));
+ for (size_t I = 0, E = Funcs.size(); I != E; ++I) {
+ auto* Func = make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this);
+ Func->Discarded = isExcludedByComdat(Func);
+ Functions.emplace_back(Func);
+ }
setRelocs(Functions, CodeSection);
// Populate `Globals`.
@@ -387,21 +392,16 @@ Symbol *ObjFile::createDefined(const Was
case WASM_SYMBOL_TYPE_FUNCTION: {
InputFunction *Func =
Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];
- if (isExcludedByComdat(Func)) {
- Func->Live = false;
+ if (Func->Discarded)
return nullptr;
- }
-
if (Sym.isBindingLocal())
return make<DefinedFunction>(Name, Flags, this, Func);
return Symtab->addDefinedFunction(Name, Flags, this, Func);
}
case WASM_SYMBOL_TYPE_DATA: {
InputSegment *Seg = Segments[Sym.Info.DataRef.Segment];
- if (isExcludedByComdat(Seg)) {
- Seg->Live = false;
+ if (Seg->Discarded)
return nullptr;
- }
uint32_t Offset = Sym.Info.DataRef.Offset;
uint32_t Size = Sym.Info.DataRef.Size;
@@ -439,12 +439,22 @@ Symbol *ObjFile::createUndefined(const W
switch (Sym.Info.Kind) {
case WASM_SYMBOL_TYPE_FUNCTION:
+ if (Sym.isBindingLocal())
+ return make<UndefinedFunction>(Name, Sym.Info.ImportName,
+ Sym.Info.ImportModule, Flags, this,
+ Sym.Signature, IsCalledDirectly);
return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName,
Sym.Info.ImportModule, Flags, this,
Sym.Signature, IsCalledDirectly);
case WASM_SYMBOL_TYPE_DATA:
+ if (Sym.isBindingLocal())
+ return make<UndefinedData>(Name, Flags, this);
return Symtab->addUndefinedData(Name, Flags, this);
case WASM_SYMBOL_TYPE_GLOBAL:
+ if (Sym.isBindingLocal())
+ return make<UndefinedGlobal>(Name, Sym.Info.ImportName,
+ Sym.Info.ImportModule, Flags, this,
+ Sym.GlobalType);
return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName,
Sym.Info.ImportModule, Flags, this,
Sym.GlobalType);
Modified: lld/trunk/wasm/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.cpp?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/MarkLive.cpp (original)
+++ lld/trunk/wasm/MarkLive.cpp Thu Jun 6 23:00:46 2019
@@ -52,8 +52,11 @@ void lld::wasm::markLive() {
if (Sym == WasmSym::CallCtors) {
for (const ObjFile *Obj : Symtab->ObjectFiles) {
const WasmLinkingData &L = Obj->getWasmObj()->linkingData();
- for (const WasmInitFunc &F : L.InitFunctions)
- Enqueue(Obj->getFunctionSymbol(F.Symbol));
+ for (const WasmInitFunc &F : L.InitFunctions) {
+ auto* InitSym = Obj->getFunctionSymbol(F.Symbol);
+ if (!InitSym->isDiscarded())
+ Enqueue(InitSym);
+ }
}
}
};
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Thu Jun 6 23:00:46 2019
@@ -63,6 +63,12 @@ InputChunk *Symbol::getChunk() const {
return nullptr;
}
+bool Symbol::isDiscarded() const {
+ if (InputChunk *C = getChunk())
+ return C->Discarded;
+ return false;
+}
+
bool Symbol::isLive() const {
if (auto *G = dyn_cast<DefinedGlobal>(this))
return G->Global->Live;
@@ -74,6 +80,7 @@ bool Symbol::isLive() const {
}
void Symbol::markLive() {
+ assert(!isDiscarded());
if (auto *G = dyn_cast<DefinedGlobal>(this))
G->Global->Live = true;
if (auto *E = dyn_cast<DefinedEvent>(this))
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Thu Jun 6 23:00:46 2019
@@ -69,6 +69,9 @@ public:
bool isWeak() const;
bool isHidden() const;
+ // Returns true if this symbol exists in a discarded (due to COMDAT) section
+ bool isDiscarded() const;
+
// True if this is an undefined weak symbol. This only works once
// all input files have been added.
bool isUndefWeak() const {
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=362769&r1=362768&r2=362769&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Thu Jun 6 23:00:46 2019
@@ -701,6 +701,9 @@ void Writer::calculateInitFunctions() {
const WasmLinkingData &L = File->getWasmObj()->linkingData();
for (const WasmInitFunc &F : L.InitFunctions) {
FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol);
+ // comdat exclusions can cause init functions be discarded.
+ if (Sym->isDiscarded())
+ continue;
assert(Sym->isLive());
if (*Sym->Signature != WasmSignature{{}, {}})
error("invalid signature for init func: " + toString(*Sym));
More information about the llvm-commits
mailing list