2015-06-30 07:51:55 +08:00
|
|
|
//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
|
|
|
|
//
|
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
|
2015-06-30 07:51:55 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
2018-05-01 23:54:18 +08:00
|
|
|
/// This file contains the WebAssembly implementation of the
|
2015-06-30 07:51:55 +08:00
|
|
|
/// TargetInstrInfo class.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "WebAssemblyInstrInfo.h"
|
|
|
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
2016-01-28 09:22:44 +08:00
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
2015-06-30 07:51:55 +08:00
|
|
|
#include "WebAssemblySubtarget.h"
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "wasm-instr-info"
|
|
|
|
|
2015-07-23 05:28:15 +08:00
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
|
|
#include "WebAssemblyGenInstrInfo.inc"
|
|
|
|
|
[WebAssembly] Use named operands to identify loads and stores
Summary:
Uses the named operands tablegen feature to look up the indices of
offset, address, and p2align operands for all load and store
instructions. This replaces brittle, incorrect logic for identifying
loads and store when eliminating frame indices, which previously
crashed on bulk-memory ops. It also cleans up the SetP2Alignment pass.
Reviewers: aheejin, dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59007
llvm-svn: 355770
2019-03-09 12:31:37 +08:00
|
|
|
// defines WebAssembly::getNamedOperandIdx
|
|
|
|
#define GET_INSTRINFO_NAMED_OPS
|
|
|
|
#include "WebAssemblyGenInstrInfo.inc"
|
|
|
|
|
2015-06-30 07:51:55 +08:00
|
|
|
WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
|
2015-12-05 07:22:35 +08:00
|
|
|
: WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
|
[WebAssembly] Support instruction selection for catching exceptions
Summary:
This lowers exception catching-related instructions:
1. Lowers `wasm.catch` intrinsic to `catch` instruction
2. Removes `catchpad` and `cleanuppad` instructions; they are not
necessary after isel phase. (`MachineBasicBlock::isEHFuncletEntry()` or
`MachineBasicBlock::isEHPad()` can be used instead.)
3. Lowers `catchret` and `cleanupret` instructions to pseudo `catchret`
and `cleanupret` instructions in isel, which will be replaced with other
instructions in `WebAssemblyExceptionPrepare` pass.
4. Adds 'WebAssemblyExceptionPrepare` pass, which is for running various
transformation for EH. Currently this pass only replaces `catchret` and
`cleanupret` instructions into appropriate wasm instructions to make
this patch successfully run until the end.
Currently this does not handle lowering of intrinsics related to LSDA
info generation (`wasm.landingpad.index` and `wasm.lsda`), because they
cannot be tested without implementing `EHStreamer`'s wasm-specific
handlers. They are marked as TODO, which is needed to make isel pass.
Also this does not generate `try` and `end_try` markers yet, which will
be handled in later patches.
This patch is based on the first wasm EH proposal.
(https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md)
Reviewers: dschuff, majnemer
Subscribers: jfb, sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D44090
llvm-svn: 333705
2018-06-01 06:25:54 +08:00
|
|
|
WebAssembly::ADJCALLSTACKUP,
|
|
|
|
WebAssembly::CATCHRET),
|
2015-12-05 07:22:35 +08:00
|
|
|
RI(STI.getTargetTriple()) {}
|
2015-09-09 08:52:47 +08:00
|
|
|
|
2016-01-20 00:59:23 +08:00
|
|
|
bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
|
2016-06-30 08:01:54 +08:00
|
|
|
const MachineInstr &MI, AliasAnalysis *AA) const {
|
|
|
|
switch (MI.getOpcode()) {
|
2016-01-20 00:59:23 +08:00
|
|
|
case WebAssembly::CONST_I32:
|
|
|
|
case WebAssembly::CONST_I64:
|
|
|
|
case WebAssembly::CONST_F32:
|
|
|
|
case WebAssembly::CONST_F64:
|
|
|
|
// isReallyTriviallyReMaterializableGeneric misses these because of the
|
|
|
|
// ARGUMENTS implicit def, so we manualy override it here.
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-09 08:52:47 +08:00
|
|
|
void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
2016-06-12 23:39:02 +08:00
|
|
|
const DebugLoc &DL, unsigned DestReg,
|
2015-09-09 08:52:47 +08:00
|
|
|
unsigned SrcReg, bool KillSrc) const {
|
2015-12-17 07:21:30 +08:00
|
|
|
// This method is called by post-RA expansion, which expects only pregs to
|
|
|
|
// exist. However we need to handle both here.
|
|
|
|
auto &MRI = MBB.getParent()->getRegInfo();
|
2016-01-20 00:59:23 +08:00
|
|
|
const TargetRegisterClass *RC =
|
|
|
|
TargetRegisterInfo::isVirtualRegister(DestReg)
|
|
|
|
? MRI.getRegClass(DestReg)
|
2016-01-30 02:37:49 +08:00
|
|
|
: MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
|
2015-11-19 00:12:01 +08:00
|
|
|
|
2016-10-25 03:49:43 +08:00
|
|
|
unsigned CopyOpcode;
|
2015-11-19 00:12:01 +08:00
|
|
|
if (RC == &WebAssembly::I32RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_I32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::I64RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_I64;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F32RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_F32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F64RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_F64;
|
2018-11-08 10:35:28 +08:00
|
|
|
else if (RC == &WebAssembly::V128RegClass)
|
|
|
|
CopyOpcode = WebAssembly::COPY_V128;
|
2015-11-19 00:12:01 +08:00
|
|
|
else
|
|
|
|
llvm_unreachable("Unexpected register class");
|
|
|
|
|
2016-10-25 03:49:43 +08:00
|
|
|
BuildMI(MBB, I, DL, get(CopyOpcode), DestReg)
|
2015-09-09 08:52:47 +08:00
|
|
|
.addReg(SrcReg, KillSrc ? RegState::Kill : 0);
|
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2018-09-05 09:27:38 +08:00
|
|
|
MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(
|
|
|
|
MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {
|
2016-01-28 09:22:44 +08:00
|
|
|
// If the operands are stackified, we can't reorder them.
|
|
|
|
WebAssemblyFunctionInfo &MFI =
|
2016-06-30 08:01:54 +08:00
|
|
|
*MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
|
|
|
|
MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))
|
2016-01-28 09:22:44 +08:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Otherwise use the default implementation.
|
|
|
|
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
|
|
|
}
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
// Branch analysis.
|
2016-07-15 22:41:04 +08:00
|
|
|
bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
|
2015-09-17 00:51:30 +08:00
|
|
|
MachineBasicBlock *&TBB,
|
|
|
|
MachineBasicBlock *&FBB,
|
|
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
2015-11-30 06:32:02 +08:00
|
|
|
bool /*AllowModify*/) const {
|
[WebAssembly] Don't analyze branches after CFGStackify
Summary:
`WebAssembly::analyzeBranch` now does not analyze anything if the
function is CFG stackified. We were previously doing similar things by
checking if a branch's operand is whether an integer or an MBB, but this
failed to bail out when a BB did not have any terminators.
Consider this case:
```
bb0:
try $label0
call @foo // unwinds to %ehpad
bb1:
...
br $label0 // jumps to %cont. can be deleted
ehpad:
catch
...
cont:
end_try
```
Here `br $label0` will be deleted in CFGStackify's
`removeUnnecessaryInstrs` function, because we jump to the %cont block
even without the branch. But in this case, MachineVerifier fails to
verify this, because `ehpad` is not a successor of `bb1` even if `bb1`
does not have any terminators. MachineVerifier incorrectly thinks `bb1`
falls through to the next block.
This pass now consistently rejects all analysis after CFGStackify
whether a BB has terminators or not, also making the MachineVerifier
work. (MachineVerifier does not try to verify relationships between BBs
if `analyzeBranch` fails, the behavior we want after CFGStackify.)
This also adds a new option `-wasm-disable-ehpad-sort` for testing. This
option helps create the sorted order we want to test, and without the
fix in this patch, the tests in cfg-stackify-eh.ll fail at
MachineVerifier with `-wasm-disable-ehpad-sort`.
Reviewers: dschuff
Subscribers: sunfish, sbc100, jgravelle-google, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59740
llvm-svn: 357015
2019-03-27 02:21:20 +08:00
|
|
|
const auto &MFI = *MBB.getParent()->getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
// WebAssembly has control flow that doesn't have explicit branches or direct
|
|
|
|
// fallthrough (e.g. try/catch), which can't be modeled by analyzeBranch. It
|
|
|
|
// is created after CFGStackify.
|
|
|
|
if (MFI.isCFGStackified())
|
|
|
|
return true;
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
bool HaveCond = false;
|
2015-12-22 01:22:02 +08:00
|
|
|
for (MachineInstr &MI : MBB.terminators()) {
|
2015-09-17 00:51:30 +08:00
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
default:
|
|
|
|
// Unhandled instruction; bail out.
|
|
|
|
return true;
|
2015-11-13 08:46:31 +08:00
|
|
|
case WebAssembly::BR_IF:
|
2015-09-17 00:51:30 +08:00
|
|
|
if (HaveCond)
|
|
|
|
return true;
|
2015-12-05 11:03:35 +08:00
|
|
|
Cond.push_back(MachineOperand::CreateImm(true));
|
2016-02-09 05:50:13 +08:00
|
|
|
Cond.push_back(MI.getOperand(1));
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
2015-12-05 11:03:35 +08:00
|
|
|
HaveCond = true;
|
|
|
|
break;
|
|
|
|
case WebAssembly::BR_UNLESS:
|
|
|
|
if (HaveCond)
|
|
|
|
return true;
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(false));
|
2016-02-09 05:50:13 +08:00
|
|
|
Cond.push_back(MI.getOperand(1));
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
2015-09-17 00:51:30 +08:00
|
|
|
HaveCond = true;
|
|
|
|
break;
|
|
|
|
case WebAssembly::BR:
|
|
|
|
if (!HaveCond)
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
|
|
|
else
|
|
|
|
FBB = MI.getOperand(0).getMBB();
|
|
|
|
break;
|
[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
|
|
|
case WebAssembly::BR_ON_EXN:
|
|
|
|
if (HaveCond)
|
|
|
|
return true;
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(true));
|
|
|
|
Cond.push_back(MI.getOperand(2));
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
|
|
|
HaveCond = true;
|
|
|
|
break;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|
|
|
|
if (MI.isBarrier())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-15 04:43:16 +08:00
|
|
|
unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
|
2016-09-15 01:23:48 +08:00
|
|
|
int *BytesRemoved) const {
|
|
|
|
assert(!BytesRemoved && "code size not handled");
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
MachineBasicBlock::instr_iterator I = MBB.instr_end();
|
|
|
|
unsigned Count = 0;
|
|
|
|
|
|
|
|
while (I != MBB.instr_begin()) {
|
|
|
|
--I;
|
2018-05-09 10:42:00 +08:00
|
|
|
if (I->isDebugInstr())
|
2015-09-17 00:51:30 +08:00
|
|
|
continue;
|
|
|
|
if (!I->isTerminator())
|
|
|
|
break;
|
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
|
|
|
I = MBB.instr_end();
|
|
|
|
++Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2018-09-05 09:27:38 +08:00
|
|
|
unsigned WebAssemblyInstrInfo::insertBranch(
|
|
|
|
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
|
|
|
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
|
2016-09-15 01:23:48 +08:00
|
|
|
assert(!BytesAdded && "code size not handled");
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
if (Cond.empty()) {
|
|
|
|
if (!TBB)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-12-05 11:03:35 +08:00
|
|
|
assert(Cond.size() == 2 && "Expected a flag and a successor block");
|
|
|
|
|
[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
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
auto &MRI = MF.getRegInfo();
|
|
|
|
bool IsBrOnExn = Cond[1].isReg() && MRI.getRegClass(Cond[1].getReg()) ==
|
|
|
|
&WebAssembly::EXCEPT_REFRegClass;
|
|
|
|
|
2015-12-05 11:03:35 +08:00
|
|
|
if (Cond[0].getImm()) {
|
[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
|
|
|
if (IsBrOnExn) {
|
|
|
|
const char *CPPExnSymbol = MF.createExternalSymbolName("__cpp_exception");
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_ON_EXN))
|
|
|
|
.addMBB(TBB)
|
|
|
|
.addExternalSymbol(CPPExnSymbol, WebAssemblyII::MO_SYMBOL_EVENT)
|
|
|
|
.add(Cond[1]);
|
|
|
|
} else
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]);
|
2015-12-05 11:03:35 +08:00
|
|
|
} else {
|
[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
|
|
|
assert(!IsBrOnExn && "br_on_exn does not have a reversed condition");
|
2017-01-13 17:58:52 +08:00
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]);
|
2015-12-05 11:03:35 +08:00
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
if (!FBB)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2016-09-15 04:43:16 +08:00
|
|
|
bool WebAssemblyInstrInfo::reverseBranchCondition(
|
2015-09-17 00:51:30 +08:00
|
|
|
SmallVectorImpl<MachineOperand> &Cond) const {
|
[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
|
|
|
assert(Cond.size() == 2 && "Expected a flag and a condition expression");
|
|
|
|
|
|
|
|
// br_on_exn's condition cannot be reversed
|
|
|
|
MachineFunction &MF = *Cond[1].getParent()->getParent()->getParent();
|
|
|
|
auto &MRI = MF.getRegInfo();
|
|
|
|
if (Cond[1].isReg() &&
|
|
|
|
MRI.getRegClass(Cond[1].getReg()) == &WebAssembly::EXCEPT_REFRegClass)
|
|
|
|
return true;
|
|
|
|
|
2015-12-05 11:03:35 +08:00
|
|
|
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
|
|
|
|
return false;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|