[lld] r348703 - [WebAssembly] Add support for the event section

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 7 22:17:43 PST 2018


Author: aheejin
Date: Fri Dec  7 22:17:43 2018
New Revision: 348703

URL: http://llvm.org/viewvc/llvm-project?rev=348703&view=rev
Log:
[WebAssembly] Add support for the event section

Summary:
This adds support for the 'event section' specified in the exception
handling proposal.

Wasm exception handling binary model spec:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md#changes-to-the-binary-model

Reviewers: sbc100, ruiu

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

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

Added:
    lld/trunk/test/wasm/Inputs/event-section1.ll
    lld/trunk/test/wasm/Inputs/event-section2.ll
    lld/trunk/test/wasm/event-section.ll
    lld/trunk/wasm/InputEvent.h
Modified:
    lld/trunk/include/lld/Common/LLVM.h
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/InputChunks.cpp
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/InputFiles.h
    lld/trunk/wasm/LTO.cpp
    lld/trunk/wasm/MarkLive.cpp
    lld/trunk/wasm/OutputSections.cpp
    lld/trunk/wasm/SymbolTable.cpp
    lld/trunk/wasm/SymbolTable.h
    lld/trunk/wasm/Symbols.cpp
    lld/trunk/wasm/Symbols.h
    lld/trunk/wasm/Writer.cpp
    lld/trunk/wasm/WriterUtils.cpp
    lld/trunk/wasm/WriterUtils.h

