Skip to content

Commit

Permalink
[WebAssembly] Add support for the event section
Browse files Browse the repository at this point in the history
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

llvm-svn: 348703
  • Loading branch information
aheejin committed Dec 8, 2018
1 parent a2125b8 commit e915a71
Show file tree
Hide file tree
Showing 19 changed files with 401 additions and 30 deletions.
4 changes: 4 additions & 0 deletions lld/include/lld/Common/LLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class WasmSymbol;
} // namespace object

namespace wasm {
struct WasmEvent;
struct WasmEventType;
struct WasmFunction;
struct WasmGlobal;
struct WasmGlobalType;
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions lld/test/wasm/Inputs/event-section1.ll
Original file line number Diff line number Diff line change
@@ -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
}
9 changes: 9 additions & 0 deletions lld/test/wasm/Inputs/event-section2.ll
Original file line number Diff line number Diff line change
@@ -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
}
34 changes: 34 additions & 0 deletions lld/test/wasm/event-section.ll
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions lld/wasm/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions lld/wasm/InputChunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ void InputChunk::verifyRelocTargets() const {
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;
Expand Down Expand Up @@ -111,6 +112,7 @@ void InputChunk::writeTo(uint8_t *Buf) const {
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;
Expand Down Expand Up @@ -180,6 +182,7 @@ static unsigned writeCompressedReloc(uint8_t *Buf, const WasmRelocation &Rel,
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:
Expand All @@ -195,6 +198,7 @@ static unsigned getRelocWidthPadded(const WasmRelocation &Rel) {
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:
Expand Down
63 changes: 63 additions & 0 deletions lld/wasm/InputEvent.h
Original file line number Diff line number Diff line change
@@ -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
26 changes: 23 additions & 3 deletions lld/wasm/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -119,7 +121,8 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
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;
}
Expand Down Expand Up @@ -147,6 +150,8 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
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())
Expand Down Expand Up @@ -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()) {
Expand All @@ -293,6 +302,10 @@ GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
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]);
}
Expand Down Expand Up @@ -347,6 +360,13 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
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");
}
Expand All @@ -357,7 +377,7 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {

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:
Expand Down
3 changes: 3 additions & 0 deletions lld/wasm/InputFiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class InputChunk;
class InputFunction;
class InputSegment;
class InputGlobal;
class InputEvent;
class InputSection;

class InputFile {
Expand Down Expand Up @@ -108,6 +109,7 @@ class ObjFile : public InputFile {
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;

Expand All @@ -116,6 +118,7 @@ class ObjFile : public InputFile {
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);
Expand Down
2 changes: 1 addition & 1 deletion lld/wasm/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ BitcodeCompiler::~BitcodeCompiler() = default;
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
Expand Down
4 changes: 4 additions & 0 deletions lld/wasm/MarkLive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions lld/wasm/OutputSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ static StringRef sectionTypeToString(uint32_t SectionType) {
return "MEMORY";
case WASM_SEC_GLOBAL:
return "GLOBAL";
case WASM_SEC_EVENT:
return "EVENT";
case WASM_SEC_EXPORT:
return "EXPORT";
case WASM_SEC_START:
Expand Down
Loading

0 comments on commit e915a71

Please sign in to comment.