@@ -80,8 +80,12 @@ class WebAssemblyCFGStackify final : public MachineFunctionPass {
80
80
void removeUnnecessaryInstrs (MachineFunction &MF);
81
81
82
82
// Wrap-up
83
- unsigned getDepth (const SmallVectorImpl<const MachineBasicBlock *> &Stack,
84
- const MachineBasicBlock *MBB);
83
+ using EndMarkerInfo =
84
+ std::pair<const MachineBasicBlock *, const MachineInstr *>;
85
+ unsigned getBranchDepth (const SmallVectorImpl<EndMarkerInfo> &Stack,
86
+ const MachineBasicBlock *MBB);
87
+ unsigned getDelegateDepth (const SmallVectorImpl<EndMarkerInfo> &Stack,
88
+ const MachineBasicBlock *MBB);
85
89
void rewriteDepthImmediates (MachineFunction &MF);
86
90
void fixEndsAtEndOfFunction (MachineFunction &MF);
87
91
void cleanupFunctionData (MachineFunction &MF);
@@ -1399,21 +1403,6 @@ void WebAssemblyCFGStackify::recalculateScopeTops(MachineFunction &MF) {
1399
1403
}
1400
1404
}
1401
1405
1402
- unsigned WebAssemblyCFGStackify::getDepth (
1403
- const SmallVectorImpl<const MachineBasicBlock *> &Stack,
1404
- const MachineBasicBlock *MBB) {
1405
- if (MBB == FakeCallerBB)
1406
- return Stack.size ();
1407
- unsigned Depth = 0 ;
1408
- for (auto X : reverse (Stack)) {
1409
- if (X == MBB)
1410
- break ;
1411
- ++Depth;
1412
- }
1413
- assert (Depth < Stack.size () && " Branch destination should be in scope" );
1414
- return Depth;
1415
- }
1416
-
1417
1406
// / In normal assembly languages, when the end of a function is unreachable,
1418
1407
// / because the function ends in an infinite loop or a noreturn call or similar,
1419
1408
// / it isn't necessary to worry about the function return type at the end of
@@ -1515,48 +1504,85 @@ void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
1515
1504
}
1516
1505
}
1517
1506
1507
+ unsigned WebAssemblyCFGStackify::getBranchDepth (
1508
+ const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) {
1509
+ unsigned Depth = 0 ;
1510
+ for (auto X : reverse (Stack)) {
1511
+ if (X.first == MBB)
1512
+ break ;
1513
+ ++Depth;
1514
+ }
1515
+ assert (Depth < Stack.size () && " Branch destination should be in scope" );
1516
+ return Depth;
1517
+ }
1518
+
1519
+ unsigned WebAssemblyCFGStackify::getDelegateDepth (
1520
+ const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) {
1521
+ if (MBB == FakeCallerBB)
1522
+ return Stack.size ();
1523
+ // Delegate's destination is either a catch or a another delegate BB. When the
1524
+ // destination is another delegate, we can compute the argument in the same
1525
+ // way as branches, because the target delegate BB only contains the single
1526
+ // delegate instruction.
1527
+ if (!MBB->isEHPad ()) // Target is a delegate BB
1528
+ return getBranchDepth (Stack, MBB);
1529
+
1530
+ // When the delegate's destination is a catch BB, we need to use its
1531
+ // corresponding try's end_try BB because Stack contains each marker's end BB.
1532
+ // Also we need to check if the end marker instruction matches, because a
1533
+ // single BB can contain multiple end markers, like this:
1534
+ // bb:
1535
+ // END_BLOCK
1536
+ // END_TRY
1537
+ // END_BLOCK
1538
+ // END_TRY
1539
+ // ...
1540
+ //
1541
+ // In case of branches getting the immediate that targets any of these is
1542
+ // fine, but delegate has to exactly target the correct try.
1543
+ unsigned Depth = 0 ;
1544
+ const MachineInstr *EndTry = BeginToEnd[EHPadToTry[MBB]];
1545
+ for (auto X : reverse (Stack)) {
1546
+ if (X.first == EndTry->getParent () && X.second == EndTry)
1547
+ break ;
1548
+ ++Depth;
1549
+ }
1550
+ assert (Depth < Stack.size () && " Delegate destination should be in scope" );
1551
+ return Depth;
1552
+ }
1553
+
1518
1554
void WebAssemblyCFGStackify::rewriteDepthImmediates (MachineFunction &MF) {
1519
1555
// Now rewrite references to basic blocks to be depth immediates.
1520
- SmallVector<const MachineBasicBlock *, 8 > Stack;
1521
- SmallVector<const MachineBasicBlock *, 8 > DelegateStack;
1556
+ SmallVector<EndMarkerInfo, 8 > Stack;
1522
1557
for (auto &MBB : reverse (MF)) {
1523
1558
for (auto I = MBB.rbegin (), E = MBB.rend (); I != E; ++I) {
1524
1559
MachineInstr &MI = *I;
1525
1560
switch (MI.getOpcode ()) {
1526
1561
case WebAssembly::BLOCK:
1527
1562
case WebAssembly::TRY:
1528
- assert (ScopeTops[Stack.back ()->getNumber ()]->getNumber () <=
1563
+ assert (ScopeTops[Stack.back (). first ->getNumber ()]->getNumber () <=
1529
1564
MBB.getNumber () &&
1530
1565
" Block/try marker should be balanced" );
1531
1566
Stack.pop_back ();
1532
- DelegateStack.pop_back ();
1533
1567
break ;
1534
1568
1535
1569
case WebAssembly::LOOP:
1536
- assert (Stack.back () == &MBB && " Loop top should be balanced" );
1570
+ assert (Stack.back (). first == &MBB && " Loop top should be balanced" );
1537
1571
Stack.pop_back ();
1538
- DelegateStack.pop_back ();
1539
1572
break ;
1540
1573
1541
1574
case WebAssembly::END_BLOCK:
1542
- Stack.push_back (&MBB);
1543
- DelegateStack.push_back (&MBB);
1575
+ Stack.push_back (std::make_pair (&MBB, &MI));
1544
1576
break ;
1545
1577
1546
1578
case WebAssembly::END_TRY:
1547
1579
// We handle DELEGATE in the default level, because DELEGATE has
1548
- // immediate operands to rewirte .
1549
- Stack.push_back (&MBB);
1580
+ // immediate operands to rewrite .
1581
+ Stack.push_back (std::make_pair ( &MBB, &MI) );
1550
1582
break ;
1551
1583
1552
1584
case WebAssembly::END_LOOP:
1553
- Stack.push_back (EndToBegin[&MI]->getParent ());
1554
- DelegateStack.push_back (EndToBegin[&MI]->getParent ());
1555
- break ;
1556
-
1557
- case WebAssembly::CATCH:
1558
- case WebAssembly::CATCH_ALL:
1559
- DelegateStack.push_back (&MBB);
1585
+ Stack.push_back (std::make_pair (EndToBegin[&MI]->getParent (), &MI));
1560
1586
break ;
1561
1587
1562
1588
default :
@@ -1569,18 +1595,17 @@ void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
1569
1595
if (MO.isMBB ()) {
1570
1596
if (MI.getOpcode () == WebAssembly::DELEGATE)
1571
1597
MO = MachineOperand::CreateImm (
1572
- getDepth (DelegateStack , MO.getMBB ()));
1598
+ getDelegateDepth (Stack , MO.getMBB ()));
1573
1599
else
1574
- MO = MachineOperand::CreateImm (getDepth (Stack, MO.getMBB ()));
1600
+ MO = MachineOperand::CreateImm (
1601
+ getBranchDepth (Stack, MO.getMBB ()));
1575
1602
}
1576
1603
MI.addOperand (MF, MO);
1577
1604
}
1578
1605
}
1579
1606
1580
- if (MI.getOpcode () == WebAssembly::DELEGATE) {
1581
- Stack.push_back (&MBB);
1582
- DelegateStack.push_back (&MBB);
1583
- }
1607
+ if (MI.getOpcode () == WebAssembly::DELEGATE)
1608
+ Stack.push_back (std::make_pair (&MBB, &MI));
1584
1609
break ;
1585
1610
}
1586
1611
}
0 commit comments