Skip to content

Commit 7cc116c

Browse files
author
git apple-llvm automerger
committed
Merge commit 'aadaa00de76e' from llvm.org/release/19.x into stable/20240723
2 parents 7c9a435 + aadaa00 commit 7cc116c

File tree

11 files changed

+181
-63
lines changed

11 files changed

+181
-63
lines changed

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ def SDTCatchret : SDTypeProfile<0, 2, [ // catchret
231231
SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT>
232232
]>;
233233

234+
def SDTCleanupret : SDTypeProfile<0, 1, [ // cleanupret
235+
SDTCisVT<0, OtherVT>
236+
]>;
237+
234238
def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap
235239

236240
def SDTUBSANTrap : SDTypeProfile<0, 1, []>; // ubsantrap
@@ -680,7 +684,7 @@ def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
680684
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
681685
def catchret : SDNode<"ISD::CATCHRET" , SDTCatchret,
682686
[SDNPHasChain, SDNPSideEffect]>;
683-
def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>;
687+
def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTCleanupret, [SDNPHasChain]>;
684688

685689
def trap : SDNode<"ISD::TRAP" , SDTNone,
686690
[SDNPHasChain, SDNPSideEffect]>;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,8 +2168,10 @@ void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
21682168
FuncInfo.MBB->normalizeSuccProbs();
21692169