Modified: lld/trunk/include/lld/Common/LLVM.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Common/LLVM.h?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/include/lld/Common/LLVM.h (original)
+++ lld/trunk/include/lld/Common/LLVM.h Fri Dec  7 22:17:43 2018
@@ -43,6 +43,8 @@ class WasmSymbol;
 } // namespace object
 
 namespace wasm {
+struct WasmEvent;
+struct WasmEventType;
 struct WasmFunction;
 struct WasmGlobal;
 struct WasmGlobalType;
@@ -76,6 +78,8 @@ using llvm::object::WasmObjectFile;
 using llvm::object::WasmSection;
 using llvm::object::WasmSegment;
 using llvm::object::WasmSymbol;
+using llvm::wasm::WasmEvent;
+using llvm::wasm::WasmEventType;
 using llvm::wasm::WasmFunction;
 using llvm::wasm::WasmGlobal;
 using llvm::wasm::WasmGlobalType;

Added: lld/trunk/test/wasm/Inputs/event-section1.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/event-section1.ll?rev=348703&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/event-section1.ll (added)
+++ lld/trunk/test/wasm/Inputs/event-section1.ll Fri Dec  7 22:17:43 2018
@@ -0,0 +1,9 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+declare void @llvm.wasm.throw(i32, i8*)
+
+define void @foo(i8* %p) {
+  call void @llvm.wasm.throw(i32 0, i8* %p)
+  ret void
+}

Added: lld/trunk/test/wasm/Inputs/event-section2.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/event-section2.ll?rev=348703&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/event-section2.ll (added)
+++ lld/trunk/test/wasm/Inputs/event-section2.ll Fri Dec  7 22:17:43 2018
@@ -0,0 +1,9 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+declare void @llvm.wasm.throw(i32, i8*)
+
+define void @bar(i8* %p) {
+  call void @llvm.wasm.throw(i32 0, i8* %p)
+  ret void
+}

Added: lld/trunk/test/wasm/event-section.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/event-section.ll?rev=348703&view=auto
==============================================================================
--- lld/trunk/test/wasm/event-section.ll (added)
+++ lld/trunk/test/wasm/event-section.ll Fri Dec  7 22:17:43 2018
@@ -0,0 +1,34 @@
+; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %p/Inputs/event-section1.ll -o %t1.o
+; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %p/Inputs/event-section2.ll -o %t2.o
+; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o %t.o
+; RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+declare void @foo(i8*)
+declare void @bar(i8*)
+
+define void @_start() {
+  call void @foo(i8* null)
+  call void @bar(i8* null)
+  ret void
+}
+
+; CHECK:      Sections:
+; CHECK-NEXT:   - Type:            TYPE
+; CHECK-NEXT:     Signatures:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ParamTypes:      []
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:           - I32
+
+; CHECK:        - Type:            EVENT
+; CHECK-NEXT:     Events:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Attribute:       0
+; CHECK-NEXT:         SigIndex:        1

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Fri Dec  7 22:17:43 2018
@@ -306,8 +306,8 @@ static void handleWeakUndefines() {
 
     // It is possible for undefined functions not to have a signature (eg. if
     // added via "--undefined"), but weak undefined ones do have a signature.
-    assert(FuncSym->FunctionType);
-    const WasmSignature &Sig = *FuncSym->FunctionType;
+    assert(FuncSym->Signature);
+    const WasmSignature &Sig = *FuncSym->Signature;
 
     // Add a synthetic dummy for weak undefined functions.  These dummies will
     // be GC'd if not used as the target of any "call" instructions.

Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Fri Dec  7 22:17:43 2018
@@ -55,6 +55,7 @@ void InputChunk::verifyRelocTargets() co
     case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
     case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+    case R_WEBASSEMBLY_EVENT_INDEX_LEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
       ExistingValue = decodeULEB128(Loc, &BytesRead);
       break;
@@ -111,6 +112,7 @@ void InputChunk::writeTo(uint8_t *Buf) c
     case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
     case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+    case R_WEBASSEMBLY_EVENT_INDEX_LEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
       encodeULEB128(Value, Loc, 5);
       break;
@@ -180,6 +182,7 @@ static unsigned writeCompressedReloc(uin
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+  case R_WEBASSEMBLY_EVENT_INDEX_LEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
     return encodeULEB128(Value, Buf);
   case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
@@ -195,6 +198,7 @@ static unsigned getRelocWidthPadded(cons
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+  case R_WEBASSEMBLY_EVENT_INDEX_LEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
   case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:

Added: lld/trunk/wasm/InputEvent.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputEvent.h?rev=348703&view=auto
==============================================================================
--- lld/trunk/wasm/InputEvent.h (added)
+++ lld/trunk/wasm/InputEvent.h Fri Dec  7 22:17:43 2018
@@ -0,0 +1,63 @@
+//===- InputEvent.h ---------------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Wasm events are features that suspend the current execution and transfer the
+// control flow to a corresponding handler. Currently the only supported event
+// kind is exceptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_WASM_INPUT_EVENT_H
+#define LLD_WASM_INPUT_EVENT_H
+
+#include "Config.h"
+#include "InputFiles.h"
+#include "WriterUtils.h"
+#include "lld/Common/ErrorHandler.h"
+#include "llvm/Object/Wasm.h"
+
+namespace lld {
+namespace wasm {
+
+// Represents a single Wasm Event within an input file. These are combined to
+// form the final EVENTS section.
+class InputEvent {
+public:
+  InputEvent(const WasmSignature &S, const WasmEvent &E, ObjFile *F)
+      : File(F), Event(E), Signature(S), Live(!Config->GcSections) {}
+
+  StringRef getName() const { return Event.SymbolName; }
+  const WasmEventType &getType() const { return Event.Type; }
+
+  uint32_t getEventIndex() const { return EventIndex.getValue(); }
+  bool hasEventIndex() const { return EventIndex.hasValue(); }
+  void setEventIndex(uint32_t Index) {
+    assert(!hasEventIndex());
+    EventIndex = Index;
+  }
+
+  ObjFile *File;
+  WasmEvent Event;
+  const WasmSignature &Signature;
+
+  bool Live = false;
+
+protected:
+  llvm::Optional<uint32_t> EventIndex;
+};
+
+} // namespace wasm
+
+inline std::string toString(const wasm::InputEvent *E) {
+  return (toString(E->File) + ":(" + E->getName() + ")").str();
+}
+
+} // namespace lld
+
+#endif // LLD_WASM_INPUT_EVENT_H

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Fri Dec  7 22:17:43 2018
@@ -10,6 +10,7 @@
 #include "InputFiles.h"
 #include "Config.h"
 #include "InputChunks.h"
+#include "InputEvent.h"
 #include "InputGlobal.h"
 #include "SymbolTable.h"
 #include "lld/Common/ErrorHandler.h"
@@ -57,7 +58,8 @@ void ObjFile::dumpInfo() const {
   log("info for: " + getName() +
       "\n              Symbols : " + Twine(Symbols.size()) +
       "\n     Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) +
-      "\n       Global Imports : " + Twine(WasmObj->getNumImportedGlobals()));
+      "\n       Global Imports : " + Twine(WasmObj->getNumImportedGlobals()) +
+      "\n        Event Imports : " + Twine(WasmObj->getNumImportedEvents()));
 }
 
 // Relocations contain either symbol or type indices.  This function takes a
@@ -119,7 +121,8 @@ uint32_t ObjFile::calcExpectedValue(cons
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     return Reloc.Index;
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
-  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
+  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+  case R_WEBASSEMBLY_EVENT_INDEX_LEB: {
     const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];
     return Sym.Info.ElementIndex;
   }
@@ -147,6 +150,8 @@ uint32_t ObjFile::calcNewValue(const Was
     return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     return getGlobalSymbol(Reloc.Index)->getGlobalIndex();
+  case R_WEBASSEMBLY_EVENT_INDEX_LEB:
+    return getEventSymbol(Reloc.Index)->getEventIndex();
   case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
     if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {
       if (Sym->isLive())
@@ -267,6 +272,10 @@ void ObjFile::parse() {
   for (const WasmGlobal &G : WasmObj->globals())
     Globals.emplace_back(make<InputGlobal>(G, this));
 
+  // Populate `Events`.
+  for (const WasmEvent &E : WasmObj->events())
+    Events.emplace_back(make<InputEvent>(Types[E.Type.SigIndex], E, this));
+
   // Populate `Symbols` based on the WasmSymbols in the object.
   Symbols.reserve(WasmObj->getNumberOfSymbols());
   for (const SymbolRef &Sym : WasmObj->symbols()) {
@@ -293,6 +302,10 @@ GlobalSymbol *ObjFile::getGlobalSymbol(u
   return cast<GlobalSymbol>(Symbols[Index]);
 }
 
+EventSymbol *ObjFile::getEventSymbol(uint32_t Index) const {
+  return cast<EventSymbol>(Symbols[Index]);
+}
+
 SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const {
   return cast<SectionSymbol>(Symbols[Index]);
 }
@@ -347,6 +360,13 @@ Symbol *ObjFile::createDefined(const Was
     assert(Sym.isBindingLocal());
     return make<SectionSymbol>(Name, Flags, Section, this);
   }
+  case WASM_SYMBOL_TYPE_EVENT: {
+    InputEvent *Event =
+        Events[Sym.Info.ElementIndex - WasmObj->getNumImportedEvents()];
+    if (Sym.isBindingLocal())
+      return make<DefinedEvent>(Name, Flags, this, Event);
+    return Symtab->addDefinedEvent(Name, Flags, this, Event);
+  }
   }
   llvm_unreachable("unknown symbol kind");
 }
@@ -357,7 +377,7 @@ Symbol *ObjFile::createUndefined(const W
 
   switch (Sym.Info.Kind) {
   case WASM_SYMBOL_TYPE_FUNCTION:
-    return Symtab->addUndefinedFunction(Name, Flags, this, Sym.FunctionType);
+    return Symtab->addUndefinedFunction(Name, Flags, this, Sym.Signature);
   case WASM_SYMBOL_TYPE_DATA:
     return Symtab->addUndefinedData(Name, Flags, this);
   case WASM_SYMBOL_TYPE_GLOBAL:

Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Fri Dec  7 22:17:43 2018
@@ -27,6 +27,7 @@ class InputChunk;
 class InputFunction;
 class InputSegment;
 class InputGlobal;
+class InputEvent;
 class InputSection;
 
 class InputFile {
@@ -108,6 +109,7 @@ public:
   std::vector<InputSegment *> Segments;
   std::vector<InputFunction *> Functions;
   std::vector<InputGlobal *> Globals;
+  std::vector<InputEvent *> Events;
   std::vector<InputSection *> CustomSections;
   llvm::DenseMap<uint32_t, InputSection *> CustomSectionsByIndex;
 
@@ -116,6 +118,7 @@ public:
   DataSymbol *getDataSymbol(uint32_t Index) const;
   GlobalSymbol *getGlobalSymbol(uint32_t Index) const;
   SectionSymbol *getSectionSymbol(uint32_t Index) const;
+  EventSymbol *getEventSymbol(uint32_t Index) const;
 
 private:
   Symbol *createDefined(const WasmSymbol &Sym);

Modified: lld/trunk/wasm/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/LTO.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/LTO.cpp (original)
+++ lld/trunk/wasm/LTO.cpp Fri Dec  7 22:17:43 2018
@@ -80,7 +80,7 @@ BitcodeCompiler::~BitcodeCompiler() = de
 static void undefine(Symbol *S) {
   if (auto F = dyn_cast<DefinedFunction>(S))
     replaceSymbol<UndefinedFunction>(F, F->getName(), 0, F->getFile(),
-                                     F->FunctionType);
+                                     F->Signature);
   else if (isa<DefinedData>(S))
     replaceSymbol<UndefinedData>(S, S->getName(), 0, S->getFile());
   else

Modified: lld/trunk/wasm/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/MarkLive.cpp (original)
+++ lld/trunk/wasm/MarkLive.cpp Fri Dec  7 22:17:43 2018
@@ -22,6 +22,7 @@
 #include "MarkLive.h"
 #include "Config.h"
 #include "InputChunks.h"
+#include "InputEvent.h"
 #include "InputGlobal.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
@@ -105,6 +106,9 @@ void lld::wasm::markLive() {
       for (InputGlobal *G : Obj->Globals)
         if (!G->Live)
           message("removing unused section " + toString(G));
+      for (InputEvent *E : Obj->Events)
+        if (!E->Live)
+          message("removing unused section " + toString(E));
     }
     for (InputChunk *C : Symtab->SyntheticFunctions)
       if (!C->Live)

Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Fri Dec  7 22:17:43 2018
@@ -40,6 +40,8 @@ static StringRef sectionTypeToString(uin
     return "MEMORY";
   case WASM_SEC_GLOBAL:
     return "GLOBAL";
+  case WASM_SEC_EVENT:
+    return "EVENT";
   case WASM_SEC_EXPORT:
     return "EXPORT";
   case WASM_SEC_START:

Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Fri Dec  7 22:17:43 2018
@@ -10,6 +10,7 @@
 #include "SymbolTable.h"
 #include "Config.h"
 #include "InputChunks.h"
+#include "InputEvent.h"
 #include "InputGlobal.h"
 #include "WriterUtils.h"
 #include "lld/Common/ErrorHandler.h"
@@ -111,9 +112,9 @@ static void checkFunctionType(Symbol *Ex
   if (!NewSig)
     return;
 
-  const WasmSignature *OldSig = ExistingFunction->FunctionType;
+  const WasmSignature *OldSig = ExistingFunction->Signature;
   if (!OldSig) {
-    ExistingFunction->FunctionType = NewSig;
+    ExistingFunction->Signature = NewSig;
     return;
   }
 
@@ -139,6 +140,28 @@ static void checkGlobalType(const Symbol
   }
 }
 
+static void checkEventType(const Symbol *Existing, const InputFile *File,
+                           const WasmEventType *NewType,
+                           const WasmSignature *NewSig) {
+  auto ExistingEvent = dyn_cast<EventSymbol>(Existing);
+  if (!isa<EventSymbol>(Existing)) {
+    reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT);
+    return;
+  }
+
+  const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType();
+  const WasmSignature *OldSig = ExistingEvent->Signature;
+  if (NewType->Attribute != OldType->Attribute)
+    error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " +
+          toString(*OldType) + " in " + toString(Existing->getFile()) +
+          "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
+  if (*NewSig != *OldSig)
+    warn("Event signature mismatch: " + Existing->getName() +
+         "\n>>> defined as " + toString(*OldSig) + " in " +
+         toString(Existing->getFile()) + "\n>>> defined as " +
+         toString(*NewSig) + " in " + toString(File));
+}
+
 static void checkDataType(const Symbol *Existing, const InputFile *File) {
   if (!isa<DataSymbol>(Existing))
     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);
@@ -222,10 +245,10 @@ Symbol *SymbolTable::addDefinedFunction(
     // functions) but the old symbols does then preserve the old signature
     const WasmSignature *OldSig = nullptr;
     if (auto* F = dyn_cast<FunctionSymbol>(S))
-      OldSig = F->FunctionType;
+      OldSig = F->Signature;
     auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
-    if (!NewSym->FunctionType)
-      NewSym->FunctionType = OldSig;
+    if (!NewSym->Signature)
+      NewSym->Signature = OldSig;
   }
   return S;
 }
@@ -271,6 +294,26 @@ Symbol *SymbolTable::addDefinedGlobal(St
   return S;
 }
 
+Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,
+                                     InputFile *File, InputEvent *Event) {
+  LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n");
+
+  Symbol *S;
+  bool WasInserted;
+  std::tie(S, WasInserted) = insert(Name, File);
+
+  if (WasInserted || S->isLazy()) {
+    replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);
+    return S;
+  }
+
+  checkEventType(S, File, &Event->getType(), &Event->Signature);
+
+  if (shouldReplace(S, File, Flags))
+    replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);
+  return S;
+}
+
 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags,
                                           InputFile *File,
                                           const WasmSignature *Sig) {

Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Fri Dec  7 22:17:43 2018
@@ -56,6 +56,8 @@ public:
                          uint32_t Size);
   Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
                            InputGlobal *G);
+  Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
+                          InputEvent *E);
 
   Symbol *addUndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File,
                                const WasmSignature *Signature);

Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Fri Dec  7 22:17:43 2018
@@ -10,6 +10,7 @@
 #include "Symbols.h"
 #include "Config.h"
 #include "InputChunks.h"
