[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

llvm-svn: 322415
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 34cade9..257c948 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -170,6 +170,11 @@
   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 @@
   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 @@
     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;