mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[WinEH] Make funclet return instrs pseudo instrs
This makes catchret look more like a branch, and less like a weird use of BlockAddress. It also lets us get away from llvm.x86.seh.restoreframe, which relies on the old parentfpoffset label arithmetic. llvm-svn: 247936
This commit is contained in:
parent
f2ab1ed0ec
commit
5370cf8a53
@ -452,6 +452,7 @@ def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
|
||||
def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
|
||||
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
|
||||
def catchret : SDNode<"ISD::CATCHRET" , SDTBr, [SDNPHasChain]>;
|
||||
def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>;
|
||||
|
||||
def trap : SDNode<"ISD::TRAP" , SDTNone,
|
||||
[SDNPHasChain, SDNPSideEffect]>;
|
||||
|
@ -141,6 +141,41 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
|
||||
// The EH_RETURN pseudo is really removed during the MC Lowering.
|
||||
return true;
|
||||
}
|
||||
|
||||
case X86::CLEANUPRET: {
|
||||
// Replace CATCHRET with the appropriate RET.
|
||||
unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL;
|
||||
BuildMI(MBB, MBBI, DL, TII->get(RetOp));
|
||||
MBBI->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
case X86::CATCHRET: {
|
||||
MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB();
|
||||
|
||||
// Fill EAX/RAX with the address of the target block.
|
||||
unsigned ReturnReg = STI->is64Bit() ? X86::RAX : X86::EAX;
|
||||
unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL;
|
||||
if (STI->is64Bit()) {
|
||||
// LEA64r TargetMBB(%rip), %rax
|
||||
BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), ReturnReg)
|
||||
.addReg(X86::RIP)
|
||||
.addImm(0)
|
||||
.addReg(0)
|
||||
.addMBB(TargetMBB)
|
||||
.addReg(0);
|
||||
} else {
|
||||
// MOV32ri $TargetMBB, %eax
|
||||
BuildMI(MBB, MBBI, DL, TII->get(X86::MOV32ri))
|
||||
.addReg(ReturnReg)
|
||||
.addMBB(TargetMBB);
|
||||
}
|
||||
|
||||
// Replace CATCHRET with the appropriate RET.
|
||||
BuildMI(MBB, MBBI, DL, TII->get(RetOp)).addReg(ReturnReg);
|
||||
MBBI->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Previous switch has a fallthrough?");
|
||||
}
|
||||
|
@ -711,7 +711,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
|
||||
.addReg(MachineFramePtr, RegState::Kill)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
// Reset EBP / ESI to something good.
|
||||
MBBI = restoreWin32EHFrameAndBasePtr(MBB, MBBI, DL);
|
||||
MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL);
|
||||
} else {
|
||||
// FIXME: Add SEH directives.
|
||||
NeedsWinCFI = false;
|
||||
@ -1038,9 +1038,7 @@ bool X86FrameLowering::canUseLEAForSPInEpilogue(
|
||||
static bool isFuncletReturnInstr(MachineInstr *MI) {
|
||||
switch (MI->getOpcode()) {
|
||||
case X86::CATCHRET:
|
||||
case X86::CATCHRET64:
|
||||
case X86::CLEANUPRET:
|
||||
case X86::CLEANUPRET64:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -1073,13 +1071,51 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
|
||||
uint64_t NumBytes = 0;
|
||||
|
||||
if (isFuncletReturnInstr(MBBI)) {
|
||||
if (MBBI->getOpcode() == X86::CATCHRET) {
|
||||
NumBytes = MFI->getMaxCallFrameSize();
|
||||
assert(hasFP(MF) && "win64 EH funclets without FP not yet implemented");
|
||||
assert(hasFP(MF) && "EH funclets without FP not yet implemented");
|
||||
MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB();
|
||||
|
||||
// If this is SEH, this isn't really a funclet return.
|
||||
bool IsSEH = isAsynchronousEHPersonality(
|
||||
classifyEHPersonality(MF.getFunction()->getPersonalityFn()));
|
||||
if (IsSEH) {
|
||||
if (STI.is32Bit())
|
||||
restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/true);
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB);
|
||||
MBBI->eraseFromParent();
|
||||
return;
|
||||
}
|
||||
|
||||
// For 32-bit, create a new block for the restore code.
|
||||
MachineBasicBlock *RestoreMBB = TargetMBB;
|
||||
if (STI.is32Bit()) {
|
||||
RestoreMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
|
||||
MF.insert(TargetMBB, RestoreMBB);
|
||||
MBB.transferSuccessors(RestoreMBB);
|
||||
MBB.addSuccessor(RestoreMBB);
|
||||
MBBI->getOperand(0).setMBB(RestoreMBB);
|
||||
}
|
||||
|
||||
// Pop EBP.
|
||||
BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r),
|
||||
MachineFramePtr).setMIFlag(MachineInstr::FrameDestroy);
|
||||
MachineFramePtr)
|
||||
.setMIFlag(MachineInstr::FrameDestroy);
|
||||
|
||||
// Insert frame restoration code in a new block.
|
||||
if (STI.is32Bit()) {
|
||||
auto RestoreMBBI = RestoreMBB->begin();
|
||||
restoreWin32EHStackPointers(*RestoreMBB, RestoreMBBI, DL,
|
||||
/*RestoreSP=*/true);
|
||||
BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::JMP_4))
|
||||
.addMBB(TargetMBB);
|
||||
}
|
||||
} else if (isFuncletReturnInstr(MBBI)) {
|
||||
NumBytes = MFI->getMaxCallFrameSize();
|
||||
assert(hasFP(MF) && "EH funclets without FP not yet implemented");
|
||||
BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r),
|
||||
MachineFramePtr)
|
||||
.setMIFlag(MachineInstr::FrameDestroy);
|
||||
} else if (hasFP(MF)) {
|
||||
// Calculate required stack adjustment.
|
||||
uint64_t FrameSize = StackSize - SlotSize;
|
||||
@ -2067,9 +2103,9 @@ bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
|
||||
return !terminatorsNeedFlagsAsInput(MBB);
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
|
||||
MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
DebugLoc DL) const {
|
||||
DebugLoc DL, bool RestoreSP) const {
|
||||
assert(STI.isTargetWindowsMSVC() && "funclets only supported in MSVC env");
|
||||
assert(STI.isTargetWin32() && "EBP/ESI restoration only required on win32");
|
||||
assert(STI.is32Bit() && !Uses64BitFramePtr &&
|
||||
@ -2087,13 +2123,22 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
|
||||
// FIXME: Don't set FrameSetup flag in catchret case.
|
||||
|
||||
int FI = FuncInfo.EHRegNodeFrameIndex;
|
||||
int EHRegSize = MFI->getObjectSize(FI);
|
||||
|
||||
if (RestoreSP) {
|
||||
// MOV32rm -EHRegSize(%ebp), %esp
|
||||
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), X86::ESP),
|
||||
X86::EBP, true, -EHRegSize)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
}
|
||||
|
||||
unsigned UsedReg;
|
||||
int EHRegOffset = getFrameIndexReference(MF, FI, UsedReg);
|
||||
int EHRegSize = MFI->getObjectSize(FI);
|
||||
int EndOffset = -EHRegOffset - EHRegSize;
|
||||
FuncInfo.EHRegNodeEndOffset = EndOffset;
|
||||
assert(EndOffset >= 0 &&
|
||||
"end of registration object above normal EBP position!");
|
||||
|
||||
if (UsedReg == FramePtr) {
|
||||
// ADD $offset, %ebp
|
||||
assert(UsedReg == FramePtr);
|
||||
@ -2110,14 +2155,13 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
|
||||
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA32r), BasePtr),
|
||||
FramePtr, false, EndOffset)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
// MOV32mr SavedEBPOffset(%esi), %ebp
|
||||
// MOV32rm SavedEBPOffset(%esi), %ebp
|
||||
assert(X86FI->getHasSEHFramePtrSave());
|
||||
int Offset =
|
||||
getFrameIndexReference(MF, X86FI->getSEHFramePtrSaveIndex(), UsedReg);
|
||||
assert(UsedReg == BasePtr);
|
||||
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32mr)), UsedReg, true,
|
||||
Offset)
|
||||
.addReg(FramePtr)
|
||||
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), FramePtr),
|
||||
UsedReg, true, Offset)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
}
|
||||
return MBBI;
|
||||
|
@ -158,9 +158,9 @@ private:
|
||||
/// Sets up EBP and optionally ESI based on the incoming EBP value. Only
|
||||
/// needed for 32-bit. Used in funclet prologues and at catchret destinations.
|
||||
MachineBasicBlock::iterator
|
||||
restoreWin32EHFrameAndBasePtr(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
DebugLoc DL) const;
|
||||
restoreWin32EHStackPointers(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI, DebugLoc DL,
|
||||
bool RestoreSP = false) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -417,8 +417,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
||||
setOperationAction(ISD::SETCC , MVT::i64 , Custom);
|
||||
}
|
||||
setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
|
||||
setOperationAction(ISD::CATCHRET , MVT::Other, Custom);
|
||||
setOperationAction(ISD::CLEANUPRET , MVT::Other, Custom);
|
||||
// NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support
|
||||
// SjLj exception handling but a light-weight setjmp/longjmp replacement to
|
||||
// support continuation, user-level threading, and etc.. As a result, no
|
||||
@ -16922,41 +16920,6 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
|
||||
DAG.getRegister(StoreAddrReg, PtrVT));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Dest = Op.getOperand(1);
|
||||
SDLoc DL(Op);
|
||||
|
||||
MVT PtrVT = getPointerTy(DAG.getDataLayout());
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
if (isAsynchronousEHPersonality(
|
||||
classifyEHPersonality(MF.getFunction()->getPersonalityFn()))) {
|
||||
// For SEH, codegen catchret as a branch for now.
|
||||
// FIXME: Insert something to restore the frame.
|
||||
return DAG.getNode(ISD::BR, DL, MVT::Other, Chain, Dest);
|
||||
}
|
||||
|
||||
unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX);
|
||||
|
||||
// Load the address of the destination block.
|
||||
// FIXME: Do this without creating a BlockAddress.
|
||||
MachineBasicBlock *DestMBB = cast<BasicBlockSDNode>(Dest)->getBasicBlock();
|
||||
BlockAddress *BA =
|
||||
BlockAddress::get(const_cast<Function *>(MF.getFunction()),
|
||||
const_cast<BasicBlock *>(DestMBB->getBasicBlock()));
|
||||
DestMBB->setHasAddressTaken();
|
||||
SDValue BlockPtr = DAG.getBlockAddress(BA, PtrVT);
|
||||
Chain = DAG.getCopyToReg(Chain, DL, ReturnReg, BlockPtr);
|
||||
return DAG.getNode(X86ISD::CATCHRET, DL, MVT::Other, Chain,
|
||||
DAG.getRegister(ReturnReg, PtrVT));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerCLEANUPRET(SDValue Op, SelectionDAG &DAG) const {
|
||||
return DAG.getNode(X86ISD::CLEANUPRET, SDLoc(Op), MVT::Other,
|
||||
Op.getOperand(0));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
@ -19198,8 +19161,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
||||
case ISD::CLEANUPRET: return LowerCLEANUPRET(Op, DAG);
|
||||
case ISD::CATCHRET: return LowerCATCHRET(Op, DAG);
|
||||
case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG);
|
||||
case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG);
|
||||
case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
|
||||
@ -19537,8 +19498,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP";
|
||||
case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP";
|
||||
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
|
||||
case X86ISD::CATCHRET: return "X86ISD::CATCHRET";
|
||||
case X86ISD::CLEANUPRET: return "X86ISD::CLEANUPRET";
|
||||
case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN";
|
||||
case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m";
|
||||
case X86ISD::FNSTSW16r: return "X86ISD::FNSTSW16r";
|
||||
|
@ -268,14 +268,6 @@ namespace llvm {
|
||||
// Exception Handling helpers.
|
||||
EH_RETURN,
|
||||
|
||||
// CATCHRET - Represents a return from a catch block funclet. Used for
|
||||
// MSVC compatible exception handling. Takes a chain operand and RAX.
|
||||
CATCHRET,
|
||||
|
||||
// CLEANUPRET - Represents a return from a cleanup block funclet. Used
|
||||
// for MSVC compatible exception handling. Takes only a chain operand.
|
||||
CLEANUPRET,
|
||||
|
||||
// SjLj exception handling setjmp.
|
||||
EH_SJLJ_SETJMP,
|
||||
|
||||
@ -1014,7 +1006,6 @@ namespace llvm {
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCLEANUPRET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
@ -153,20 +153,10 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
}
|
||||
|
||||
let isTerminator = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1, isReturn = 1 in {
|
||||
def CATCHRET : I<0xC3, RawFrm, (outs), (ins GR32:$addr),
|
||||
"ret{l}\t# CATCHRET",
|
||||
[(X86catchret GR32:$addr)], IIC_RET>, Sched<[WriteJumpLd]>;
|
||||
def CATCHRET64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
"ret{q}\t# CATCHRET",
|
||||
[(X86catchret GR64:$addr)], IIC_RET>, Sched<[WriteJumpLd]>;
|
||||
def CLEANUPRET : I<0xC3, RawFrm, (outs), (ins),
|
||||
"ret{l}\t# CLEANUPRET",
|
||||
[(X86cleanupret)], IIC_RET>, Sched<[WriteJumpLd]>,
|
||||
Requires<[Not64BitMode]>;
|
||||
def CLEANUPRET64 : I<0xC3, RawFrm, (outs), (ins),
|
||||
"ret{q}\t# CLEANUPRET",
|
||||
[(X86cleanupret)], IIC_RET>, Sched<[WriteJumpLd]>,
|
||||
Requires<[In64BitMode]>;
|
||||
def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst),
|
||||
"# CATCHRET",
|
||||
[(catchret bb:$dst)]>;
|
||||
def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>;
|
||||
}
|
||||
|
||||
let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
|
||||
|
@ -205,10 +205,6 @@ def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR,
|
||||
def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
def X86catchret : SDNode<"X86ISD::CATCHRET", SDT_X86EHRET, [SDNPHasChain]>;
|
||||
|
||||
def X86cleanupret : SDNode<"X86ISD::CLEANUPRET", SDTX86Void, [SDNPHasChain]>;
|
||||
|
||||
def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP",
|
||||
SDTypeProfile<1, 1, [SDTCisInt<0>,
|
||||
SDTCisPtrTy<1>]>,
|
||||
|
@ -531,13 +531,6 @@ ReSimplify:
|
||||
break;
|
||||
}
|
||||
|
||||
case X86::CATCHRET:
|
||||
case X86::CATCHRET64: {
|
||||
OutMI = MCInst();
|
||||
OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget()));
|
||||
break;
|
||||
}
|
||||
|
||||
// TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions.
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPd:
|
||||
|
@ -500,15 +500,6 @@ void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode,
|
||||
insertStateNumberStore(ParentRegNode, II, State);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert calls to llvm.x86.seh.restoreframe at catchret destinations. In
|
||||
// SEH, insert them before the catchret.
|
||||
// FIXME: We should probably do this as part of catchret lowering in the
|
||||
// DAG.
|
||||
if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator()))
|
||||
insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH
|
||||
? CR->getParent()
|
||||
: CR->getSuccessor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,9 +59,7 @@ catchendblock: ; preds = %catch,
|
||||
; X86: movl $0, -{{[0-9]+}}(%ebp)
|
||||
; X86: movl $1, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: [[contbb:Ltmp[0-9]+]]: # Block address taken
|
||||
; X86: movl -{{[0-9]+}}(%ebp), %esp
|
||||
; X86: addl ${{[0-9]+}}, %esp
|
||||
; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont
|
||||
; X86: popl %esi
|
||||
; X86: popl %edi
|
||||
; X86: popl %ebx
|
||||
@ -76,11 +74,17 @@ catchendblock: ; preds = %catch,
|
||||
; X86: movl $1, -{{[0-9]+}}(%ebp)
|
||||
; X86: movl $2, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: movl $[[contbb]], %eax
|
||||
; X86-NEXT: addl $16, %esp
|
||||
; X86: addl $16, %esp
|
||||
; X86-NEXT: popl %ebp
|
||||
; X86-NEXT: movl $[[restorebb:LBB0_[0-9]+]], %eax
|
||||
; X86-NEXT: retl
|
||||
|
||||
; FIXME: Lay this out in the parent funclet.
|
||||
; X86: [[restorebb]]:
|
||||
; X86: movl -16(%ebp), %esp
|
||||
; X86: addl $12, %ebp
|
||||
; X86: jmp [[contbb]]
|
||||
|
||||
; X86: L__ehtable$try_catch_catch:
|
||||
; X86: $handlerMap$0$try_catch_catch:
|
||||
; X86: .long 0
|
||||
@ -108,7 +112,7 @@ catchendblock: ; preds = %catch,
|
||||
; X64: callq useints
|
||||
; X64: movl $1, %ecx
|
||||
; X64: callq f
|
||||
; X64: [[contbb:.Ltmp[0-9]+]]: # Block address taken
|
||||
; X64: [[contbb:\.LBB0_[0-9]+]]: # %try.cont
|
||||
; X64: addq $40, %rsp
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
@ -120,9 +124,9 @@ catchendblock: ; preds = %catch,
|
||||
; X64: subq $32, %rsp
|
||||
; X64: movl $2, %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: addq $32, %rsp
|
||||
; X64: popq %rbp
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: retq
|
||||
|
||||
; X64: $handlerMap$0$try_catch_catch:
|
||||
|
@ -70,8 +70,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X86-DAG: movl %[[addr_reg]], 4(%esp)
|
||||
; X86-DAG: movl $1, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: [[contbb:Ltmp[0-9]+]]: # Block address taken
|
||||
; X86: movl -{{[0-9]+}}(%ebp), %esp
|
||||
; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont
|
||||
; X86: retl
|
||||
|
||||
; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}}
|
||||
@ -84,9 +83,9 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X86-DAG: movl %[[addr_reg]], 4(%esp)
|
||||
; X86-DAG: movl %[[e_reg]], (%esp)
|
||||
; X86: calll _f
|
||||
; X86: movl $[[contbb]], %eax
|
||||
; X86-NEXT: addl $8, %esp
|
||||
; X86-NEXT: popl %ebp
|
||||
; X86-NEXT: movl $[[restorebb:LBB0_[0-9]+]], %eax
|
||||
; X86-NEXT: retl
|
||||
|
||||
; X86: [[catch2bb:LBB0_[0-9]+]]: # %catch.2{{$}}
|
||||
@ -98,11 +97,17 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X86-DAG: movl %[[addr_reg]], 4(%esp)
|
||||
; X86-DAG: movl $3, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: movl $[[contbb]], %eax
|
||||
; X86-NEXT: addl $8, %esp
|
||||
; X86-NEXT: popl %ebp
|
||||
; X86-NEXT: movl $[[restorebb]], %eax
|
||||
; X86-NEXT: retl
|
||||
|
||||
; FIXME: We should lay this code out up with the parent function.
|
||||
; X86: [[restorebb]]:
|
||||
; X86: movl -16(%ebp), %esp
|
||||
; X86: addl $12, %ebp
|
||||
; X86: jmp [[contbb]]
|
||||
|
||||
; X86: L__ehtable$try_catch_catch:
|
||||
; X86: $handlerMap$0$try_catch_catch:
|
||||
; X86-NEXT: .long 0
|
||||
@ -124,7 +129,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx
|
||||
; X64-DAG: movl $1, %ecx
|
||||
; X64: callq f
|
||||
; X64: [[contbb:.Ltmp[0-9]+]]: # Block address taken
|
||||
; X64: [[contbb:\.LBB0_[0-9]+]]: # %try.cont
|
||||
; X64: addq $48, %rsp
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
@ -137,10 +142,10 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
|
||||
; X64-DAG: movl [[e_addr:[-0-9]+]](%rbp), %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: addq $32, %rsp
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
; X64-NEXT: popq %rbp
|
||||
; X64-NEXT: leaq [[contbb]](%rip), %rax
|
||||
; X64-NEXT: retq
|
||||
|
||||
; X64: [[catch2bb:\.LBB0_[0-9]+]]: # %catch.2{{$}}
|
||||
; X64: movq %rdx, 16(%rsp)
|
||||
@ -150,10 +155,10 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
||||
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
|
||||
; X64-DAG: movl $3, %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: addq $32, %rsp
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
; X64-NEXT: popq %rbp
|
||||
; X64-NEXT: leaq [[contbb]](%rip), %rax
|
||||
; X64-NEXT: retq
|
||||
|
||||
; X64: $handlerMap$0$try_catch_catch:
|
||||
; X64: .long 0
|
||||
|
@ -66,14 +66,18 @@ cleanup.outer: ; preds = %invoke.cont.1, %c
|
||||
; X86: calll _f
|
||||
|
||||
; X86: LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner
|
||||
; X86: pushl %ebp
|
||||
; X86: leal {{.*}}(%ebp), %ecx
|
||||
; X86: calll "??1Dtor@@QAE@XZ"
|
||||
; X86: retl # CLEANUPRET
|
||||
; X86: popl %ebp
|
||||
; X86: retl
|
||||
|
||||
; X86: LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer
|
||||
; X86: pushl %ebp
|
||||
; X86: leal {{.*}}(%ebp), %ecx
|
||||
; X86: calll "??1Dtor@@QAE@XZ"
|
||||
; X86: retl # CLEANUPRET
|
||||
; X86: popl %ebp
|
||||
; X86: retl
|
||||
|
||||
; X86: L__ehtable$nested_cleanup:
|
||||
; X86: .long 429065506
|
||||
@ -100,14 +104,18 @@ cleanup.outer: ; preds = %invoke.cont.1, %c
|
||||
; X64: callq f
|
||||
|
||||
; X64: .LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner
|
||||
; X64: pushq %rbp
|
||||
; X64: leaq {{.*}}(%rbp), %rcx
|
||||
; X64: callq "??1Dtor@@QAE@XZ"
|
||||
; X64: retq # CLEANUPRET
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
|
||||
; X64: .LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer
|
||||
; X64: pushq %rbp
|
||||
; X64: leaq {{.*}}(%rbp), %rcx
|
||||
; X64: callq "??1Dtor@@QAE@XZ"
|
||||
; X64: retq # CLEANUPRET
|
||||
; X64: popq %rbp
|
||||
; X64: retq
|
||||
|
||||
; X64: .seh_handlerdata
|
||||
; X64: .long ($cppxdata$nested_cleanup)@IMGREL
|
||||
|
Loading…
x
Reference in New Issue
Block a user