Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 07:55:10 +08:00
|
|
|
//===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 07:55:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains support for writing WebAssembly exception info into asm
|
|
|
|
// files.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "WasmException.h"
|
2018-11-14 10:46:21 +08:00
|
|
|
#include "llvm/IR/Mangler.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 07:55:10 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
void WasmException::endModule() {
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
// This is the symbol used in 'throw' and 'br_on_exn' instruction to denote
|
2018-11-14 10:46:21 +08:00
|
|
|
// this is a C++ exception. This symbol has to be emitted somewhere once in
|
|
|
|
// the module. Check if the symbol has already been created, i.e., we have at
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
// least one 'throw' or 'br_on_exn' instruction in the module, and emit the
|
2018-11-14 10:46:21 +08:00
|
|
|
// symbol only if so.
|
|
|
|
SmallString<60> NameStr;
|
|
|
|
Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
|
|
|
|
if (Asm->OutContext.lookupSymbol(NameStr)) {
|
|
|
|
MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception");
|
|
|
|
Asm->OutStreamer->EmitLabel(ExceptionSym);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 07:55:10 +08:00
|
|
|
void WasmException::markFunctionEnd() {
|
|
|
|
// Get rid of any dead landing pads.
|
|
|
|
if (!Asm->MF->getLandingPads().empty()) {
|
|
|
|
auto *NonConstMF = const_cast<MachineFunction *>(Asm->MF);
|
|
|
|
// Wasm does not set BeginLabel and EndLabel information for landing pads,
|
|
|
|
// so we should set the second argument false.
|
|
|
|
NonConstMF->tidyLandingPads(nullptr, /* TidyIfNoBeginLabels */ false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WasmException::endFunction(const MachineFunction *MF) {
|
|
|
|
bool ShouldEmitExceptionTable = false;
|
|
|
|
for (const LandingPadInfo &Info : MF->getLandingPads()) {
|
|
|
|
if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) {
|
|
|
|
ShouldEmitExceptionTable = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ShouldEmitExceptionTable)
|
|
|
|
return;
|
|
|
|
MCSymbol *LSDALabel = emitExceptionTable();
|
|
|
|
assert(LSDALabel && ".GCC_exception_table has not been emitted!");
|
|
|
|
|
|
|
|
// Wasm requires every data section symbol to have a .size set. So we emit an
|
|
|
|
// end marker and set the size as the difference between the start end the end
|
|
|
|
// marker.
|
|
|
|
MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end");
|
|
|
|
Asm->OutStreamer->EmitLabel(LSDAEndLabel);
|
|
|
|
MCContext &OutContext = Asm->OutStreamer->getContext();
|
|
|
|
const MCExpr *SizeExp = MCBinaryExpr::createSub(
|
|
|
|
MCSymbolRefExpr::create(LSDAEndLabel, OutContext),
|
|
|
|
MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext);
|
|
|
|
Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the call-site table for wasm EH. Even though we use the same function
|
|
|
|
// name to share the common routines, a call site entry in the table corresponds
|
|
|
|
// to not a call site for possibly-throwing functions but a landing pad. In wasm
|
|
|
|
// EH the VM is responsible for stack unwinding. After an exception occurs and
|
|
|
|
// the stack is unwound, the control flow is transferred to wasm 'catch'
|
|
|
|
// instruction by the VM, after which the personality function is called from
|
|
|
|
// the compiler-generated code. Refer to WasmEHPrepare pass for more
|
|
|
|
// information.
|
|
|
|
void WasmException::computeCallSiteTable(
|
|
|
|
SmallVectorImpl<CallSiteEntry> &CallSites,
|
|
|
|
const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
|
|
|
|
const SmallVectorImpl<unsigned> &FirstActions) {
|
|
|
|
MachineFunction &MF = *Asm->MF;
|
|
|
|
for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) {
|
|
|
|
const LandingPadInfo *Info = LandingPads[I];
|
|
|
|
MachineBasicBlock *LPad = Info->LandingPadBlock;
|
|
|
|
// We don't emit LSDA for single catch (...).
|
|
|
|
if (!MF.hasWasmLandingPadIndex(LPad))
|
|
|
|
continue;
|
|
|
|
// Wasm EH must maintain the EH pads in the order assigned to them by the
|
|
|
|
// WasmEHPrepare pass.
|
|
|
|
unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad);
|
|
|
|
CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]};
|
|
|
|
if (CallSites.size() < LPadIndex + 1)
|
|
|
|
CallSites.resize(LPadIndex + 1);
|
|
|
|
CallSites[LPadIndex] = Site;
|
|
|
|
}
|
|
|
|
}
|