[WebAssembly] Use a Symbol class heirarchy. NFC.

This brings wasm into line with ELF and COFF in terms of
symbol types are represented.

Differential Revision: https://reviews.llvm.org/D43112

llvm-svn: 325150
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index e14ebcf..a42cce7 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -66,7 +66,7 @@
   Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
   if (Sym)
     return {Sym, false};
-  Sym = make<Symbol>(Name, false);
+  Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
   SymVector.emplace_back(Sym);
   return {Sym, true};
 }
@@ -80,13 +80,10 @@
 // Check the type of new symbol matches that of the symbol is replacing.
 // For functions this can also involve verifying that the signatures match.
 static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
-                             Symbol::Kind Kind, const WasmSignature *NewSig) {
+                             bool NewIsFunction, const WasmSignature *NewSig) {
   if (Existing.isLazy())
     return;
 
-  bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind ||
-                       Kind == Symbol::Kind::DefinedFunctionKind;
-
   // First check the symbol types match (i.e. either both are function
   // symbols or both are data symbols).
   if (Existing.isFunction() != NewIsFunction) {
@@ -98,105 +95,102 @@
   }
 
   // For function symbols, optionally check the function signature matches too.
-  if (!NewIsFunction || !Config->CheckSignatures)
+  auto *ExistingFunc = dyn_cast<FunctionSymbol>(&Existing);
+  if (!ExistingFunc || !Config->CheckSignatures)
     return;
+
   // Skip the signature check if the existing function has no signature (e.g.
   // if it is an undefined symbol generated by --undefined command line flag).
-  if (!Existing.hasFunctionType())
+  if (!ExistingFunc->hasFunctionType())
     return;
 
-  DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
+  DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n");
   assert(NewSig);
 
-  const WasmSignature &OldSig = Existing.getFunctionType();
+  const WasmSignature &OldSig = ExistingFunc->getFunctionType();
   if (*NewSig == OldSig)
     return;
 
-  error("function signature mismatch: " + Existing.getName() +
+  error("function signature mismatch: " + ExistingFunc->getName() +
         "\n>>> defined as " + toString(OldSig) + " in " +
-        toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) +
-        " in " + F.getName());
+        toString(ExistingFunc->getFile()) + "\n>>> defined as " +
+        toString(*NewSig) + " in " + F.getName());
 }
 
 static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
-                             Symbol::Kind Kind, const InputChunk *Chunk) {
+                             bool IsFunction, const InputChunk *Chunk) {
   const WasmSignature *Sig = nullptr;
   if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
     Sig = &F->Signature;
-  return checkSymbolTypes(Existing, F, Kind, Sig);
+  return checkSymbolTypes(Existing, F, IsFunction, Sig);
 }
 
-Symbol *SymbolTable::addSyntheticFunction(StringRef Name,
-                                          const WasmSignature *Type,
-                                          uint32_t Flags) {
+DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
+                                                   const WasmSignature *Type,
+                                                   uint32_t Flags) {
   DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
   assert(WasInserted);
-  S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
-  S->setFunctionType(Type);
-  return S;
+  return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
 }
 
-Symbol *SymbolTable::addSyntheticGlobal(StringRef Name) {
+DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags) {
   DEBUG(dbgs() << "addSyntheticGlobal: " << Name << "\n");
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
   assert(WasInserted);
-  S->update(Symbol::DefinedGlobalKind);
-  return S;
+  return replaceSymbol<DefinedGlobal>(S, Name, Flags);
 }
 
-Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
-                                uint32_t Flags, InputFile *F, InputChunk *Chunk,
+Symbol *SymbolTable::addDefined(bool IsFunction, StringRef Name, uint32_t Flags,
+                                InputFile *F, InputChunk *Chunk,
                                 uint32_t Address) {
-  DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
+  if (IsFunction)
+    DEBUG(dbgs() << "addDefined: func:" << Name << "\n");
+  else
+    DEBUG(dbgs() << "addDefined: global:" << Name << " addr:" << Address
+                 << "\n");
   Symbol *S;
   bool WasInserted;
+  bool Replace = false;
+  bool CheckTypes = false;
 
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
-    S->update(Kind, F, Flags, Chunk, Address);
+    Replace = true;
   } else if (S->isLazy()) {
-    // The existing symbol is lazy. Replace it without checking types since
+    // Existing symbol is lazy. Replace it without checking types since
     // lazy symbols don't have any type information.
     DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
-    S->update(Kind, F, Flags, Chunk, Address);
+    Replace = true;
   } else if (!S->isDefined()) {
-    // The existing symbol table entry is undefined. The new symbol replaces
-    // it, after checking the type matches
+    // Existing symbol is undefined: replace it, while check types.
     DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
-    checkSymbolTypes(*S, *F, Kind, Chunk);
-    S->update(Kind, F, Flags, Chunk, Address);
+    Replace = true;
+    CheckTypes = true;
   } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
     // the new symbol is weak we can ignore it
     DEBUG(dbgs() << "existing symbol takes precedence\n");
   } else if (S->isWeak()) {
-    // the new symbol is not weak and the existing symbol is, so we replace
-    // it
+    // the existing symbol is, so we replace it
     DEBUG(dbgs() << "replacing existing weak symbol\n");
-    checkSymbolTypes(*S, *F, Kind, Chunk);
-    S->update(Kind, F, Flags, Chunk, Address);
+    Replace = true;
+    CheckTypes = true;
   } else {
     // neither symbol is week. They conflict.
     reportDuplicate(S, F);
   }
-  return S;
-}
 
-Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
-                                          const WasmSignature *Type) {
-  DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n");
-  Symbol *S;
-  bool WasInserted;
-  std::tie(S, WasInserted) = insert(Name);
-  if (WasInserted) {
-    S->update(Symbol::UndefinedFunctionKind);
-    S->setFunctionType(Type);
-  } else if (!S->isFunction()) {
-    error("symbol type mismatch: " + Name);
+  if (Replace) {
+    if (CheckTypes)
+      checkSymbolTypes(*S, *F, IsFunction, Chunk);
+    if (IsFunction)
+      replaceSymbol<DefinedFunction>(S, Name, Flags, F, Chunk);
+    else
+      replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Chunk, Address);
   }
   return S;
 }
@@ -208,17 +202,19 @@
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
+  bool IsFunction = Kind == Symbol::UndefinedFunctionKind;
   if (WasInserted) {
-    S->update(Kind, F, Flags);
-    if (Type)
-      S->setFunctionType(Type);
-  } else if (S->isLazy()) {
+    if (IsFunction)
+      replaceSymbol<UndefinedFunction>(S, Name, Flags, F, Type);
+    else
+      replaceSymbol<UndefinedGlobal>(S, Name, Flags, F);
+  } else if (auto *LazySym = dyn_cast<LazySymbol>(S)) {
     DEBUG(dbgs() << "resolved by existing lazy\n");
-    auto *AF = cast<ArchiveFile>(S->getFile());
-    AF->addMember(&S->getArchiveSymbol());
+    auto *AF = cast<ArchiveFile>(LazySym->getFile());
+    AF->addMember(&LazySym->getArchiveSymbol());
   } else if (S->isDefined()) {
     DEBUG(dbgs() << "resolved by existing\n");
-    checkSymbolTypes(*S, *F, Kind, Type);
+    checkSymbolTypes(*S, *F, IsFunction, Type);
   }
   return S;
 }
@@ -230,8 +226,7 @@
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
-    S->update(Symbol::LazyKind, F);
-    S->setArchiveSymbol(*Sym);
+    replaceSymbol<LazySymbol>(S, Name, F, *Sym);
   } else if (S->isUndefined()) {
     // There is an existing undefined symbol.  The can load from the
     // archive.