Skip to content

Commit 5924e97

Browse files
aheejinmemfrob
authored andcommitted
[WebAssembly] Add Wasm SjLj support
This add support for SjLj using Wasm exception handling instructions: https://github.com/WebAssembly/exception-handling/blob/master/proposals/exception-handling/Exceptions.md This does not yet support the mixed use of EH and SjLj within a function. It will be added in a follow-up CL. This currently passes all SjLj Emscripten tests for wasm0/1/2/3/s, except for the below: - `test_longjmp_standalone`: Uses Node - `test_dlfcn_longjmp`: Uses NodeRAWFS - `test_longjmp_throw`: Mixes EH and SjLj - `test_exceptions_longjmp1`: Mixes EH and SjLj - `test_exceptions_longjmp2`: Mixes EH and SjLj - `test_exceptions_longjmp3`: Mixes EH and SjLj Reviewed By: dschuff, tlively Differential Revision: https://reviews.llvm.org/D108960
1 parent ed9fb1b commit 5924e97

File tree

8 files changed

+564
-79
lines changed

8 files changed

+564
-79
lines changed

llvm/lib/CodeGen/AsmPrinter/WasmException.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@
1818
using namespace llvm;
1919

2020
void WasmException::endModule() {
21-
// This is the symbol used in 'throw' and 'catch' instruction to denote this
22-
// is a C++ exception. This symbol has to be emitted somewhere once in the
23-
// module. Check if the symbol has already been created, i.e., we have at
24-
// least one 'throw' or 'catch' instruction in the module, and emit the symbol
25-
// only if so.
26-
SmallString<60> NameStr;
27-
Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
28-
if (Asm->OutContext.lookupSymbol(NameStr)) {
29-
MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception");
30-
Asm->OutStreamer->emitLabel(ExceptionSym);
21+
// These are symbols used to throw/catch C++ exceptions and C longjmps. These
22+
// symbols have to be emitted somewhere once in the module. Check if each of
23+
// the symbols has already been created, i.e., we have at least one 'throw' or
24+
// 'catch' instruction with the symbol in the module, and emit the symbol only
25+
// if so.
26+
for (const char *SymName : {"__cpp_exception", "__c_longjmp"}) {
27+
SmallString<60> NameStr;
28+
Mangler::getNameWithPrefix(NameStr, SymName, Asm->getDataLayout());
29+
if (Asm->OutContext.lookupSymbol(NameStr)) {
30+
MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol(SymName);
31+
Asm->OutStreamer->emitLabel(ExceptionSym);
32+
}
3133
}
3234
}
3335

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,7 +1226,10 @@ static void mapWasmLandingPadIndex(MachineBasicBlock *MBB,
12261226
bool IsSingleCatchAllClause =
12271227
CPI->getNumArgOperands() == 1 &&
12281228
cast<Constant>(CPI->getArgOperand(0))->isNullValue();
1229-
if (!IsSingleCatchAllClause) {
1229+
// cathchpads for longjmp use an empty type list, e.g. catchpad within %0 []
1230+
// and they don't need LSDA info
1231+
bool IsCatchLongjmp = CPI->getNumArgOperands() == 0;
1232+
if (!IsSingleCatchAllClause && !IsCatchLongjmp) {
12301233
// Create a mapping from landing pad label to landing pad index.
12311234
bool IntrFound = false;
12321235
for (const User *U : CPI->users()) {

llvm/lib/MC/WasmObjectWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,8 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
16441644
LLVM_DEBUG(dbgs() << " -> table index: "
16451645
<< WasmIndices.find(&WS)->second << "\n");
16461646
} else if (WS.isTag()) {
1647-
// C++ exception symbol (__cpp_exception)
1647+
// C++ exception symbol (__cpp_exception) or longjmp symbol
1648+
// (__c_longjmp)
16481649
unsigned Index;
16491650
if (WS.isDefined()) {
16501651
Index = NumTagImports + Tags.size();

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
236236

237237
SmallVector<wasm::ValType, 4> Returns;
238238
SmallVector<wasm::ValType, 4> Params;
239-
if (Name == "__cpp_exception") {
239+
if (Name == "__cpp_exception" || Name == "__c_longjmp") {
240240
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
241241
// We can't confirm its signature index for now because there can be
242242
// imported exceptions. Set it to be 0 for now.
@@ -248,12 +248,14 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
248248
WasmSym->setWeak(true);
249249
WasmSym->setExternal(true);
250250

251-
// All C++ exceptions are assumed to have a single i32 (for wasm32) or i64
252-
// (for wasm64) param type and void return type. The reaon is, all C++
253-
// exception values are pointers, and to share the type section with
254-
// functions, exceptions are assumed to have void return type.
255-
Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64
256-
: wasm::ValType::I32);
251+
// Currently both C++ exceptions and C longjmps have a single pointer type
252+
// param. For C++ exceptions it is a pointer to an exception object, and for
253+
// C longjmps it is pointer to a struct that contains a setjmp buffer and a
254+
// longjmp return value. We may consider using multiple value parameters for
255+
// longjmps later when multivalue support is ready.
256+
wasm::ValType AddrType =
257+
Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
258+
Params.push_back(AddrType);
257259
} else { // Function symbols
258260
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
259261
getLibcallSignature(Subtarget, Name, Returns, Params);

llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,13 @@ void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
8989
}
9090

9191
static SDValue getTagSymNode(int Tag, SelectionDAG *DAG) {
92-
assert(Tag == WebAssembly::CPP_EXCEPTION);
92+
assert(Tag == WebAssembly::CPP_EXCEPTION || WebAssembly::C_LONGJMP);
9393
auto &MF = DAG->getMachineFunction();
9494
const auto &TLI = DAG->getTargetLoweringInfo();
9595
MVT PtrVT = TLI.getPointerTy(DAG->getDataLayout());
96-
const char *SymName = MF.createExternalSymbolName("__cpp_exception");
96+
const char *SymName = Tag == WebAssembly::CPP_EXCEPTION
97+
? MF.createExternalSymbolName("__cpp_exception")
98+
: MF.createExternalSymbolName("__c_longjmp");
9799
return DAG->getTargetExternalSymbol(SymName, PtrVT);
98100
}
99101

0 commit comments

Comments
 (0)