21702170
// Create the terminator node.
2171-
SDValue Ret =
2172-
DAG.getNode(ISD::CLEANUPRET, getCurSDLoc(), MVT::Other, getControlRoot());
2171+
MachineBasicBlock *CleanupPadMBB =
2172+
FuncInfo.MBBMap[I.getCleanupPad()->getParent()];
2173+
SDValue Ret = DAG.getNode(ISD::CLEANUPRET, getCurSDLoc(), MVT::Other,
2174+
getControlRoot(), DAG.getBasicBlock(CleanupPadMBB));
21732175
DAG.setRoot(Ret);
21742176
}
21752177

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5162,7 +5162,7 @@ let isPseudo = 1 in {
51625162
//===----------------------------------------------------------------------===//
51635163
let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
51645164
isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1, isPseudo = 1 in {
5165-
def CLEANUPRET : Pseudo<(outs), (ins), [(cleanupret)]>, Sched<[]>;
5165+
def CLEANUPRET : Pseudo<(outs), (ins), [(cleanupret bb)]>, Sched<[]>;
51665166
let usesCustomInserter = 1 in
51675167
def CATCHRET : Pseudo<(outs), (ins am_brcond:$dst, am_brcond:$src), [(catchret bb:$dst, bb:$src)]>,
51685168
Sched<[]>;

llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,8 @@ class WebAssemblyCFGStackify final : public MachineFunctionPass {
8787
const MachineBasicBlock *MBB);
8888
unsigned getDelegateDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
8989
const MachineBasicBlock *MBB);
90-
unsigned
91-
getRethrowDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
92-
const SmallVectorImpl<const MachineBasicBlock *> &EHPadStack);
90+
unsigned getRethrowDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
91+
const MachineBasicBlock *EHPadToRethrow);
9392
void rewriteDepthImmediates(MachineFunction &MF);
9493
void fixEndsAtEndOfFunction(MachineFunction &MF);
9594
void cleanupFunctionData(MachineFunction &MF);
@@ -1612,34 +1611,13 @@ unsigned WebAssemblyCFGStackify::getDelegateDepth(
16121611

16131612
unsigned WebAssemblyCFGStackify::getRethrowDepth(
16141613
const SmallVectorImpl<EndMarkerInfo> &Stack,
1615-
const SmallVectorImpl<const MachineBasicBlock *> &EHPadStack) {
1614+
const MachineBasicBlock *EHPadToRethrow) {
16161615
unsigned Depth = 0;
1617-
// In our current implementation, rethrows always rethrow the exception caught
1618-
// by the innermost enclosing catch. This means while traversing Stack in the
1619-
// reverse direction, when we encounter END_TRY, we should check if the
1620-
// END_TRY corresponds to the current innermost EH pad. For example:
1621-
// try
1622-
// ...
1623-
// catch ;; (a)
1624-
// try
1625-
// rethrow 1 ;; (b)
1626-
// catch ;; (c)
1627-
// rethrow 0 ;; (d)
1628-
// end ;; (e)
1629-
// end ;; (f)
1630-
//
1631-
// When we are at 'rethrow' (d), while reversely traversing Stack the first
1632-
// 'end' we encounter is the 'end' (e), which corresponds to the 'catch' (c).
1633-
// And 'rethrow' (d) rethrows the exception caught by 'catch' (c), so we stop
1634-
// there and the depth should be 0. But when we are at 'rethrow' (b), it
1635-
// rethrows the exception caught by 'catch' (a), so when traversing Stack
1636-
// reversely, we should skip the 'end' (e) and choose 'end' (f), which
1637-
// corresponds to 'catch' (a).
16381616
for (auto X : reverse(Stack)) {
16391617
const MachineInstr *End = X.second;
16401618
if (End->getOpcode() == WebAssembly::END_TRY) {
16411619
auto *EHPad = TryToEHPad[EndToBegin[End]];
1642-
if (EHPadStack.back() == EHPad)
1620+
if (EHPadToRethrow == EHPad)
16431621
break;
16441622
}
16451623
++Depth;
@@ -1651,7 +1629,6 @@ unsigned WebAssemblyCFGStackify::getRethrowDepth(
16511629
void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
16521630
// Now rewrite references to basic blocks to be depth immediates.
16531631
SmallVector<EndMarkerInfo, 8> Stack;
1654-
SmallVector<const MachineBasicBlock *, 8> EHPadStack;
16551632
for (auto &MBB : reverse(MF)) {
16561633
for (MachineInstr &MI : llvm::reverse(MBB)) {
16571634
switch (MI.getOpcode()) {
@@ -1669,31 +1646,14 @@ void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
16691646
break;
16701647

16711648
case WebAssembly::END_BLOCK:
1649+
case WebAssembly::END_TRY:
16721650
Stack.push_back(std::make_pair(&MBB, &MI));
16731651
break;
16741652

1675-
case WebAssembly::END_TRY: {
1676-
// We handle DELEGATE in the default level, because DELEGATE has
1677-
// immediate operands to rewrite.
1678-
Stack.push_back(std::make_pair(&MBB, &MI));
1679-
auto *EHPad = TryToEHPad[EndToBegin[&MI]];
1680-
EHPadStack.push_back(EHPad);
1681-
break;
1682-
}
1683-
16841653
case WebAssembly::END_LOOP:
16851654
Stack.push_back(std::make_pair(EndToBegin[&MI]->getParent(), &MI));
16861655
break;
16871656

1688-
case WebAssembly::CATCH:
1689-
case WebAssembly::CATCH_ALL:
1690-
EHPadStack.pop_back();
1691-
break;
1692-
1693-
case WebAssembly::RETHROW:
1694-
MI.getOperand(0).setImm(getRethrowDepth(Stack, EHPadStack));
1695-
break;
1696-
16971657
default:
16981658
if (MI.isTerminator()) {
16991659
// Rewrite MBB operands to be depth immediates.
@@ -1705,6 +1665,9 @@ void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
17051665
if (MI.getOpcode() == WebAssembly::DELEGATE)
17061666
MO = MachineOperand::CreateImm(
17071667
getDelegateDepth(Stack, MO.getMBB()));
1668+
else if (MI.getOpcode() == WebAssembly::RETHROW)
1669+
MO = MachineOperand::CreateImm(
1670+
getRethrowDepth(Stack, MO.getMBB()));
17081671
else
17091672
MO = MachineOperand::CreateImm(
17101673
getBranchDepth(Stack, MO.getMBB()));

llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,19 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
245245
ReplaceNode(Node, Throw);
246246
return;
247247
}
248+
case Intrinsic::wasm_rethrow: {
249+
// RETHROW's BB argument will be populated in LateEHPrepare. Just use a
250+
// '0' as a placeholder for now.
251+
MachineSDNode *Rethrow = CurDAG->getMachineNode(
252+
WebAssembly::RETHROW, DL,
253+
MVT::Other, // outchain type
254+
{
255+
CurDAG->getConstant(0, DL, MVT::i32), // placeholder
256+
Node->getOperand(0) // inchain
257+
});
258+
ReplaceNode(Node, Rethrow);
259+
return;
260+
}
248261
}
249262
break;
250263
}

llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,9 @@ let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
132132
defm THROW : I<(outs), (ins tag_op:$tag, variable_ops),
133133
(outs), (ins tag_op:$tag), [],
134134
"throw \t$tag", "throw \t$tag", 0x08>;
135-
defm RETHROW : NRI<(outs), (ins i32imm:$depth), [], "rethrow \t$depth", 0x09>;
135+
// $ehpad is the EH pad where the exception to rethrow has been caught.
136+
defm RETHROW : NRI<(outs), (ins bb_op:$ehpad), [], "rethrow \t$ehpad", 0x09>;
136137
} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
137-
// The depth argument will be computed in CFGStackify. We set it to 0 here for
138-
// now.
139-
def : Pat<(int_wasm_rethrow), (RETHROW 0)>;
140138

141139
// Region within which an exception is caught: try / end_try
142140
let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in {
@@ -160,7 +158,8 @@ defm DELEGATE : NRI<(outs), (ins bb_op:$dst), [], "delegate \t $dst", 0x18>;
160158
// Pseudo instructions: cleanupret / catchret
161159
let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
162160
isPseudo = 1, isEHScopeReturn = 1 in {
163-
defm CLEANUPRET : NRI<(outs), (ins), [(cleanupret)], "cleanupret", 0>;
161+
defm CLEANUPRET : NRI<(outs), (ins bb_op:$ehpad), [(cleanupret bb:$ehpad)],
162+
"cleanupret", 0>;
164163
defm CATCHRET : NRI<(outs), (ins bb_op:$dst, bb_op:$from),
165164
[(catchret bb:$dst, bb:$from)], "catchret", 0>;
166165
} // isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,

llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,39 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
245245
Changed = true;
246246
break;
247247
}
248+
case WebAssembly::RETHROW:
249+
// These RETHROWs here were lowered from llvm.wasm.rethrow() intrinsics,
250+
// generated in Clang for when an exception is not caught by the given
251+
// type (e.g. catch (int)).
252+
//
253+
// RETHROW's BB argument is the EH pad where the exception to rethrow has
254+
// been caught. (Until this point, RETHROW has just a '0' as a placeholder
255+
// argument.) For these llvm.wasm.rethrow()s, we can safely assume the
256+
// exception comes from the nearest dominating EH pad, because catch.start
257+
// EH pad is structured like this:
258+
//
259+
// catch.start:
260+
// catchpad ...
261+
// %matches = compare ehselector with typeid
262+
// br i1 %matches, label %catch, label %rethrow
263+
//
264+
// rethrow:
265+
// ;; rethrows the exception caught in 'catch.start'
266+
// call @llvm.wasm.rethrow()
267+
TI->removeOperand(0);
268+
TI->addOperand(MachineOperand::CreateMBB(getMatchingEHPad(TI)));
269+
Changed = true;
270+
break;
248271
case WebAssembly::CLEANUPRET: {
249-
// Replace a cleanupret with a rethrow. For C++ support, currently
250-
// rethrow's immediate argument is always 0 (= the latest exception).
272+
// CLEANUPRETs have the EH pad BB the exception to rethrow has been caught
273+
// as an argument. Use it and change the instruction opcode to 'RETHROW'
274+
// to make rethrowing instructions consistent.
275+
//
276+
// This is because we cannot safely assume that it is always the nearest
277+
// dominating EH pad, in case there are code transformations such as
278+
// inlining.
251279
BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::RETHROW))
252-
.addImm(0);
280+
.addMBB(TI->getOperand(0).getMBB());
253281
TI->eraseFromParent();
254282
Changed = true;
255283
break;

llvm/lib/Target/X86/X86InstrCompiler.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
195195

196196
let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
197197
isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1 in {
198-
def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>;
198+
def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET",
199+
[(cleanupret bb)]>;
199200

200201
// CATCHRET needs a custom inserter for SEH.
201202
let usesCustomInserter = 1 in

llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.mir

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ body: |
3939
; CHECK: RETHROW 1
4040
EH_LABEL <mcsymbol .Ltmp2>
4141
%0:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
42-
RETHROW 0, implicit-def dead $arguments
42+
RETHROW %bb.1, implicit-def dead $arguments
4343
4444
bb.2 (landing-pad):
45+
successors: %bb.3
4546
; CHECK: bb.2 (landing-pad):
4647
; CHECK: CATCH
4748
; CHECK: RETHROW 0
4849
EH_LABEL <mcsymbol .Ltmp3>
4950
%1:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
50-
RETHROW 0, implicit-def dead $arguments
51+
RETHROW %bb.2, implicit-def dead $arguments
5152
5253
bb.3:
5354
; CHECK: bb.3:
@@ -104,12 +105,14 @@ body: |
104105
RETURN %0:i32, implicit-def dead $arguments
105106
106107
bb.3 (landing-pad):
108+
successors:
107109
EH_LABEL <mcsymbol .Ltmp4>
108110
%0:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
109-
RETHROW 0, implicit-def dead $arguments
111+
RETHROW %bb.3, implicit-def dead $arguments
110112
111113
bb.4 (landing-pad):
114+
successors:
112115
EH_LABEL <mcsymbol .Ltmp5>
113116
%1:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
114-
RETHROW 0, implicit-def dead $arguments
117+
RETHROW %bb.4, implicit-def dead $arguments
115118
...

llvm/test/CodeGen/WebAssembly/exception-legacy.ll

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,107 @@ unreachable: ; preds = %rethrow
400400
unreachable
401401
}
402402

403+
; The bitcode below is generated when the code below is compiled and
404+
; Temp::~Temp() is inlined into inlined_cleanupret():
405+
;
406+
; void inlined_cleanupret() {
407+
; try {
408+
; Temp t;
409+
; throw 2;
410+
; } catch (...)
411+
; }
412+
;
413+
; Temp::~Temp() {
414+
; try {
415+
; throw 1;
416+
; } catch (...) {
417+
; }
418+
; }
419+
;
420+
; ~Temp() generates cleanupret, which is lowered to a 'rethrow' later. That
421+
; rethrow's immediate argument should correctly target the top-level cleanuppad
422+
; (catch_all). This is a regression test for the bug where we did not compute
423+
; rethrow's argument correctly.
424+
425+
; CHECK-LABEL: inlined_cleanupret:
426+
; CHECK: try
427+
; CHECK: call __cxa_throw
428+
; CHECK: catch_all
429+
; CHECK: try
430+
; CHECK: try
431+
; CHECK: call __cxa_throw
432+
; CHECK: catch
433+
; CHECK: call __cxa_end_catch
434+
; CHECK: try
435+
; CHECK: try
436+
; Note that this rethrow targets the top-level catch_all
437+
; CHECK: rethrow 4
438+
; CHECK: catch
439+
; CHECK: try
440+
; CHECK: call __cxa_end_catch
441+
; CHECK: delegate 5
442+
; CHECK: return
443+
; CHECK: end_try
444+
; CHECK: delegate 3
445+
; CHECK: end_try
446+
; CHECK: catch_all
447+
; CHECK: call _ZSt9terminatev
448+
; CHECK: end_try
449+
; CHECK: end_try
450+
define void @inlined_cleanupret() personality ptr @__gxx_wasm_personality_v0 {
451+
entry:
452+
%exception = tail call ptr @__cxa_allocate_exception(i32 4)
453+
store i32 2, ptr %exception, align 16
454+
invoke void @__cxa_throw(ptr nonnull %exception, ptr nonnull @_ZTIi, ptr null)
455+
to label %unreachable unwind label %ehcleanup
456+
457+
ehcleanup: ; preds = %entry
458+
%0 = cleanuppad within none []
459+
%exception.i = call ptr @__cxa_allocate_exception(i32 4) [ "funclet"(token %0) ]
460+
store i32 1, ptr %exception.i, align 16
461+
invoke void @__cxa_throw(ptr nonnull %exception.i, ptr nonnull @_ZTIi, ptr null) [ "funclet"(token %0) ]
462+
to label %unreachable unwind label %catch.dispatch.i
463+
464+
catch.dispatch.i: ; preds = %ehcleanup
465+
%1 = catchswitch within %0 [label %catch.start.i] unwind label %terminate.i
466+
467+
catch.start.i: ; preds = %catch.dispatch.i
468+
%2 = catchpad within %1 [ptr null]
469+
%3 = tail call ptr @llvm.wasm.get.exception(token %2)
470+
%4 = tail call i32 @llvm.wasm.get.ehselector(token %2)
471+
%5 = call ptr @__cxa_begin_catch(ptr %3) [ "funclet"(token %2) ]
472+
invoke void @__cxa_end_catch() [ "funclet"(token %2) ]
473+
to label %invoke.cont.i unwind label %terminate.i
474+
475+
invoke.cont.i: ; preds = %catch.start.i
476+
catchret from %2 to label %_ZN4TempD2Ev.exit
477+
478+
terminate.i: ; preds = %catch.start.i, %catch.dispatch.i
479+
%6 = cleanuppad within %0 []
480+
call void @_ZSt9terminatev() [ "funclet"(token %6) ]
481+
unreachable
482+
483+
_ZN4TempD2Ev.exit: ; preds = %invoke.cont.i
484+
cleanupret from %0 unwind label %catch.dispatch
485+
486+
catch.dispatch: ; preds = %_ZN4TempD2Ev.exit
487+
%7 = catchswitch within none [label %catch.start] unwind to caller
488+
489+
catch.start: ; preds = %catch.dispatch
490+
%8 = catchpad within %7 [ptr null]
491+
%9 = tail call ptr @llvm.wasm.get.exception(token %8)
492+
%10 = tail call i32 @llvm.wasm.get.ehselector(token %8)
493+
%11 = call ptr @__cxa_begin_catch(ptr %9) #8 [ "funclet"(token %8) ]
494+
call void @__cxa_end_catch() [ "funclet"(token %8) ]
495+
catchret from %8 to label %try.cont
496+
497+
try.cont: ; preds = %catch.start
498+
ret void
499+
500+
unreachable: ; preds = %entry
501+
unreachable
502+
}
503+
403504

404505
declare void @foo()
405506
declare void @bar(ptr)
@@ -415,8 +516,12 @@ declare i32 @llvm.wasm.get.ehselector(token) #0
415516
declare void @llvm.wasm.rethrow() #1
416517
; Function Attrs: nounwind
417518
declare i32 @llvm.eh.typeid.for(ptr) #0
519+
; Function Attrs: nounwind
520+
declare ptr @__cxa_allocate_exception(i32) #0
418521
declare ptr @__cxa_begin_catch(ptr)
419522
declare void @__cxa_end_catch()
523+
; Function Attrs: noreturn
524+
declare void @__cxa_throw(ptr, ptr, ptr) #1
420525
declare void @_ZSt9terminatev()
421526
declare ptr @_ZN4TempD2Ev(ptr returned)
422527

0 commit comments

Comments
 (0)