+#include "InputEvent.h"
 #include "InputFiles.h"
 #include "InputGlobal.h"
 #include "OutputSegment.h"
@@ -38,6 +39,8 @@ WasmSymbolType Symbol::getWasmType() con
     return WASM_SYMBOL_TYPE_DATA;
   if (isa<GlobalSymbol>(this))
     return WASM_SYMBOL_TYPE_GLOBAL;
+  if (isa<EventSymbol>(this))
+    return WASM_SYMBOL_TYPE_EVENT;
   if (isa<SectionSymbol>(this))
     return WASM_SYMBOL_TYPE_SECTION;
   llvm_unreachable("invalid symbol kind");
@@ -54,6 +57,8 @@ InputChunk *Symbol::getChunk() const {
 bool Symbol::isLive() const {
   if (auto *G = dyn_cast<DefinedGlobal>(this))
     return G->Global->Live;
+  if (auto *E = dyn_cast<DefinedEvent>(this))
+    return E->Event->Live;
   if (InputChunk *C = getChunk())
     return C->Live;
   return Referenced;
@@ -62,6 +67,8 @@ bool Symbol::isLive() const {
 void Symbol::markLive() {
   if (auto *G = dyn_cast<DefinedGlobal>(this))
     G->Global->Live = true;
+  if (auto *E = dyn_cast<DefinedEvent>(this))
+    E->Event->Live = true;
   if (InputChunk *C = getChunk())
     C->Live = true;
   Referenced = true;
@@ -212,6 +219,32 @@ DefinedGlobal::DefinedGlobal(StringRef N
                    Global ? &Global->getType() : nullptr),
       Global(Global) {}
 
+uint32_t EventSymbol::getEventIndex() const {
+  if (auto *F = dyn_cast<DefinedEvent>(this))
+    return F->Event->getEventIndex();
+  assert(EventIndex != INVALID_INDEX);
+  return EventIndex;
+}
+
+void EventSymbol::setEventIndex(uint32_t Index) {
+  LLVM_DEBUG(dbgs() << "setEventIndex " << Name << " -> " << Index << "\n");
+  assert(EventIndex == INVALID_INDEX);
+  EventIndex = Index;
+}
+
+bool EventSymbol::hasEventIndex() const {
+  if (auto *F = dyn_cast<DefinedEvent>(this))
+    return F->Event->hasEventIndex();
+  return EventIndex != INVALID_INDEX;
+}
+
+DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
+                           InputEvent *Event)
+    : EventSymbol(Name, DefinedEventKind, Flags, File,
+                  Event ? &Event->getType() : nullptr,
+                  Event ? &Event->Signature : nullptr),
+      Event(Event) {}
+
 uint32_t SectionSymbol::getOutputSectionIndex() const {
   LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
   assert(OutputSectionIndex != INVALID_INDEX);
@@ -246,6 +279,8 @@ std::string lld::toString(wasm::Symbol::
     return "DefinedData";
   case wasm::Symbol::DefinedGlobalKind:
     return "DefinedGlobal";
+  case wasm::Symbol::DefinedEventKind:
+    return "DefinedEvent";
   case wasm::Symbol::UndefinedFunctionKind:
     return "UndefinedFunction";
   case wasm::Symbol::UndefinedDataKind:

Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Fri Dec  7 22:17:43 2018
@@ -25,6 +25,7 @@ class InputChunk;
 class InputSegment;
 class InputFunction;
 class InputGlobal;
+class InputEvent;
 class InputSection;
 
 #define INVALID_INDEX UINT32_MAX
@@ -36,6 +37,7 @@ public:
     DefinedFunctionKind,
     DefinedDataKind,
     DefinedGlobalKind,
+    DefinedEventKind,
     SectionKind,
     UndefinedFunctionKind,
     UndefinedDataKind,
@@ -47,7 +49,8 @@ public:
 
   bool isDefined() const {
     return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
-           SymbolKind == DefinedGlobalKind || SymbolKind == SectionKind;
+           SymbolKind == DefinedGlobalKind || SymbolKind == DefinedEventKind ||
+           SymbolKind == SectionKind;
   }
 
   bool isUndefined() const {
@@ -121,12 +124,12 @@ public:
   void setFunctionIndex(uint32_t Index);
   bool hasFunctionIndex() const;
 
-  const WasmSignature *FunctionType;
+  const WasmSignature *Signature;
 
 protected:
   FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
-                 const WasmSignature *Type)
-      : Symbol(Name, K, Flags, F), FunctionType(Type) {}
+                 const WasmSignature *Sig)
+      : Symbol(Name, K, Flags, F), Signature(Sig) {}
 
   uint32_t TableIndex = INVALID_INDEX;
   uint32_t FunctionIndex = INVALID_INDEX;
@@ -267,6 +270,50 @@ public:
   }
 };
 
+// Wasm events are features that suspend the current execution and transfer the
+// control flow to a corresponding handler. Currently the only supported event
+// kind is exceptions.
+//
+// Event tags are values to distinguish different events. For exceptions, they
+// can be used to distinguish different language's exceptions, i.e., all C++
+// exceptions have the same tag. Wasm can generate code capable of doing
+// different handling actions based on the tag of caught exceptions.
+//
+// A single EventSymbol object represents a single tag. C++ exception event
+// symbol is a weak symbol generated in every object file in which exceptions
+// are used, and has name '__cpp_exception' for linking.
+class EventSymbol : public Symbol {
+public:
+  static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }
+
+  const WasmEventType *getEventType() const { return EventType; }
+
+  // Get/set the event index
+  uint32_t getEventIndex() const;
+  void setEventIndex(uint32_t Index);
+  bool hasEventIndex() const;
+
+  const WasmSignature *Signature;
+
+protected:
+  EventSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
+              const WasmEventType *EventType, const WasmSignature *Sig)
+      : Symbol(Name, K, Flags, F), Signature(Sig), EventType(EventType) {}
+
+  const WasmEventType *EventType;
+  uint32_t EventIndex = INVALID_INDEX;
+};
+
+class DefinedEvent : public EventSymbol {
+public:
+  DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
+               InputEvent *Event);
+
+  static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }
+
+  InputEvent *Event;
+};
+
 class LazySymbol : public Symbol {
 public:
   LazySymbol(StringRef Name, InputFile *File,
@@ -321,10 +368,11 @@ union SymbolUnion {
   alignas(DefinedFunction) char A[sizeof(DefinedFunction)];
   alignas(DefinedData) char B[sizeof(DefinedData)];
   alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)];
-  alignas(LazySymbol) char D[sizeof(LazySymbol)];
-  alignas(UndefinedFunction) char E[sizeof(UndefinedFunction)];
-  alignas(UndefinedData) char F[sizeof(UndefinedData)];
-  alignas(UndefinedGlobal) char G[sizeof(UndefinedGlobal)];
+  alignas(DefinedEvent) char D[sizeof(DefinedEvent)];
+  alignas(LazySymbol) char E[sizeof(LazySymbol)];
+  alignas(UndefinedFunction) char F[sizeof(UndefinedFunction)];
+  alignas(UndefinedData) char G[sizeof(UndefinedData)];
+  alignas(UndefinedGlobal) char H[sizeof(UndefinedGlobal)];
   alignas(SectionSymbol) char I[sizeof(SectionSymbol)];
 };
 

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Fri Dec  7 22:17:43 2018
@@ -10,6 +10,7 @@
 #include "Writer.h"
 #include "Config.h"
 #include "InputChunks.h"
