summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
diff options
context:
space:
mode:
authorDan Gohman <dan433584@gmail.com>2016-10-06 22:29:32 +0000
committerDan Gohman <dan433584@gmail.com>2016-10-06 22:29:32 +0000
commit2726b88c038737460a4502915ff427db5854b3e7 (patch)
tree4c4ad476a660cea533b0fa28b41d701e4f6adece /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
parent3a643e8d46d06da4c6648a12e48ceb6ab6dc3733 (diff)
downloadbcm5719-llvm-2726b88c038737460a4502915ff427db5854b3e7.tar.gz
bcm5719-llvm-2726b88c038737460a4502915ff427db5854b3e7.zip
[WebAssemby] Implement block signatures.
Per spec changes, this implements block signatures, and adds just enough logic to produce correct block signatures at the ends of functions. Differential Revision: https://reviews.llvm.org/D25144 llvm-svn: 283503
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp86
1 files changed, 75 insertions, 11 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 558ac229993..774c41d8909 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -309,7 +309,8 @@ static bool IsChild(const MachineInstr &MI,
static void PlaceBlockMarker(
MachineBasicBlock &MBB, MachineFunction &MF,
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
- DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops,
+ DenseMap<const MachineInstr *, MachineInstr *> &BlockTops,
+ DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
const WebAssemblyInstrInfo &TII,
const MachineLoopInfo &MLI,
MachineDominatorTree &MDT,
@@ -372,15 +373,19 @@ static void PlaceBlockMarker(
}
// Add the BLOCK.
- BuildMI(*Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK));
+ MachineInstr *Begin = BuildMI(*Header, InsertPos, DebugLoc(),
+ TII.get(WebAssembly::BLOCK))
+ .addImm(WebAssembly::Void);
// Mark the end of the block.
InsertPos = MBB.begin();
while (InsertPos != MBB.end() &&
InsertPos->getOpcode() == WebAssembly::END_LOOP &&
- LoopTops[&*InsertPos]->getNumber() >= Header->getNumber())
+ LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->getNumber())
++InsertPos;
- BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::END_BLOCK));
+ MachineInstr *End = BuildMI(MBB, InsertPos, DebugLoc(),
+ TII.get(WebAssembly::END_BLOCK));
+ BlockTops[End] = Begin;
// Track the farthest-spanning scope that ends at this point.
int Number = MBB.getNumber();
@@ -393,7 +398,7 @@ static void PlaceBlockMarker(
static void PlaceLoopMarker(
MachineBasicBlock &MBB, MachineFunction &MF,
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
- DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops,
+ DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) {
MachineLoop *Loop = MLI.getLoopFor(&MBB);
if (!Loop || Loop->getHeader() != &MBB)
@@ -418,12 +423,14 @@ static void PlaceLoopMarker(
while (InsertPos != MBB.end() &&
InsertPos->getOpcode() == WebAssembly::END_LOOP)
++InsertPos;
- BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::LOOP));
+ MachineInstr *Begin = BuildMI(MBB, InsertPos, DebugLoc(),
+ TII.get(WebAssembly::LOOP))
+ .addImm(WebAssembly::Void);
// Mark the end of the loop.
MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(),
TII.get(WebAssembly::END_LOOP));
- LoopTops[End] = &MBB;
+ LoopTops[End] = Begin;
assert((!ScopeTops[AfterLoop->getNumber()] ||
ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
@@ -445,6 +452,56 @@ GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
return Depth;
}
+/// 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) {
+ case MVT::i32: retType = WebAssembly::I32; break;
+ case MVT::i64: retType = WebAssembly::I64; break;
+ case MVT::f32: retType = WebAssembly::F32; break;
+ case MVT::f64: retType = WebAssembly::F64; break;
+ case MVT::v16i8: retType = WebAssembly::I8x16; break;
+ case MVT::v8i16: retType = WebAssembly::I16x8; break;
+ case MVT::v4i32: retType = WebAssembly::I32x4; break;
+ case MVT::v2i64: retType = WebAssembly::I64x2; break;
+ case MVT::v4f32: retType = WebAssembly::F32x4; break;
+ case MVT::v2f64: retType = WebAssembly::F64x2; break;
+ default: llvm_unreachable("unexpected return type");
+ }
+
+ for (MachineBasicBlock &MBB : reverse(MF)) {
+ for (MachineInstr &MI : reverse(MBB)) {
+ if (MI.isPosition() || MI.isDebugValue())
+ 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;
+ }
+ }
+}
+
/// Insert LOOP and BLOCK markers at appropriate places.
static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
const WebAssemblyInstrInfo &TII,
@@ -457,15 +514,18 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
// we may insert at the end.
SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1);
- // For eacn LOOP_END, the corresponding LOOP.
- DenseMap<const MachineInstr *, const MachineBasicBlock *> LoopTops;
+ // For each LOOP_END, the corresponding LOOP.
+ DenseMap<const MachineInstr *, MachineInstr *> LoopTops;
+
+ // For each END_BLOCK, the corresponding BLOCK.
+ DenseMap<const MachineInstr *, MachineInstr *> BlockTops;
for (auto &MBB : MF) {
// Place the LOOP for MBB if MBB is the header of a loop.
PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI);
// Place the BLOCK for MBB if MBB is branched to from above.
- PlaceBlockMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI, MDT, MFI);
+ PlaceBlockMarker(MBB, MF, ScopeTops, BlockTops, LoopTops, TII, MLI, MDT, MFI);
}
// Now rewrite references to basic blocks to be depth immediates.
@@ -486,7 +546,7 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
Stack.push_back(&MBB);
break;
case WebAssembly::END_LOOP:
- Stack.push_back(LoopTops[&MI]);
+ Stack.push_back(LoopTops[&MI]->getParent());
break;
default:
if (MI.isTerminator()) {
@@ -505,6 +565,10 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
}
}
assert(Stack.empty() && "Control flow should be balanced");
+
+ // Fix up block/loop signatures at the end of the function to conform to
+ // WebAssembly's rules.
+ FixEndsAtEndOfFunction(MF, MFI, BlockTops, LoopTops);
}
bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
OpenPOWER on IntegriCloud