[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