+#include "InputEvent.h"
 #include "InputGlobal.h"
 #include "OutputSections.h"
 #include "OutputSegment.h"
@@ -80,6 +81,7 @@ private:
   void createFunctionSection();
   void createTableSection();
   void createGlobalSection();
+  void createEventSection();
   void createExportSection();
   void createImportSection();
   void createMemorySection();
@@ -111,10 +113,12 @@ private:
   std::vector<const Symbol *> ImportedSymbols;
   unsigned NumImportedFunctions = 0;
   unsigned NumImportedGlobals = 0;
+  unsigned NumImportedEvents = 0;
   std::vector<WasmExport> Exports;
   std::vector<const DefinedData *> DefinedFakeGlobals;
   std::vector<InputGlobal *> InputGlobals;
   std::vector<InputFunction *> InputFunctions;
+  std::vector<InputEvent *> InputEvents;
   std::vector<const FunctionSymbol *> IndirectFunctions;
   std::vector<const Symbol *> SymtabEntries;
   std::vector<WasmInitEntry> InitFunctions;
@@ -182,11 +186,15 @@ void Writer::createImportSection() {
     Import.Field = Sym->getName();
     if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
       Import.Kind = WASM_EXTERNAL_FUNCTION;
-      Import.SigIndex = lookupType(*FunctionSym->FunctionType);
-    } else {
-      auto *GlobalSym = cast<GlobalSymbol>(Sym);
+      Import.SigIndex = lookupType(*FunctionSym->Signature);
+    } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
       Import.Kind = WASM_EXTERNAL_GLOBAL;
       Import.Global = *GlobalSym->getGlobalType();
