[WebAssembly] Seal imports section before counting imports

Summary:
Before we can assign entries in the function of global index space
we need to know the total number of function and global imports
respectively.

To avoid programmer error this change seals that imports section before
assigned function and global index space.  Any attempt to add an import
after the section is sealed will assert.

The lack this such as check caused  https://reviews.llvm.org/D61876
to be reverted.  I'm also trying to craft a test case the this
failure.

Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits

Tags: #llvm

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

git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@361470 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/wasm/SyntheticSections.cpp b/wasm/SyntheticSections.cpp
index 6dd68f6..198e6db 100644
--- a/wasm/SyntheticSections.cpp
+++ b/wasm/SyntheticSections.cpp
@@ -92,6 +92,7 @@
 }
 
 uint32_t ImportSection::numImports() const {
+  assert(IsSealed);
   uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size();
   if (Config->ImportMemory)
     ++NumImports;
@@ -101,6 +102,7 @@
 }
 
 void ImportSection::addGOTEntry(Symbol *Sym) {
+  assert(!IsSealed);
   if (Sym->hasGOTIndex())
     return;
   Sym->setGOTIndex(NumImportedGlobals++);
@@ -108,6 +110,7 @@
 }
 
 void ImportSection::addImport(Symbol *Sym) {
+  assert(!IsSealed);
   ImportedSymbols.emplace_back(Sym);
   if (auto *F = dyn_cast<FunctionSymbol>(Sym))
     F->setFunctionIndex(NumImportedFunctions++);
@@ -202,7 +205,7 @@
   if (!Func->Live)
     return;
   uint32_t FunctionIndex =
-      Out.ImportSec->NumImportedFunctions + InputFunctions.size();
+      Out.ImportSec->numImportedFunctions() + InputFunctions.size();
   InputFunctions.emplace_back(Func);
   Func->setFunctionIndex(FunctionIndex);
 }
@@ -251,7 +254,7 @@
   if (!Global->Live)
     return;
   uint32_t GlobalIndex =
-      Out.ImportSec->NumImportedGlobals + InputGlobals.size();
+      Out.ImportSec->numImportedGlobals() + InputGlobals.size();
   LLVM_DEBUG(dbgs() << "addGlobal: " << GlobalIndex << "\n");
   Global->setGlobalIndex(GlobalIndex);
   Out.GlobalSec->InputGlobals.push_back(Global);
@@ -270,7 +273,7 @@
 void EventSection::addEvent(InputEvent *Event) {
   if (!Event->Live)
     return;
-  uint32_t EventIndex = Out.ImportSec->NumImportedEvents + InputEvents.size();
+  uint32_t EventIndex = Out.ImportSec->numImportedEvents() + InputEvents.size();
   LLVM_DEBUG(dbgs() << "addEvent: " << EventIndex << "\n");
   Event->setEventIndex(EventIndex);
   InputEvents.push_back(Event);
@@ -457,7 +460,7 @@
 }
 
 unsigned NameSection::numNames() const {
-  unsigned NumNames = Out.ImportSec->NumImportedFunctions;
+  unsigned NumNames = Out.ImportSec->numImportedFunctions();
   for (const InputFunction *F : Out.FunctionSec->InputFunctions)
     if (!F->getName().empty() || !F->getDebugName().empty())
       ++NumNames;
diff --git a/wasm/SyntheticSections.h b/wasm/SyntheticSections.h
index c897132..ccd6632 100644
--- a/wasm/SyntheticSections.h
+++ b/wasm/SyntheticSections.h
@@ -101,14 +101,28 @@
   void writeBody() override;
   void addImport(Symbol *Sym);
   void addGOTEntry(Symbol *Sym);
+  void seal() { IsSealed = true; }
   uint32_t numImports() const;
+  uint32_t numImportedGlobals() const {
+    assert(IsSealed);
+    return NumImportedGlobals;
+  }
+  uint32_t numImportedFunctions() const {
+    assert(IsSealed);
+    return NumImportedFunctions;
+  }
+  uint32_t numImportedEvents() const {
+    assert(IsSealed);
+    return NumImportedEvents;
+  }
 
-  unsigned NumImportedGlobals = 0;
-  unsigned NumImportedFunctions = 0;
-  unsigned NumImportedEvents = 0;
   std::vector<const Symbol *> ImportedSymbols;
 
 protected:
+  bool IsSealed = false;
+  unsigned NumImportedGlobals = 0;
+  unsigned NumImportedFunctions = 0;
+  unsigned NumImportedEvents = 0;
   std::vector<const Symbol *> GOTSymbols;
 };
 
diff --git a/wasm/Writer.cpp b/wasm/Writer.cpp
index eb567ec..01dbd82 100644
--- a/wasm/Writer.cpp
+++ b/wasm/Writer.cpp
@@ -439,7 +439,7 @@
         WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0});
 
   unsigned FakeGlobalIndex =
-      Out.ImportSec->NumImportedGlobals + Out.GlobalSec->InputGlobals.size();
+      Out.ImportSec->numImportedGlobals() + Out.GlobalSec->InputGlobals.size();
 
   for (Symbol *Sym : Symtab->getSymbols()) {
     if (!Sym->isExported())
@@ -532,7 +532,9 @@
 }
 
 void Writer::assignIndexes() {
-  assert(Out.FunctionSec->InputFunctions.empty());
+  // Seal the import section, since other index spaces such as function and
+  // global are effected by the number of imports.
+  Out.ImportSec->seal();
 
   for (InputFunction *Func : Symtab->SyntheticFunctions)
     Out.FunctionSec->addFunction(Func);
@@ -543,8 +545,6 @@
       Out.FunctionSec->addFunction(Func);
   }
 
-  scanRelocations();
-
   for (InputGlobal *Global : Symtab->SyntheticGlobals)
     Out.GlobalSec->addGlobal(Global);
 
@@ -724,6 +724,8 @@
   populateTargetFeatures();
   log("-- calculateImports");
   calculateImports();
+  log("-- scanRelocations");
+  scanRelocations();
   log("-- assignIndexes");
   assignIndexes();
   log("-- calculateInitFunctions");
@@ -750,9 +752,9 @@
     log("Defined Functions: " + Twine(Out.FunctionSec->InputFunctions.size()));
     log("Defined Globals  : " + Twine(Out.GlobalSec->InputGlobals.size()));
     log("Defined Events   : " + Twine(Out.EventSec->InputEvents.size()));
-    log("Function Imports : " + Twine(Out.ImportSec->NumImportedFunctions));
-    log("Global Imports   : " + Twine(Out.ImportSec->NumImportedGlobals));
-    log("Event Imports    : " + Twine(Out.ImportSec->NumImportedEvents));
+    log("Function Imports : " + Twine(Out.ImportSec->numImportedFunctions()));
+    log("Global Imports   : " + Twine(Out.ImportSec->numImportedGlobals()));
+    log("Event Imports    : " + Twine(Out.ImportSec->numImportedEvents()));
     for (ObjFile *File : Symtab->ObjectFiles)
       File->dumpInfo();
   }