2015-09-17 00:51:30 +08:00
|
|
|
//===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===//
|
|
|
|
//
|
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-09-17 00:51:30 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
2018-05-01 23:54:18 +08:00
|
|
|
/// This file implements a CFG stacking pass.
|
2015-09-17 00:51:30 +08:00
|
|
|
///
|
2018-08-17 07:50:59 +08:00
|
|
|
/// This pass inserts BLOCK, LOOP, and TRY markers to mark the start of scopes,
|
|
|
|
/// since scope boundaries serve as the labels for WebAssembly's control
|
|
|
|
/// transfers.
|
2015-09-17 00:51:30 +08:00
|
|
|
///
|
|
|
|
/// This is sufficient to convert arbitrary CFGs into a form that works on
|
|
|
|
/// WebAssembly, provided that all loops are single-entry.
|
|
|
|
///
|
2018-08-17 07:50:59 +08:00
|
|
|
/// In case we use exceptions, this pass also fixes mismatches in unwind
|
|
|
|
/// destinations created during transforming CFG into wasm structured format.
|
|
|
|
///
|
2015-09-17 00:51:30 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "WebAssembly.h"
|
2018-08-17 07:50:59 +08:00
|
|
|
#include "WebAssemblyExceptionInfo.h"
|
2016-01-30 13:01:06 +08:00
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
2015-09-17 00:51:30 +08:00
|
|
|
#include "WebAssemblySubtarget.h"
|
2016-10-25 03:49:43 +08:00
|
|
|
#include "WebAssemblyUtilities.h"
|
2015-11-24 00:19:56 +08:00
|
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
2015-09-17 00:51:30 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
2016-01-14 01:10:28 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2015-09-17 00:51:30 +08:00
|
|
|
#include "llvm/CodeGen/Passes.h"
|
2018-08-17 07:50:59 +08:00
|
|
|
#include "llvm/CodeGen/WasmEHFuncInfo.h"
|
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2015-09-17 00:51:30 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
[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
|
|
|
#include <cstring>
|
2015-09-17 00:51:30 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "wasm-cfg-stackify"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class WebAssemblyCFGStackify final : public MachineFunctionPass {
|
2016-10-01 10:56:57 +08:00
|
|
|
StringRef getPassName() const override { return "WebAssembly CFG Stackify"; }
|
2015-09-17 00:51:30 +08:00
|
|
|
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2015-11-24 00:19:56 +08:00
|
|
|
AU.addRequired<MachineDominatorTree>();
|
2015-09-17 00:51:30 +08:00
|
|
|
AU.addRequired<MachineLoopInfo>();
|
2018-08-17 07:50:59 +08:00
|
|
|
AU.addRequired<WebAssemblyExceptionInfo>();
|
2015-09-17 00:51:30 +08:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// For each block whose label represents the end of a scope, record the block
|
|
|
|
// which holds the beginning of the scope. This will allow us to quickly skip
|
|
|
|
// over scoped regions when walking blocks.
|
|
|
|
SmallVector<MachineBasicBlock *, 8> ScopeTops;
|
|
|
|
|
|
|
|
void placeMarkers(MachineFunction &MF);
|
|
|
|
void placeBlockMarker(MachineBasicBlock &MBB);
|
|
|
|
void placeLoopMarker(MachineBasicBlock &MBB);
|
|
|
|
void placeTryMarker(MachineBasicBlock &MBB);
|
2019-02-27 08:50:53 +08:00
|
|
|
void removeUnnecessaryInstrs(MachineFunction &MF);
|
2018-08-17 07:50:59 +08:00
|
|
|
void rewriteDepthImmediates(MachineFunction &MF);
|
|
|
|
void fixEndsAtEndOfFunction(MachineFunction &MF);
|
|
|
|
|
|
|
|
// For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY).
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
|
|
|
|
// For each END_(BLOCK|LOOP|TRY), the corresponding BLOCK|LOOP|TRY.
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
|
|
|
|
// <TRY marker, EH pad> map
|
|
|
|
DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
|
|
|
|
// <EH pad, TRY marker> map
|
|
|
|
DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
|
|
|
|
|
2019-02-27 08:50:53 +08:00
|
|
|
// Helper functions to register / unregister scope information created by
|
|
|
|
// marker instructions.
|
2018-08-17 07:50:59 +08:00
|
|
|
void registerScope(MachineInstr *Begin, MachineInstr *End);
|
|
|
|
void registerTryScope(MachineInstr *Begin, MachineInstr *End,
|
|
|
|
MachineBasicBlock *EHPad);
|
2019-02-27 08:50:53 +08:00
|
|
|
void unregisterScope(MachineInstr *Begin);
|
2018-08-17 07:50:59 +08:00
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
public:
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
|
2018-08-17 07:50:59 +08:00
|
|
|
~WebAssemblyCFGStackify() override { releaseMemory(); }
|
|
|
|
void releaseMemory() override;
|
2015-09-17 00:51:30 +08:00
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
char WebAssemblyCFGStackify::ID = 0;
|
2018-03-31 04:36:58 +08:00
|
|
|
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
|
2018-09-05 09:27:38 +08:00
|
|
|
"Insert BLOCK and LOOP markers for WebAssembly scopes", false,
|
|
|
|
false)
|
2018-03-31 04:36:58 +08:00
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
FunctionPass *llvm::createWebAssemblyCFGStackify() {
|
|
|
|
return new WebAssemblyCFGStackify();
|
|
|
|
}
|
|
|
|
|
2015-12-17 03:06:41 +08:00
|
|
|
/// Test whether Pred has any terminators explicitly branching to MBB, as
|
|
|
|
/// opposed to falling through. Note that it's possible (eg. in unoptimized
|
|
|
|
/// code) for a branch instruction to both branch to a block and fallthrough
|
|
|
|
/// to it, so we check the actual branch operands to see if there are any
|
|
|
|
/// explicit mentions.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
static bool explicitlyBranchesTo(MachineBasicBlock *Pred,
|
2016-01-08 09:06:00 +08:00
|
|
|
MachineBasicBlock *MBB) {
|
2015-12-17 03:06:41 +08:00
|
|
|
for (MachineInstr &MI : Pred->terminators())
|
[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
|
|
|
for (MachineOperand &MO : MI.explicit_operands())
|
|
|
|
if (MO.isMBB() && MO.getMBB() == MBB)
|
|
|
|
return true;
|
2015-12-17 03:06:41 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Returns an iterator to the earliest position possible within the MBB,
|
|
|
|
// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
|
|
|
|
// contains instructions that should go before the marker, and AfterSet contains
|
|
|
|
// ones that should go after the marker. In this function, AfterSet is only
|
|
|
|
// used for sanity checking.
|
|
|
|
static MachineBasicBlock::iterator
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
getEarliestInsertPos(MachineBasicBlock *MBB,
|
2018-08-17 07:50:59 +08:00
|
|
|
const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
|
|
|
|
const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
|
|
|
|
auto InsertPos = MBB->end();
|
|
|
|
while (InsertPos != MBB->begin()) {
|
|
|
|
if (BeforeSet.count(&*std::prev(InsertPos))) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Sanity check
|
|
|
|
for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos)
|
|
|
|
assert(!AfterSet.count(&*std::prev(Pos)));
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
--InsertPos;
|
|
|
|
}
|
|
|
|
return InsertPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns an iterator to the latest position possible within the MBB,
|
|
|
|
// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
|
|
|
|
// contains instructions that should go before the marker, and AfterSet contains
|
|
|
|
// ones that should go after the marker. In this function, BeforeSet is only
|
|
|
|
// used for sanity checking.
|
|
|
|
static MachineBasicBlock::iterator
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
getLatestInsertPos(MachineBasicBlock *MBB,
|
2018-08-17 07:50:59 +08:00
|
|
|
const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
|
|
|
|
const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
|
|
|
|
auto InsertPos = MBB->begin();
|
|
|
|
while (InsertPos != MBB->end()) {
|
|
|
|
if (AfterSet.count(&*InsertPos)) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Sanity check
|
|
|
|
for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos)
|
|
|
|
assert(!BeforeSet.count(&*Pos));
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++InsertPos;
|
|
|
|
}
|
|
|
|
return InsertPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin,
|
|
|
|
MachineInstr *End) {
|
|
|
|
BeginToEnd[Begin] = End;
|
|
|
|
EndToBegin[End] = Begin;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
|
|
|
|
MachineInstr *End,
|
|
|
|
MachineBasicBlock *EHPad) {
|
|
|
|
registerScope(Begin, End);
|
|
|
|
TryToEHPad[Begin] = EHPad;
|
|
|
|
EHPadToTry[EHPad] = Begin;
|
|
|
|
}
|
|
|
|
|
2019-02-27 08:50:53 +08:00
|
|
|
void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
|
|
|
|
assert(BeginToEnd.count(Begin));
|
|
|
|
MachineInstr *End = BeginToEnd[Begin];
|
|
|
|
assert(EndToBegin.count(End));
|
|
|
|
BeginToEnd.erase(Begin);
|
|
|
|
EndToBegin.erase(End);
|
|
|
|
MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin);
|
|
|
|
if (EHPad) {
|
|
|
|
assert(EHPadToTry.count(EHPad));
|
|
|
|
TryToEHPad.erase(Begin);
|
|
|
|
EHPadToTry.erase(EHPad);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-24 00:19:56 +08:00
|
|
|
/// Insert a BLOCK marker for branches to MBB (if needed).
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) {
|
2019-03-27 01:15:55 +08:00
|
|
|
assert(!MBB.isEHPad());
|
2018-08-17 07:50:59 +08:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
auto &MDT = getAnalysis<MachineDominatorTree>();
|
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
|
2015-12-15 06:51:54 +08:00
|
|
|
// First compute the nearest common dominator of all forward non-fallthrough
|
|
|
|
// predecessors so that we minimize the time that the BLOCK is on the stack,
|
|
|
|
// which reduces overall stack height.
|
2015-11-24 00:19:56 +08:00
|
|
|
MachineBasicBlock *Header = nullptr;
|
|
|
|
bool IsBranchedTo = false;
|
[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
|
|
|
bool IsBrOnExn = false;
|
|
|
|
MachineInstr *BrOnExn = nullptr;
|
2015-11-24 00:19:56 +08:00
|
|
|
int MBBNumber = MBB.getNumber();
|
2018-08-17 07:50:59 +08:00
|
|
|
for (MachineBasicBlock *Pred : MBB.predecessors()) {
|
2015-11-24 00:19:56 +08:00
|
|
|
if (Pred->getNumber() < MBBNumber) {
|
|
|
|
Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
if (explicitlyBranchesTo(Pred, &MBB)) {
|
2015-11-24 00:19:56 +08:00
|
|
|
IsBranchedTo = true;
|
[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 (Pred->getFirstTerminator()->getOpcode() == WebAssembly::BR_ON_EXN) {
|
|
|
|
IsBrOnExn = true;
|
|
|
|
assert(!BrOnExn && "There should be only one br_on_exn per block");
|
|
|
|
BrOnExn = &*Pred->getFirstTerminator();
|
|
|
|
}
|
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
2015-11-24 00:19:56 +08:00
|
|
|
if (!Header)
|
|
|
|
return;
|
|
|
|
if (!IsBranchedTo)
|
|
|
|
return;
|
|
|
|
|
2015-12-15 06:51:54 +08:00
|
|
|
assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors");
|
2019-03-06 05:05:09 +08:00
|
|
|
MachineBasicBlock *LayoutPred = MBB.getPrevNode();
|
2015-12-15 06:51:54 +08:00
|
|
|
|
|
|
|
// If the nearest common dominator is inside a more deeply nested context,
|
|
|
|
// walk out to the nearest scope which isn't more deeply nested.
|
|
|
|
for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
|
|
|
|
if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
|
|
|
|
if (ScopeTop->getNumber() > Header->getNumber()) {
|
|
|
|
// Skip over an intervening scope.
|
2019-03-06 05:05:09 +08:00
|
|
|
I = std::next(ScopeTop->getIterator());
|
2015-12-15 06:51:54 +08:00
|
|
|
} else {
|
|
|
|
// We found a scope level at an appropriate depth.
|
|
|
|
Header = ScopeTop;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decide where in Header to put the BLOCK.
|
2018-08-17 07:50:59 +08:00
|
|
|
|
|
|
|
// Instructions that should go before the BLOCK.
|
|
|
|
SmallPtrSet<const MachineInstr *, 4> BeforeSet;
|
|
|
|
// Instructions that should go after the BLOCK.
|
|
|
|
SmallPtrSet<const MachineInstr *, 4> AfterSet;
|
|
|
|
for (const auto &MI : *Header) {
|
2019-03-27 01:15:55 +08:00
|
|
|
// If there is a previously placed LOOP marker and the bottom block of the
|
|
|
|
// loop is above MBB, it should be after the BLOCK, because the loop is
|
|
|
|
// nested in this BLOCK. Otherwise it should be before the BLOCK.
|
|
|
|
if (MI.getOpcode() == WebAssembly::LOOP) {
|
|
|
|
auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
|
|
|
|
if (MBB.getNumber() > LoopBottom->getNumber())
|
2018-08-17 07:50:59 +08:00
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
// All previously inserted BLOCK/TRY markers should be after the BLOCK
|
|
|
|
// because they are all nested blocks.
|
|
|
|
if (MI.getOpcode() == WebAssembly::BLOCK ||
|
|
|
|
MI.getOpcode() == WebAssembly::TRY)
|
2018-08-17 07:50:59 +08:00
|
|
|
AfterSet.insert(&MI);
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_BLOCK ||
|
|
|
|
MI.getOpcode() == WebAssembly::END_LOOP ||
|
|
|
|
MI.getOpcode() == WebAssembly::END_TRY)
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Terminators should go after the BLOCK.
|
|
|
|
if (MI.isTerminator())
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Local expression tree should go after the BLOCK.
|
|
|
|
for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
|
|
|
|
--I) {
|
2018-10-05 07:31:00 +08:00
|
|
|
if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
|
|
|
|
continue;
|
2018-08-17 07:50:59 +08:00
|
|
|
if (WebAssembly::isChild(*std::prev(I), MFI))
|
|
|
|
AfterSet.insert(&*std::prev(I));
|
|
|
|
else
|
|
|
|
break;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|
|
|
|
|
2015-12-15 06:51:54 +08:00
|
|
|
// Add the 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
|
|
|
|
|
|
|
// 'br_on_exn' extracts except_ref object and pushes variable number of values
|
|
|
|
// depending on its tag. For C++ exception, its a single i32 value, and the
|
|
|
|
// generated code will be in the form of:
|
|
|
|
// block i32
|
|
|
|
// br_on_exn 0, $__cpp_exception
|
|
|
|
// rethrow
|
|
|
|
// end_block
|
|
|
|
WebAssembly::ExprType ReturnType = WebAssembly::ExprType::Void;
|
|
|
|
if (IsBrOnExn) {
|
|
|
|
const char *TagName = BrOnExn->getOperand(1).getSymbolName();
|
|
|
|
if (std::strcmp(TagName, "__cpp_exception") != 0)
|
|
|
|
llvm_unreachable("Only C++ exception is supported");
|
|
|
|
ReturnType = WebAssembly::ExprType::I32;
|
|
|
|
}
|
|
|
|
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
|
2018-04-14 08:12:12 +08:00
|
|
|
MachineInstr *Begin =
|
|
|
|
BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
|
|
|
|
TII.get(WebAssembly::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
|
|
|
.addImm(int64_t(ReturnType));
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Decide where in Header to put the END_BLOCK.
|
|
|
|
BeforeSet.clear();
|
|
|
|
AfterSet.clear();
|
|
|
|
for (auto &MI : MBB) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// END_BLOCK should precede existing LOOP and TRY markers.
|
|
|
|
if (MI.getOpcode() == WebAssembly::LOOP ||
|
|
|
|
MI.getOpcode() == WebAssembly::TRY)
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// If there is a previously placed END_LOOP marker and the header of the
|
|
|
|
// loop is above this block's header, the END_LOOP should be placed after
|
|
|
|
// the BLOCK, because the loop contains this block. Otherwise the END_LOOP
|
|
|
|
// should be placed before the BLOCK. The same for END_TRY.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP ||
|
|
|
|
MI.getOpcode() == WebAssembly::END_TRY) {
|
|
|
|
if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
// Mark the end of the block.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
|
2018-03-16 06:06:51 +08:00
|
|
|
MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
|
2016-10-07 06:29:32 +08:00
|
|
|
TII.get(WebAssembly::END_BLOCK));
|
2018-08-17 07:50:59 +08:00
|
|
|
registerScope(Begin, End);
|
2015-12-15 06:51:54 +08:00
|
|
|
|
|
|
|
// Track the farthest-spanning scope that ends at this point.
|
|
|
|
int Number = MBB.getNumber();
|
|
|
|
if (!ScopeTops[Number] ||
|
|
|
|
ScopeTops[Number]->getNumber() > Header->getNumber())
|
|
|
|
ScopeTops[Number] = Header;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) {
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
const auto &MLI = getAnalysis<MachineLoopInfo>();
|
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
|
2015-12-15 06:51:54 +08:00
|
|
|
MachineLoop *Loop = MLI.getLoopFor(&MBB);
|
|
|
|
if (!Loop || Loop->getHeader() != &MBB)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// The operand of a LOOP is the first block after the loop. If the loop is the
|
|
|
|
// bottom of the function, insert a dummy block at the end.
|
2018-06-19 08:32:03 +08:00
|
|
|
MachineBasicBlock *Bottom = WebAssembly::getBottom(Loop);
|
2019-03-06 05:05:09 +08:00
|
|
|
auto Iter = std::next(Bottom->getIterator());
|
2015-12-15 06:51:54 +08:00
|
|
|
if (Iter == MF.end()) {
|
|
|
|
MachineBasicBlock *Label = MF.CreateMachineBasicBlock();
|
|
|
|
// Give it a fake predecessor so that AsmPrinter prints its label.
|
|
|
|
Label->addSuccessor(Label);
|
|
|
|
MF.push_back(Label);
|
2019-03-06 05:05:09 +08:00
|
|
|
Iter = std::next(Bottom->getIterator());
|
2015-12-15 06:51:54 +08:00
|
|
|
}
|
|
|
|
MachineBasicBlock *AfterLoop = &*Iter;
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Decide where in Header to put the LOOP.
|
|
|
|
SmallPtrSet<const MachineInstr *, 4> BeforeSet;
|
|
|
|
SmallPtrSet<const MachineInstr *, 4> AfterSet;
|
|
|
|
for (const auto &MI : MBB) {
|
|
|
|
// LOOP marker should be after any existing loop that ends here. Otherwise
|
|
|
|
// we assume the instruction belongs to the loop.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP)
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the beginning of the loop.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
|
2018-03-16 06:06:51 +08:00
|
|
|
MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
|
2016-10-07 06:29:32 +08:00
|
|
|
TII.get(WebAssembly::LOOP))
|
2018-03-16 06:06:51 +08:00
|
|
|
.addImm(int64_t(WebAssembly::ExprType::Void));
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Decide where in Header to put the END_LOOP.
|
|
|
|
BeforeSet.clear();
|
|
|
|
AfterSet.clear();
|
|
|
|
#ifndef NDEBUG
|
|
|
|
for (const auto &MI : MBB)
|
|
|
|
// Existing END_LOOP markers belong to parent loops of this loop
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP)
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Mark the end of the loop (using arbitrary debug location that branched to
|
|
|
|
// the loop end as its location).
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
|
2018-03-16 06:06:51 +08:00
|
|
|
DebugLoc EndDL = (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
|
2018-08-17 07:50:59 +08:00
|
|
|
MachineInstr *End =
|
|
|
|
BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
|
|
|
|
registerScope(Begin, End);
|
2015-12-15 06:51:54 +08:00
|
|
|
|
|
|
|
assert((!ScopeTops[AfterLoop->getNumber()] ||
|
|
|
|
ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
|
2016-02-17 00:22:41 +08:00
|
|
|
"With block sorting the outermost loop for a block should be first.");
|
2015-12-15 06:51:54 +08:00
|
|
|
if (!ScopeTops[AfterLoop->getNumber()])
|
|
|
|
ScopeTops[AfterLoop->getNumber()] = &MBB;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
|
2019-03-27 01:15:55 +08:00
|
|
|
assert(MBB.isEHPad());
|
2018-08-17 07:50:59 +08:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
auto &MDT = getAnalysis<MachineDominatorTree>();
|
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
|
|
|
|
const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
|
|
|
|
// Compute the nearest common dominator of all unwind predecessors
|
|
|
|
MachineBasicBlock *Header = nullptr;
|
|
|
|
int MBBNumber = MBB.getNumber();
|
|
|
|
for (auto *Pred : MBB.predecessors()) {
|
|
|
|
if (Pred->getNumber() < MBBNumber) {
|
|
|
|
Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
assert(!explicitlyBranchesTo(Pred, &MBB) &&
|
2018-08-17 07:50:59 +08:00
|
|
|
"Explicit branch to an EH pad!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!Header)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If this try is at the bottom of the function, insert a dummy block at the
|
|
|
|
// end.
|
|
|
|
WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
|
|
|
|
assert(WE);
|
|
|
|
MachineBasicBlock *Bottom = WebAssembly::getBottom(WE);
|
|
|
|
|
2019-03-06 05:05:09 +08:00
|
|
|
auto Iter = std::next(Bottom->getIterator());
|
2018-08-17 07:50:59 +08:00
|
|
|
if (Iter == MF.end()) {
|
|
|
|
MachineBasicBlock *Label = MF.CreateMachineBasicBlock();
|
|
|
|
// Give it a fake predecessor so that AsmPrinter prints its label.
|
|
|
|
Label->addSuccessor(Label);
|
|
|
|
MF.push_back(Label);
|
2019-03-06 05:05:09 +08:00
|
|
|
Iter = std::next(Bottom->getIterator());
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
2019-02-24 16:30:06 +08:00
|
|
|
MachineBasicBlock *Cont = &*Iter;
|
2018-08-17 07:50:59 +08:00
|
|
|
|
2019-02-24 16:30:06 +08:00
|
|
|
assert(Cont != &MF.front());
|
2019-03-06 05:05:09 +08:00
|
|
|
MachineBasicBlock *LayoutPred = Cont->getPrevNode();
|
2018-08-17 07:50:59 +08:00
|
|
|
|
|
|
|
// If the nearest common dominator is inside a more deeply nested context,
|
|
|
|
// walk out to the nearest scope which isn't more deeply nested.
|
|
|
|
for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
|
|
|
|
if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
|
|
|
|
if (ScopeTop->getNumber() > Header->getNumber()) {
|
|
|
|
// Skip over an intervening scope.
|
2019-03-06 05:05:09 +08:00
|
|
|
I = std::next(ScopeTop->getIterator());
|
2018-08-17 07:50:59 +08:00
|
|
|
} else {
|
|
|
|
// We found a scope level at an appropriate depth.
|
|
|
|
Header = ScopeTop;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decide where in Header to put the TRY.
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
// Instructions that should go before the TRY.
|
2018-08-17 07:50:59 +08:00
|
|
|
SmallPtrSet<const MachineInstr *, 4> BeforeSet;
|
2019-03-27 01:15:55 +08:00
|
|
|
// Instructions that should go after the TRY.
|
2018-08-17 07:50:59 +08:00
|
|
|
SmallPtrSet<const MachineInstr *, 4> AfterSet;
|
|
|
|
for (const auto &MI : *Header) {
|
2019-03-27 01:15:55 +08:00
|
|
|
// If there is a previously placed LOOP marker and the bottom block of the
|
|
|
|
// loop is above MBB, it should be after the TRY, because the loop is nested
|
|
|
|
// in this TRY. Otherwise it should be before the TRY.
|
2018-08-17 07:50:59 +08:00
|
|
|
if (MI.getOpcode() == WebAssembly::LOOP) {
|
2019-03-27 01:15:55 +08:00
|
|
|
auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
|
|
|
|
if (MBB.getNumber() > LoopBottom->getNumber())
|
2018-08-17 07:50:59 +08:00
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
// All previously inserted BLOCK/TRY markers should be after the TRY because
|
|
|
|
// they are all nested trys.
|
|
|
|
if (MI.getOpcode() == WebAssembly::BLOCK ||
|
|
|
|
MI.getOpcode() == WebAssembly::TRY)
|
2018-08-17 07:50:59 +08:00
|
|
|
AfterSet.insert(&MI);
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2019-03-27 01:15:55 +08:00
|
|
|
// All END_(BLOCK/LOOP/TRY) markers should be before the TRY.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_BLOCK ||
|
|
|
|
MI.getOpcode() == WebAssembly::END_LOOP ||
|
2018-08-17 07:50:59 +08:00
|
|
|
MI.getOpcode() == WebAssembly::END_TRY)
|
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Terminators should go after the TRY.
|
|
|
|
if (MI.isTerminator())
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Local expression tree should go after the TRY.
|
|
|
|
for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
|
|
|
|
--I) {
|
2018-10-05 07:31:00 +08:00
|
|
|
if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
|
|
|
|
continue;
|
2018-08-17 07:50:59 +08:00
|
|
|
if (WebAssembly::isChild(*std::prev(I), MFI))
|
|
|
|
AfterSet.insert(&*std::prev(I));
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If Header unwinds to MBB (= Header contains 'invoke'), the try block should
|
|
|
|
// contain the call within it. So the call should go after the TRY. The
|
|
|
|
// exception is when the header's terminator is a rethrow instruction, in
|
|
|
|
// which case that instruction, not a call instruction before it, is gonna
|
|
|
|
// throw.
|
|
|
|
if (MBB.isPredecessor(Header)) {
|
|
|
|
auto TermPos = Header->getFirstTerminator();
|
[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 (TermPos == Header->end() ||
|
|
|
|
TermPos->getOpcode() != WebAssembly::RETHROW) {
|
2018-08-17 07:50:59 +08:00
|
|
|
for (const auto &MI : reverse(*Header)) {
|
|
|
|
if (MI.isCall()) {
|
|
|
|
AfterSet.insert(&MI);
|
[WebAssembly] Place 'try' and 'catch' correctly wrt EH_LABELs
Summary:
After instruction selection phase, possibly-throwing calls, which were
previously invoke, are wrapped in `EH_LABEL` instructions. For example:
```
EH_LABEL <mcsymbol .Ltmp0>
CALL_VOID @foo ...
EH_LABEL <mcsymbol .Ltmp1>
```
`EH_LABEL` is placed also in the beginning of EH pads:
```
bb.1 (landing-pad):
EH_LABEL <mcsymbol .Ltmp2>
...
```
And we'd like to maintian this relationship, so when we place a `try`,
```
TRY ...
EH_LABEL <mcsymbol .Ltmp0>
CALL_VOID @foo ...
EH_LABEL <mcsymbol .Ltmp1>
```
When we place a `catch`,
```
bb.1 (landing-pad):
EH_LABEL <mcsymbol .Ltmp2>
%0:except_ref = CATCH ...
...
```
Previously we didn't treat EH_LABELs specially, so `try` was placed
right before a call, and `catch` was placed in the beginning of an EH
pad.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58914
llvm-svn: 355996
2019-03-13 08:37:31 +08:00
|
|
|
// Possibly throwing calls are usually wrapped by EH_LABEL
|
|
|
|
// instructions. We don't want to split them and the call.
|
|
|
|
if (MI.getIterator() != Header->begin() &&
|
|
|
|
std::prev(MI.getIterator())->isEHLabel())
|
|
|
|
AfterSet.insert(&*std::prev(MI.getIterator()));
|
2018-08-17 07:50:59 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the TRY.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
|
2018-08-17 07:50:59 +08:00
|
|
|
MachineInstr *Begin =
|
|
|
|
BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
|
|
|
|
TII.get(WebAssembly::TRY))
|
|
|
|
.addImm(int64_t(WebAssembly::ExprType::Void));
|
|
|
|
|
|
|
|
// Decide where in Header to put the END_TRY.
|
|
|
|
BeforeSet.clear();
|
|
|
|
AfterSet.clear();
|
2019-02-24 16:30:06 +08:00
|
|
|
for (const auto &MI : *Cont) {
|
2018-08-17 07:50:59 +08:00
|
|
|
#ifndef NDEBUG
|
2019-03-27 01:15:55 +08:00
|
|
|
// END_TRY should precede existing LOOP and BLOCK markers.
|
|
|
|
if (MI.getOpcode() == WebAssembly::LOOP ||
|
|
|
|
MI.getOpcode() == WebAssembly::BLOCK)
|
2018-08-17 07:50:59 +08:00
|
|
|
AfterSet.insert(&MI);
|
|
|
|
|
|
|
|
// All END_TRY markers placed earlier belong to exceptions that contains
|
|
|
|
// this one.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_TRY)
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// If there is a previously placed END_LOOP marker and its header is after
|
|
|
|
// where TRY marker is, this loop is contained within the 'catch' part, so
|
|
|
|
// the END_TRY marker should go after that. Otherwise, the whole try-catch
|
|
|
|
// is contained within this loop, so the END_TRY should go before that.
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP) {
|
2019-03-27 01:29:55 +08:00
|
|
|
// For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they
|
|
|
|
// are in the same BB, LOOP is always before TRY.
|
|
|
|
if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber())
|
2018-08-17 07:50:59 +08:00
|
|
|
BeforeSet.insert(&MI);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
AfterSet.insert(&MI);
|
|
|
|
#endif
|
|
|
|
}
|
2019-03-27 01:15:55 +08:00
|
|
|
|
|
|
|
// It is not possible for an END_BLOCK to be already in this block.
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the end of the TRY.
|
2019-02-24 16:30:06 +08:00
|
|
|
InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet);
|
2018-08-17 07:50:59 +08:00
|
|
|
MachineInstr *End =
|
2019-02-24 16:30:06 +08:00
|
|
|
BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(),
|
2018-08-17 07:50:59 +08:00
|
|
|
TII.get(WebAssembly::END_TRY));
|
|
|
|
registerTryScope(Begin, End, &MBB);
|
|
|
|
|
2019-02-27 09:35:14 +08:00
|
|
|
// Track the farthest-spanning scope that ends at this point. We create two
|
|
|
|
// mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB
|
|
|
|
// with 'try'). We need to create 'catch' -> 'try' mapping here too because
|
|
|
|
// markers should not span across 'catch'. For example, this should not
|
|
|
|
// happen:
|
|
|
|
//
|
|
|
|
// try
|
|
|
|
// block --| (X)
|
|
|
|
// catch |
|
|
|
|
// end_block --|
|
|
|
|
// end_try
|
|
|
|
for (int Number : {Cont->getNumber(), MBB.getNumber()}) {
|
|
|
|
if (!ScopeTops[Number] ||
|
|
|
|
ScopeTops[Number]->getNumber() > Header->getNumber())
|
|
|
|
ScopeTops[Number] = Header;
|
|
|
|
}
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 08:50:53 +08:00
|
|
|
void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
|
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
|
|
|
|
// When there is an unconditional branch right before a catch instruction and
|
|
|
|
// it branches to the end of end_try marker, we don't need the branch, because
|
|
|
|
// it there is no exception, the control flow transfers to that point anyway.
|
|
|
|
// bb0:
|
|
|
|
// try
|
|
|
|
// ...
|
|
|
|
// br bb2 <- Not necessary
|
|
|
|
// bb1:
|
|
|
|
// catch
|
|
|
|
// ...
|
|
|
|
// bb2:
|
|
|
|
// end
|
|
|
|
for (auto &MBB : MF) {
|
|
|
|
if (!MBB.isEHPad())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
|
|
|
|
SmallVector<MachineOperand, 4> Cond;
|
2019-03-06 05:05:09 +08:00
|
|
|
MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode();
|
2019-02-27 08:50:53 +08:00
|
|
|
MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent();
|
|
|
|
bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
|
|
|
|
if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
|
|
|
|
(!Cond.empty() && FBB && FBB == Cont)))
|
|
|
|
TII.removeBranch(*EHPadLayoutPred);
|
|
|
|
}
|
|
|
|
|
|
|
|
// When there are block / end_block markers that overlap with try / end_try
|
|
|
|
// markers, and the block and try markers' return types are the same, the
|
|
|
|
// block /end_block markers are not necessary, because try / end_try markers
|
|
|
|
// also can serve as boundaries for branches.
|
|
|
|
// block <- Not necessary
|
|
|
|
// try
|
|
|
|
// ...
|
|
|
|
// catch
|
|
|
|
// ...
|
|
|
|
// end
|
|
|
|
// end <- Not necessary
|
|
|
|
SmallVector<MachineInstr *, 32> ToDelete;
|
|
|
|
for (auto &MBB : MF) {
|
|
|
|
for (auto &MI : MBB) {
|
|
|
|
if (MI.getOpcode() != WebAssembly::TRY)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
|
|
|
|
MachineBasicBlock *TryBB = Try->getParent();
|
|
|
|
MachineBasicBlock *Cont = EndTry->getParent();
|
|
|
|
int64_t RetType = Try->getOperand(0).getImm();
|
2019-03-06 05:05:09 +08:00
|
|
|
for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator());
|
2019-02-27 08:50:53 +08:00
|
|
|
B != TryBB->begin() && E != Cont->end() &&
|
|
|
|
std::prev(B)->getOpcode() == WebAssembly::BLOCK &&
|
|
|
|
E->getOpcode() == WebAssembly::END_BLOCK &&
|
|
|
|
std::prev(B)->getOperand(0).getImm() == RetType;
|
|
|
|
--B, ++E) {
|
|
|
|
ToDelete.push_back(&*std::prev(B));
|
|
|
|
ToDelete.push_back(&*E);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto *MI : ToDelete) {
|
|
|
|
if (MI->getOpcode() == WebAssembly::BLOCK)
|
|
|
|
unregisterScope(MI);
|
|
|
|
MI->eraseFromParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
static unsigned
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
const MachineBasicBlock *MBB) {
|
|
|
|
unsigned Depth = 0;
|
|
|
|
for (auto X : reverse(Stack)) {
|
|
|
|
if (X == MBB)
|
|
|
|
break;
|
|
|
|
++Depth;
|
|
|
|
}
|
|
|
|
assert(Depth < Stack.size() && "Branch destination should be in scope");
|
|
|
|
return Depth;
|
|
|
|
}
|
|
|
|
|
2016-10-07 06:29:32 +08:00
|
|
|
/// In normal assembly languages, when the end of a function is unreachable,
|
|
|
|
/// because the function ends in an infinite loop or a noreturn call or similar,
|
|
|
|
/// it isn't necessary to worry about the function return type at the end of
|
|
|
|
/// the function, because it's never reached. However, in WebAssembly, blocks
|
|
|
|
/// that end at the function end need to have a return type signature that
|
|
|
|
/// matches the function signature, even though it's unreachable. This function
|
|
|
|
/// checks for such cases and fixes up the signatures.
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
|
|
|
|
const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
|
2016-10-07 06:29:32 +08:00
|
|
|
assert(MFI.getResults().size() <= 1);
|
|
|
|
|
|
|
|
if (MFI.getResults().empty())
|
|
|
|
return;
|
|
|
|
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
WebAssembly::ExprType RetType;
|
2016-10-07 06:29:32 +08:00
|
|
|
switch (MFI.getResults().front().SimpleTy) {
|
2018-09-05 09:27:38 +08:00
|
|
|
case MVT::i32:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::I32;
|
2018-09-05 09:27:38 +08:00
|
|
|
break;
|
|
|
|
case MVT::i64:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::I64;
|
2018-09-05 09:27:38 +08:00
|
|
|
break;
|
|
|
|
case MVT::f32:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::F32;
|
2018-09-05 09:27:38 +08:00
|
|
|
break;
|
|
|
|
case MVT::f64:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::F64;
|
2018-09-05 09:27:38 +08:00
|
|
|
break;
|
2018-08-07 07:16:50 +08:00
|
|
|
case MVT::v16i8:
|
|
|
|
case MVT::v8i16:
|
|
|
|
case MVT::v4i32:
|
2018-08-08 05:24:01 +08:00
|
|
|
case MVT::v2i64:
|
2018-08-07 07:16:50 +08:00
|
|
|
case MVT::v4f32:
|
2018-08-08 05:24:01 +08:00
|
|
|
case MVT::v2f64:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::V128;
|
2018-08-07 07:16:50 +08:00
|
|
|
break;
|
2018-09-05 09:27:38 +08:00
|
|
|
case MVT::ExceptRef:
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
RetType = WebAssembly::ExprType::ExceptRef;
|
2018-09-05 09:27:38 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected return type");
|
2016-10-07 06:29:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (MachineBasicBlock &MBB : reverse(MF)) {
|
|
|
|
for (MachineInstr &MI : reverse(MBB)) {
|
2018-05-09 10:42:00 +08:00
|
|
|
if (MI.isPosition() || MI.isDebugInstr())
|
2016-10-07 06:29:32 +08:00
|
|
|
continue;
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_BLOCK) {
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
|
2016-10-07 06:29:32 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP) {
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
|
2016-10-07 06:29:32 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Something other than an `end`. We're done.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// WebAssembly functions end with an end instruction, as if the function body
|
|
|
|
// were a block.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
static void appendEndToFunction(MachineFunction &MF,
|
2018-09-05 09:27:38 +08:00
|
|
|
const WebAssemblyInstrInfo &TII) {
|
2018-03-16 06:06:51 +08:00
|
|
|
BuildMI(MF.back(), MF.back().end(),
|
|
|
|
MF.back().findPrevDebugLoc(MF.back().end()),
|
2017-02-25 07:18:00 +08:00
|
|
|
TII.get(WebAssembly::END_FUNCTION));
|
|
|
|
}
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
/// Insert LOOP/TRY/BLOCK markers at appropriate places.
|
|
|
|
void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
|
|
|
|
// We allocate one more than the number of blocks in the function to
|
|
|
|
// accommodate for the possible fake block we may insert at the end.
|
|
|
|
ScopeTops.resize(MF.getNumBlockIDs() + 1);
|
|
|
|
// Place the LOOP for MBB if MBB is the header of a loop.
|
|
|
|
for (auto &MBB : MF)
|
|
|
|
placeLoopMarker(MBB);
|
2019-03-27 01:15:55 +08:00
|
|
|
|
[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
|
|
|
const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
|
2019-03-27 01:15:55 +08:00
|
|
|
for (auto &MBB : MF) {
|
|
|
|
if (MBB.isEHPad()) {
|
|
|
|
// Place the TRY for MBB if MBB is the EH pad of an exception.
|
|
|
|
if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
|
|
|
|
MF.getFunction().hasPersonalityFn())
|
|
|
|
placeTryMarker(MBB);
|
|
|
|
} else {
|
|
|
|
// Place the BLOCK for MBB if MBB is branched to from above.
|
|
|
|
placeBlockMarker(MBB);
|
|
|
|
}
|
|
|
|
}
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
// Now rewrite references to basic blocks to be depth immediates.
|
|
|
|
SmallVector<const MachineBasicBlock *, 8> Stack;
|
|
|
|
for (auto &MBB : reverse(MF)) {
|
2018-08-17 07:50:59 +08:00
|
|
|
for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) {
|
|
|
|
MachineInstr &MI = *I;
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
case WebAssembly::BLOCK:
|
2018-08-17 07:50:59 +08:00
|
|
|
case WebAssembly::TRY:
|
|
|
|
assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <=
|
|
|
|
MBB.getNumber() &&
|
|
|
|
"Block/try marker should be balanced");
|
|
|
|
Stack.pop_back();
|
|
|
|
break;
|
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
case WebAssembly::LOOP:
|
|
|
|
assert(Stack.back() == &MBB && "Loop top should be balanced");
|
|
|
|
Stack.pop_back();
|
|
|
|
break;
|
2018-08-17 07:50:59 +08:00
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
case WebAssembly::END_BLOCK:
|
2018-08-17 07:50:59 +08:00
|
|
|
case WebAssembly::END_TRY:
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
Stack.push_back(&MBB);
|
|
|
|
break;
|
2018-08-17 07:50:59 +08:00
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
case WebAssembly::END_LOOP:
|
2018-08-17 07:50:59 +08:00
|
|
|
Stack.push_back(EndToBegin[&MI]->getParent());
|
|
|
|
break;
|
|
|
|
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
default:
|
|
|
|
if (MI.isTerminator()) {
|
|
|
|
// Rewrite MBB operands to be depth immediates.
|
|
|
|
SmallVector<MachineOperand, 4> Ops(MI.operands());
|
|
|
|
while (MI.getNumOperands() > 0)
|
|
|
|
MI.RemoveOperand(MI.getNumOperands() - 1);
|
|
|
|
for (auto MO : Ops) {
|
|
|
|
if (MO.isMBB())
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB()));
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
MI.addOperand(MF, MO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(Stack.empty() && "Control flow should be balanced");
|
2018-08-17 07:50:59 +08:00
|
|
|
}
|
2016-10-07 06:29:32 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
void WebAssemblyCFGStackify::releaseMemory() {
|
|
|
|
ScopeTops.clear();
|
|
|
|
BeginToEnd.clear();
|
|
|
|
EndToBegin.clear();
|
|
|
|
TryToEHPad.clear();
|
|
|
|
EHPadToTry.clear();
|
2015-11-24 00:19:56 +08:00
|
|
|
}
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
|
|
|
|
"********** Function: "
|
|
|
|
<< MF.getName() << '\n');
|
2019-02-27 08:50:53 +08:00
|
|
|
const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
releaseMemory();
|
|
|
|
|
2016-10-04 06:43:53 +08:00
|
|
|
// Liveness is not tracked for VALUE_STACK physreg.
|
2016-01-14 01:10:28 +08:00
|
|
|
MF.getRegInfo().invalidateLiveness();
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
|
|
|
|
placeMarkers(MF);
|
|
|
|
|
2019-02-27 08:50:53 +08:00
|
|
|
if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
|
|
|
|
MF.getFunction().hasPersonalityFn())
|
|
|
|
// Remove unnecessary instructions.
|
|
|
|
removeUnnecessaryInstrs(MF);
|
|
|
|
|
2018-08-17 07:50:59 +08:00
|
|
|
// Convert MBB operands in terminators to relative depth immediates.
|
|
|
|
rewriteDepthImmediates(MF);
|
|
|
|
|
|
|
|
// Fix up block/loop/try signatures at the end of the function to conform to
|
|
|
|
// WebAssembly's rules.
|
|
|
|
fixEndsAtEndOfFunction(MF);
|
|
|
|
|
|
|
|
// Add an end instruction at the end of the function body.
|
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
if (!MF.getSubtarget<WebAssemblySubtarget>()
|
|
|
|
.getTargetTriple()
|
|
|
|
.isOSBinFormatELF())
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
appendEndToFunction(MF, TII);
|
2015-11-24 00:19:56 +08:00
|
|
|
|
2019-03-27 01:46:14 +08:00
|
|
|
MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
|
2015-09-17 00:51:30 +08:00
|
|
|
return true;
|
|
|
|
}
|