+    } else {
+      auto *EventSym = cast<EventSymbol>(Sym);
+      Import.Kind = WASM_EXTERNAL_EVENT;
+      Import.Event.Attribute = EventSym->getEventType()->Attribute;
+      Import.Event.SigIndex = lookupType(*EventSym->Signature);
     }
     writeImport(OS, Import);
   }
@@ -252,6 +260,31 @@ void Writer::createGlobalSection() {
   }
 }
 
+// The event section contains a list of declared wasm events associated with the
+// module. Currently the only supported event kind is exceptions. A single event
+// entry represents a single event with an event tag. All C++ exceptions are
+// represented by a single event. An event entry in this section contains
+// information on what kind of event it is (e.g. exception) and the type of
+// values contained in a single event object. (In wasm, an event can contain
+// multiple values of primitive types. But for C++ exceptions, we just throw a
+// pointer which is an i32 value (for wasm32 architecture), so the signature of
+// C++ exception is (i32)->(void), because all event types are assumed to have
+// void return type to share WasmSignature with functions.)
+void Writer::createEventSection() {
+  unsigned NumEvents = InputEvents.size();
+  if (NumEvents == 0)
+    return;
+
+  SyntheticSection *Section = createSyntheticSection(WASM_SEC_EVENT);
+  raw_ostream &OS = Section->getStream();
+
+  writeUleb128(OS, NumEvents, "event count");
+  for (InputEvent *E : InputEvents) {
+    E->Event.Type.SigIndex = lookupType(E->Signature);
+    writeEvent(OS, E->Event);
+  }
+}
+
 void Writer::createTableSection() {
   if (Config->ImportTable)
     return;
@@ -478,6 +511,10 @@ void Writer::createLinkingSection() {
         writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
         if (Sym->isDefined())
           writeStr(Sub.OS, Sym->getName(), "sym name");
+      } else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
+        writeUleb128(Sub.OS, E->getEventIndex(), "index");
+        if (Sym->isDefined())
+          writeStr(Sub.OS, Sym->getName(), "sym name");
       } else if (isa<DataSymbol>(Sym)) {
         writeStr(Sub.OS, Sym->getName(), "sym name");
         if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
@@ -722,6 +759,7 @@ void Writer::createSections() {
   createTableSection();
   createMemorySection();
   createGlobalSection();
+  createEventSection();
   createExportSection();
   createElemSection();
   createCodeSection();
@@ -760,8 +798,10 @@ void Writer::calculateImports() {
     ImportedSymbols.emplace_back(Sym);
     if (auto *F = dyn_cast<FunctionSymbol>(Sym))
       F->setFunctionIndex(NumImportedFunctions++);
+    else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
+      G->setGlobalIndex(NumImportedGlobals++);
     else
-      cast<GlobalSymbol>(Sym)->setGlobalIndex(NumImportedGlobals++);
+      cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
   }
 }
 
@@ -797,6 +837,8 @@ void Writer::calculateExports() {
         continue;
       }
       Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()};
