2015-09-17 00:51:30 +08:00
|
|
|
//===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
2018-05-01 23:54:18 +08:00
|
|
|
/// This file implements a CFG stacking pass.
|
2015-09-17 00:51:30 +08:00
|
|
|
///
|
2017-02-28 06:38:58 +08:00
|
|
|
/// This pass inserts BLOCK and LOOP markers to mark the start of scopes, since
|
2015-09-17 00:51:30 +08:00
|
|
|
/// scope boundaries serve as the labels for WebAssembly's control transfers.
|
|
|
|
///
|
|
|
|
/// This is sufficient to convert arbitrary CFGs into a form that works on
|
|
|
|
/// WebAssembly, provided that all loops are single-entry.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "WebAssembly.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"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
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 {
|
|
|
|
AU.setPreservesCFG();
|
2015-11-24 00:19:56 +08:00
|
|
|
AU.addRequired<MachineDominatorTree>();
|
|
|
|
AU.addPreserved<MachineDominatorTree>();
|
2015-09-17 00:51:30 +08:00
|
|
|
AU.addRequired<MachineLoopInfo>();
|
|
|
|
AU.addPreserved<MachineLoopInfo>();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
|
|
|
|
|
public:
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
|
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
char WebAssemblyCFGStackify::ID = 0;
|
2018-03-31 04:36:58 +08:00
|
|
|
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
|
|
|
|
"Insert BLOCK and LOOP markers for WebAssembly scopes",
|
|
|
|
false, false)
|
|
|
|
|
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.
|
2016-01-08 09:06:00 +08:00
|
|
|
static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred,
|
|
|
|
MachineBasicBlock *MBB) {
|
2015-12-17 03:06:41 +08:00
|
|
|
for (MachineInstr &MI : Pred->terminators())
|
|
|
|
for (MachineOperand &MO : MI.explicit_operands())
|
|
|
|
if (MO.isMBB() && MO.getMBB() == MBB)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-24 00:19:56 +08:00
|
|
|
/// Insert a BLOCK marker for branches to MBB (if needed).
|
2016-10-07 06:10:23 +08:00
|
|
|
static void PlaceBlockMarker(
|
|
|
|
MachineBasicBlock &MBB, MachineFunction &MF,
|
|
|
|
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
|
2016-10-07 06:29:32 +08:00
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> &BlockTops,
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
|
2016-10-07 06:10:23 +08:00
|
|
|
const WebAssemblyInstrInfo &TII,
|
|
|
|
const MachineLoopInfo &MLI,
|
|
|
|
MachineDominatorTree &MDT,
|
|
|
|
WebAssemblyFunctionInfo &MFI) {
|
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;
|
|
|
|
int MBBNumber = MBB.getNumber();
|
|
|
|
for (MachineBasicBlock *Pred : MBB.predecessors())
|
|
|
|
if (Pred->getNumber() < MBBNumber) {
|
|
|
|
Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
|
2015-12-17 03:06:41 +08:00
|
|
|
if (ExplicitlyBranchesTo(Pred, &MBB))
|
2015-11-24 00:19:56 +08:00
|
|
|
IsBranchedTo = true;
|
2015-09-17 00:51:30 +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");
|
2016-09-05 20:06:47 +08:00
|
|
|
MachineBasicBlock *LayoutPred = &*std::prev(MachineFunction::iterator(&MBB));
|
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.
|
2016-09-05 20:06:47 +08:00
|
|
|
I = std::next(MachineFunction::iterator(ScopeTop));
|
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.
|
2015-11-24 00:19:56 +08:00
|
|
|
MachineBasicBlock::iterator InsertPos;
|
|
|
|
MachineLoop *HeaderLoop = MLI.getLoopFor(Header);
|
2018-06-19 08:32:03 +08:00
|
|
|
if (HeaderLoop &&
|
|
|
|
MBB.getNumber() > WebAssembly::getBottom(HeaderLoop)->getNumber()) {
|
2015-12-15 06:51:54 +08:00
|
|
|
// Header is the header of a loop that does not lexically contain MBB, so
|
2016-02-13 05:19:25 +08:00
|
|
|
// the BLOCK needs to be above the LOOP, after any END constructs.
|
2015-11-24 00:19:56 +08:00
|
|
|
InsertPos = Header->begin();
|
2016-10-07 06:10:23 +08:00
|
|
|
while (InsertPos->getOpcode() == WebAssembly::END_BLOCK ||
|
|
|
|
InsertPos->getOpcode() == WebAssembly::END_LOOP)
|
2016-02-13 05:19:25 +08:00
|
|
|
++InsertPos;
|
2015-11-24 00:19:56 +08:00
|
|
|
} else {
|
2015-12-25 08:31:02 +08:00
|
|
|
// Otherwise, insert the BLOCK as late in Header as we can, but before the
|
|
|
|
// beginning of the local expression tree and any nested BLOCKs.
|
2015-11-24 00:19:56 +08:00
|
|
|
InsertPos = Header->getFirstTerminator();
|
2016-09-05 20:06:47 +08:00
|
|
|
while (InsertPos != Header->begin() &&
|
2016-10-25 03:49:43 +08:00
|
|
|
WebAssembly::isChild(*std::prev(InsertPos), MFI) &&
|
2016-09-05 20:06:47 +08:00
|
|
|
std::prev(InsertPos)->getOpcode() != WebAssembly::LOOP &&
|
|
|
|
std::prev(InsertPos)->getOpcode() != WebAssembly::END_BLOCK &&
|
|
|
|
std::prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP)
|
2015-11-24 00:19:56 +08:00
|
|
|
--InsertPos;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|
|
|
|
|
2015-12-15 06:51:54 +08:00
|
|
|
// Add the BLOCK.
|
2018-04-14 08:12:12 +08:00
|
|
|
MachineInstr *Begin =
|
|
|
|
BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
|
|
|
|
TII.get(WebAssembly::BLOCK))
|
|
|
|
.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
|
|
|
|
|
|
|
// Mark the end of the block.
|
|
|
|
InsertPos = MBB.begin();
|
|
|
|
while (InsertPos != MBB.end() &&
|
2016-10-07 06:10:23 +08:00
|
|
|
InsertPos->getOpcode() == WebAssembly::END_LOOP &&
|
2016-10-07 06:29:32 +08:00
|
|
|
LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->getNumber())
|
[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
|
|
|
++InsertPos;
|
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));
|
|
|
|
BlockTops[End] = Begin;
|
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).
|
[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 void PlaceLoopMarker(
|
|
|
|
MachineBasicBlock &MBB, MachineFunction &MF,
|
|
|
|
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
|
2016-10-07 06:29:32 +08:00
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
|
[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 WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) {
|
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);
|
2016-09-05 20:06:47 +08:00
|
|
|
auto Iter = std::next(MachineFunction::iterator(Bottom));
|
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);
|
2016-09-05 20:06:47 +08:00
|
|
|
Iter = std::next(MachineFunction::iterator(Bottom));
|
2015-12-15 06:51:54 +08:00
|
|
|
}
|
|
|
|
MachineBasicBlock *AfterLoop = &*Iter;
|
|
|
|
|
[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 beginning of the loop (after the end of any existing loop that
|
|
|
|
// ends here).
|
|
|
|
auto InsertPos = MBB.begin();
|
|
|
|
while (InsertPos != MBB.end() &&
|
|
|
|
InsertPos->getOpcode() == WebAssembly::END_LOOP)
|
|
|
|
++InsertPos;
|
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-03-16 06:06:51 +08:00
|
|
|
// Mark the end of the loop (using arbitrary debug location that branched
|
|
|
|
// to the loop end as its location).
|
|
|
|
DebugLoc EndDL = (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
|
|
|
|
MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), EndDL,
|
[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
|
|
|
TII.get(WebAssembly::END_LOOP));
|
2016-10-07 06:29:32 +08:00
|
|
|
LoopTops[End] = Begin;
|
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
|
|
|
}
|
|
|
|
|
[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
|
|
|
|
GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
|
|
|
|
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.
|
|
|
|
static void FixEndsAtEndOfFunction(
|
|
|
|
MachineFunction &MF,
|
|
|
|
const WebAssemblyFunctionInfo &MFI,
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> &BlockTops,
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops) {
|
|
|
|
assert(MFI.getResults().size() <= 1);
|
|
|
|
|
|
|
|
if (MFI.getResults().empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
WebAssembly::ExprType retType;
|
|
|
|
switch (MFI.getResults().front().SimpleTy) {
|
2016-10-25 03:49:43 +08:00
|
|
|
case MVT::i32: retType = WebAssembly::ExprType::I32; break;
|
|
|
|
case MVT::i64: retType = WebAssembly::ExprType::I64; break;
|
|
|
|
case MVT::f32: retType = WebAssembly::ExprType::F32; break;
|
|
|
|
case MVT::f64: retType = WebAssembly::ExprType::F64; 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:
|
2018-08-07 07:16:50 +08:00
|
|
|
retType = WebAssembly::ExprType::V128;
|
|
|
|
break;
|
2018-03-08 12:05:37 +08:00
|
|
|
case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break;
|
2016-10-07 06:29:32 +08:00
|
|
|
default: llvm_unreachable("unexpected return type");
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
BlockTops[&MI]->getOperand(0).setImm(int32_t(retType));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (MI.getOpcode() == WebAssembly::END_LOOP) {
|
|
|
|
LoopTops[&MI]->getOperand(0).setImm(int32_t(retType));
|
|
|
|
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.
|
|
|
|
static void AppendEndToFunction(
|
|
|
|
MachineFunction &MF,
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
/// Insert LOOP and BLOCK markers at appropriate places.
|
|
|
|
static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
|
2015-11-24 00:19:56 +08:00
|
|
|
const WebAssemblyInstrInfo &TII,
|
2016-01-30 13:01:06 +08:00
|
|
|
MachineDominatorTree &MDT,
|
|
|
|
WebAssemblyFunctionInfo &MFI) {
|
2015-12-15 06:51:54 +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. 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.
|
|
|
|
SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1);
|
|
|
|
|
2016-10-07 06:29:32 +08:00
|
|
|
// For each LOOP_END, the corresponding LOOP.
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> LoopTops;
|
|
|
|
|
|
|
|
// For each END_BLOCK, the corresponding BLOCK.
|
|
|
|
DenseMap<const MachineInstr *, MachineInstr *> BlockTops;
|
[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
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
for (auto &MBB : MF) {
|
2015-11-24 00:19:56 +08:00
|
|
|
// Place the LOOP for MBB if MBB is the header of a loop.
|
[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
|
|
|
PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI);
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2015-11-24 00:19:56 +08:00
|
|
|
// Place the BLOCK for MBB if MBB is branched to from above.
|
2016-10-07 06:29:32 +08:00
|
|
|
PlaceBlockMarker(MBB, MF, ScopeTops, BlockTops, LoopTops, TII, MLI, MDT, MFI);
|
2015-09-17 00:51:30 +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
|
|
|
// Now rewrite references to basic blocks to be depth immediates.
|
|
|
|
SmallVector<const MachineBasicBlock *, 8> Stack;
|
|
|
|
for (auto &MBB : reverse(MF)) {
|
|
|
|
for (auto &MI : reverse(MBB)) {
|
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
case WebAssembly::BLOCK:
|
2016-10-07 06:10:23 +08:00
|
|
|
assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <= MBB.getNumber() &&
|
[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
|
|
|
"Block should be balanced");
|
|
|
|
Stack.pop_back();
|
|
|
|
break;
|
|
|
|
case WebAssembly::LOOP:
|
|
|
|
assert(Stack.back() == &MBB && "Loop top should be balanced");
|
|
|
|
Stack.pop_back();
|
|
|
|
break;
|
|
|
|
case WebAssembly::END_BLOCK:
|
|
|
|
Stack.push_back(&MBB);
|
|
|
|
break;
|
|
|
|
case WebAssembly::END_LOOP:
|
2016-10-07 06:29:32 +08:00
|
|
|
Stack.push_back(LoopTops[&MI]->getParent());
|
[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
|
|
|
break;
|
|
|
|
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())
|
|
|
|
MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB()));
|
|
|
|
MI.addOperand(MF, MO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(Stack.empty() && "Control flow should be balanced");
|
2016-10-07 06:29:32 +08:00
|
|
|
|
|
|
|
// Fix up block/loop signatures at the end of the function to conform to
|
|
|
|
// WebAssembly's rules.
|
|
|
|
FixEndsAtEndOfFunction(MF, MFI, BlockTops, LoopTops);
|
2017-02-25 07:18:00 +08:00
|
|
|
|
|
|
|
// Add an end instruction at the end of the function body.
|
2018-07-17 07:09:29 +08:00
|
|
|
AppendEndToFunction(MF, TII);
|
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');
|
2015-09-17 00:51:30 +08:00
|
|
|
|
|
|
|
const auto &MLI = getAnalysis<MachineLoopInfo>();
|
2015-11-24 00:19:56 +08:00
|
|
|
auto &MDT = getAnalysis<MachineDominatorTree>();
|
2016-10-04 06:43:53 +08:00
|
|
|
// Liveness is not tracked for VALUE_STACK physreg.
|
2015-09-17 00:51:30 +08:00
|
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
2016-01-30 13:01:06 +08:00
|
|
|
WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
|
2016-01-14 01:10:28 +08:00
|
|
|
MF.getRegInfo().invalidateLiveness();
|
2015-09-17 00:51:30 +08:00
|
|
|
|
|
|
|
// Place the BLOCK and LOOP markers to indicate the beginnings of scopes.
|
2016-01-30 13:01:06 +08:00
|
|
|
PlaceMarkers(MF, MLI, TII, MDT, MFI);
|
2015-11-24 00:19:56 +08:00
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
return true;
|
|
|
|
}
|