+    } else if (auto *E = dyn_cast<DefinedEvent>(Sym)) {
+      Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()};
     } else {
       auto *D = cast<DefinedData>(Sym);
       DefinedFakeGlobals.emplace_back(D);
@@ -874,6 +916,8 @@ void Writer::calculateTypes() {
   // 1. Any signature used in the TYPE relocation
   // 2. The signatures of all imported functions
   // 3. The signatures of all defined functions
+  // 4. The signatures of all imported events
+  // 5. The signatures of all defined events
 
   for (ObjFile *File : Symtab->ObjectFiles) {
     ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
@@ -882,12 +926,18 @@ void Writer::calculateTypes() {
         File->TypeMap[I] = registerType(Types[I]);
   }
 
-  for (const Symbol *Sym : ImportedSymbols)
+  for (const Symbol *Sym : ImportedSymbols) {
     if (auto *F = dyn_cast<FunctionSymbol>(Sym))
-      registerType(*F->FunctionType);
+      registerType(*F->Signature);
+    else if (auto *E = dyn_cast<EventSymbol>(Sym))
+      registerType(*E->Signature);
+  }
 
   for (const InputFunction *F : InputFunctions)
     registerType(F->Signature);
+
+  for (const InputEvent *E : InputEvents)
+    registerType(E->Signature);
 }
 
 void Writer::assignIndexes() {
@@ -959,6 +1009,22 @@ void Writer::assignIndexes() {
     for (InputGlobal *Global : File->Globals)
       AddDefinedGlobal(Global);
   }
+
+  assert(InputEvents.empty());
+  uint32_t EventIndex = NumImportedEvents;
+  auto AddDefinedEvent = [&](InputEvent *Event) {
+    if (Event->Live) {
+      LLVM_DEBUG(dbgs() << "AddDefinedEvent: " << EventIndex << "\n");
+      Event->setEventIndex(EventIndex++);
+      InputEvents.push_back(Event);
+    }
+  };
+
+  for (ObjFile *File : Symtab->ObjectFiles) {
+    LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n");
+    for (InputEvent *Event : File->Events)
+      AddDefinedEvent(Event);
+  }
 }
 
 static StringRef getOutputDataSegmentName(StringRef Name) {
@@ -1035,7 +1101,7 @@ void Writer::calculateInitFunctions() {
     const WasmLinkingData &L = File->getWasmObj()->linkingData();
     for (const WasmInitFunc &F : L.InitFunctions) {
       FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol);
-      if (*Sym->FunctionType != WasmSignature{{}, {}})
+      if (*Sym->Signature != WasmSignature{{}, {}})
         error("invalid signature for init func: " + toString(*Sym));
       InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority});
     }
@@ -1080,8 +1146,10 @@ void Writer::run() {
   if (errorHandler().Verbose) {
     log("Defined Functions: " + Twine(InputFunctions.size()));
     log("Defined Globals  : " + Twine(InputGlobals.size()));
+    log("Defined Events   : " + Twine(InputEvents.size()));
     log("Function Imports : " + Twine(NumImportedFunctions));
     log("Global Imports   : " + Twine(NumImportedGlobals));
+    log("Event Imports    : " + Twine(NumImportedEvents));
     for (ObjFile *File : Symtab->ObjectFiles)
       File->dumpInfo();
   }

Modified: lld/trunk/wasm/WriterUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.cpp?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.cpp (original)
+++ lld/trunk/wasm/WriterUtils.cpp Fri Dec  7 22:17:43 2018
@@ -110,6 +110,15 @@ void wasm::writeGlobal(raw_ostream &OS,
   writeInitExpr(OS, Global.InitExpr);
 }
 
+void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) {
+  writeUleb128(OS, Type.Attribute, "event attribute");
+  writeUleb128(OS, Type.SigIndex, "sig index");
+}
+
+void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) {
+  writeEventType(OS, Event.Type);
+}
+
 void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
   writeU8(OS, WASM_TYPE_ANYFUNC, "table type");
   writeLimits(OS, Type.Limits);
@@ -126,6 +135,9 @@ void wasm::writeImport(raw_ostream &OS,
   case WASM_EXTERNAL_GLOBAL:
     writeGlobalType(OS, Import.Global);
     break;
+  case WASM_EXTERNAL_EVENT:
+    writeEventType(OS, Import.Event);
+    break;
   case WASM_EXTERNAL_MEMORY:
     writeLimits(OS, Import.Memory);
     break;
@@ -192,7 +204,13 @@ std::string lld::toString(const WasmSign
   return S.str();
 }
 
-std::string lld::toString(const WasmGlobalType &Sig) {
-  return (Sig.Mutable ? "var " : "const ") +
-         toString(static_cast<ValType>(Sig.Type));
+std::string lld::toString(const WasmGlobalType &Type) {
+  return (Type.Mutable ? "var " : "const ") +
+         toString(static_cast<ValType>(Type.Type));
+}
+
+std::string lld::toString(const WasmEventType &Type) {
+  if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
+    return "exception";
+  return "unknown";
 }

Modified: lld/trunk/wasm/WriterUtils.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.h?rev=348703&r1=348702&r2=348703&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.h (original)
+++ lld/trunk/wasm/WriterUtils.h Fri Dec  7 22:17:43 2018
@@ -45,6 +45,10 @@ void writeGlobalType(raw_ostream &OS, co
 
 void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global);
 
+void writeEventType(raw_ostream &OS, const llvm::wasm::WasmEventType &Type);
+
+void writeEvent(raw_ostream &OS, const llvm::wasm::WasmEvent &Event);
+
 void writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type);
 
 void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import);
@@ -55,7 +59,8 @@ void writeExport(raw_ostream &OS, const
 
 std::string toString(llvm::wasm::ValType Type);
 std::string toString(const llvm::wasm::WasmSignature &Sig);
-std::string toString(const llvm::wasm::WasmGlobalType &Sig);
+std::string toString(const llvm::wasm::WasmGlobalType &Type);
+std::string toString(const llvm::wasm::WasmEventType &Type);
 
 } // namespace lld
 




More information about the llvm-commits mailing list