diff options
| -rw-r--r-- | llvm/include/llvm/CodeGen/MachineBasicBlock.h | 9 | ||||
| -rw-r--r-- | llvm/include/llvm/CodeGen/WinEHFuncInfo.h | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h | 6 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 150 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinException.h | 7 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 5 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/seh-prepared-basic.ll | 3 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/gcc_except_table.ll | 2 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/seh-catch-all.ll | 4 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/seh-except-finally.ll | 4 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/seh-finally.ll | 4 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/seh-safe-div.ll | 4 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/win-catchpad-csrs.ll | 10 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/win-catchpad.ll | 20 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/win-cleanuppad.ll | 45 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/win-funclet-cfi.ll | 100 | 
18 files changed, 319 insertions, 65 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 511cc2a4500..33230f92828 100644 --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -114,6 +114,9 @@ protected:    /// Indicate that this basic block is the entry block of an EH funclet.    bool IsEHFuncletEntry = false; +  /// Indicate that this basic block is the entry block of a cleanup funclet. +  bool IsCleanupFuncletEntry = false; +    /// \brief since getSymbol is a relatively heavy-weight operation, the symbol    /// is only computed once and is cached.    mutable MCSymbol *CachedMCSymbol = nullptr; @@ -392,6 +395,12 @@ public:    /// Indicates if this is the entry block of an EH funclet.    void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; } +  /// Returns true if this is the entry block of a cleanup funclet. +  bool isCleanupFuncletEntry() const { return IsCleanupFuncletEntry; } + +  /// Indicates if this is the entry block of a cleanup funclet. +  void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; } +    // Code Layout methods.    /// Move 'this' block before or after the specified block.  This only moves diff --git a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h index ac19ddf86bd..6563494357e 100644 --- a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h @@ -118,7 +118,7 @@ void parseEHActions(const IntrinsicInst *II,  // exceptions on Windows.  typedef PointerUnion<const BasicBlock *, MachineBasicBlock *> MBBOrBasicBlock; -typedef PointerUnion<const Value *, MachineBasicBlock *> ValueOrMBB; +typedef PointerUnion<const Value *, const MachineBasicBlock *> ValueOrMBB;  struct WinEHUnwindMapEntry {    int ToState; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 141cc0fc6e8..52dbd5a9df4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2459,6 +2459,14 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,  /// MachineBasicBlock, an alignment (if present) and a comment describing  /// it if appropriate.  void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { +  // End the previous funclet and start a new one. +  if (MBB.isEHFuncletEntry()) { +    for (const HandlerInfo &HI : Handlers) { +      HI.Handler->endFunclet(); +      HI.Handler->beginFunclet(MBB); +    } +  } +    // Emit an alignment directive for this block, if needed.    if (unsigned Align = MBB.getAlignment())      EmitAlignment(Align); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h index f1efe9d835e..e59961f8576 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h @@ -19,6 +19,7 @@  namespace llvm { +class MachineBasicBlock;  class MachineFunction;  class MachineInstr;  class MCSymbol; @@ -50,6 +51,11 @@ public:    /// beginFunction at all.    virtual void endFunction(const MachineFunction *MF) = 0; +  /// \brief Emit target-specific EH funclet machinery. +  virtual void beginFunclet(const MachineBasicBlock &MBB, +                            MCSymbol *Sym = nullptr) {} +  virtual void endFunclet() {} +    /// \brief Process beginning of an instruction.    virtual void beginInstruction(const MachineInstr *MI) = 0; diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index f662a1b5e70..f4a279e5fe8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -30,6 +30,7 @@  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MCSymbol.h"  #include "llvm/MC/MCWin64EH.h" +#include "llvm/Support/COFF.h"  #include "llvm/Support/Dwarf.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/FormattedStream.h" @@ -98,14 +99,7 @@ void WinException::beginFunction(const MachineFunction *MF) {      return;    } -  if (shouldEmitMoves || shouldEmitPersonality) -    Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym); - -  if (shouldEmitPersonality) { -    const MCSymbol *PersHandlerSym = -        TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); -    Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true); -  } +  beginFunclet(MF->front(), Asm->CurrentFnSym);  }  /// endFunction - Gather and emit post-function exception information. @@ -125,20 +119,16 @@ void WinException::endFunction(const MachineFunction *MF) {    if (!isMSVCEHPersonality(Per))      MMI->TidyLandingPads(); +  endFunclet(); +    if (shouldEmitPersonality || shouldEmitLSDA) {      Asm->OutStreamer->PushSection(); -    if (shouldEmitMoves || shouldEmitPersonality) { -      // Emit an UNWIND_INFO struct describing the prologue. -      Asm->OutStreamer->EmitWinEHHandlerData(); -    } else { -      // Just switch sections to the right xdata section. This use of -      // CurrentFnSym assumes that we only emit the LSDA when ending the parent -      // function. -      MCSection *XData = WinEH::UnwindEmitter::getXDataSection( -          Asm->CurrentFnSym, Asm->OutContext); -      Asm->OutStreamer->SwitchSection(XData); -    } +    // Just switch sections to the right xdata section. This use of CurrentFnSym +    // assumes that we only emit the LSDA when ending the parent function. +    MCSection *XData = WinEH::UnwindEmitter::getXDataSection(Asm->CurrentFnSym, +                                                             Asm->OutContext); +    Asm->OutStreamer->SwitchSection(XData);      // Emit the tables appropriate to the personality function in use. If we      // don't recognize the personality, assume it uses an Itanium-style LSDA. @@ -153,9 +143,120 @@ void WinException::endFunction(const MachineFunction *MF) {      Asm->OutStreamer->PopSection();    } +} + +/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues +/// are used in the old WinEH scheme, and they will be removed eventually. +static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) { +  if (!Handler) +    return nullptr; +  if (Handler.is<const MachineBasicBlock *>()) { +    auto *MBB = Handler.get<const MachineBasicBlock *>(); +    assert(MBB->isEHFuncletEntry()); + +    // Give catches and cleanups a name based off of their parent function and +    // their funclet entry block's number. +    const MachineFunction *MF = MBB->getParent(); +    const Function *F = MF->getFunction(); +    StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName()); +    MCContext &Ctx = MF->getContext(); +    StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? "dtor" : "catch"; +    return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" + +                                 Twine(MBB->getNumber()) + "@?0?" + +                                 FuncLinkageName + "@4HA"); +  } +  return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>())); +} + +void WinException::beginFunclet(const MachineBasicBlock &MBB, +                                MCSymbol *Sym) { +  CurrentFuncletEntry = &MBB; + +  const Function *F = Asm->MF->getFunction(); +  // If a symbol was not provided for the funclet, invent one. +  if (!Sym) { +    Sym = getMCSymbolForMBBOrGV(Asm, &MBB); + +    // Describe our funclet symbol as a function with internal linkage. +    Asm->OutStreamer->BeginCOFFSymbolDef(Sym); +    Asm->OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC); +    Asm->OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION +                                         << COFF::SCT_COMPLEX_TYPE_SHIFT); +    Asm->OutStreamer->EndCOFFSymbolDef(); + +    // We want our funclet's entry point to be aligned such that no nops will be +    // present after the label. +    Asm->EmitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()), +                       F); + +    // Now that we've emitted the alignment directive, point at our funclet. +    Asm->OutStreamer->EmitLabel(Sym); +  } +  // Mark 'Sym' as starting our funclet.    if (shouldEmitMoves || shouldEmitPersonality) +    Asm->OutStreamer->EmitWinCFIStartProc(Sym); + +  if (shouldEmitPersonality) { +    const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); +    const Function *PerFn = nullptr; + +    // Determine which personality routine we are using for this funclet. +    if (F->hasPersonalityFn()) +      PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts()); +    const MCSymbol *PersHandlerSym = +        TLOF.getCFIPersonalitySymbol(PerFn, *Asm->Mang, Asm->TM, MMI); + +    // Classify the personality routine so that we may reason about it. +    EHPersonality Per = EHPersonality::Unknown; +    if (F->hasPersonalityFn()) +      Per = classifyEHPersonality(F->getPersonalityFn()); + +    // Do not emit a .seh_handler directive if it is a C++ cleanup funclet. +    if (Per != EHPersonality::MSVC_CXX || +        !CurrentFuncletEntry->isCleanupFuncletEntry()) +      Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true); +  } +} + +void WinException::endFunclet() { +  // No funclet to process?  Great, we have nothing to do. +  if (!CurrentFuncletEntry) +    return; + +  if (shouldEmitMoves || shouldEmitPersonality) { +    const Function *F = Asm->MF->getFunction(); +    EHPersonality Per = EHPersonality::Unknown; +    if (F->hasPersonalityFn()) +      Per = classifyEHPersonality(F->getPersonalityFn()); + +    // The .seh_handlerdata directive implicitly switches section, push the +    // current section so that we may return to it. +    Asm->OutStreamer->PushSection(); + +    // Emit an UNWIND_INFO struct describing the prologue. +    Asm->OutStreamer->EmitWinEHHandlerData(); + +    // If this is a C++ catch funclet (or the parent function), +    // emit a reference to the LSDA for the parent function. +    if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality && +        !CurrentFuncletEntry->isCleanupFuncletEntry()) { +      StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName()); +      MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol( +          Twine("$cppxdata$", FuncLinkageName)); +      Asm->OutStreamer->EmitValue(create32bitRef(FuncInfoXData), 4); +    } + +    // Switch back to the previous section now that we are done writing to +    // .xdata. +    Asm->OutStreamer->PopSection(); + +    // Emit a .seh_endproc directive to mark the end of the function.      Asm->OutStreamer->EmitWinCFIEndProc(); +  } + +  // Let's make sure we don't try to end the same funclet twice. +  CurrentFuncletEntry = nullptr;  }  const MCExpr *WinException::create32bitRef(const MCSymbol *Value) { @@ -299,16 +400,6 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {    }  } -/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues -/// are used in the old WinEH scheme, and they will be removed eventually. -static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) { -  if (!Handler) -    return nullptr; -  if (Handler.is<MachineBasicBlock *>()) -    return Handler.get<MachineBasicBlock *>()->getSymbol(); -  return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>())); -} -  void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {    const Function *F = MF->getFunction();    auto &OS = *Asm->OutStreamer; @@ -323,7 +414,6 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {      // IPs to state numbers.      FuncInfoXData =          Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName)); -    OS.EmitValue(create32bitRef(FuncInfoXData), 4);      computeIP2StateTable(MF, FuncInfo, IPToStateTable);    } else {      FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName); diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.h b/llvm/lib/CodeGen/AsmPrinter/WinException.h index 37d2ab6ae4e..bf1724f60f7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.h +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.h @@ -36,6 +36,9 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {    /// True if this is a 64-bit target and we should use image relative offsets.    bool useImageRel32 = false; +  /// Pointer to the current funclet entry BB. +  const MachineBasicBlock *CurrentFuncletEntry = nullptr; +    void emitCSpecificHandlerTable(const MachineFunction *MF);    /// Emit the EH table data for 32-bit and 64-bit functions using @@ -76,6 +79,10 @@ public:    /// Gather and emit post-function exception information.    void endFunction(const MachineFunction *) override; + +  /// \brief Emit target-specific EH funclet machinery. +  void beginFunclet(const MachineBasicBlock &MBB, MCSymbol *Sym) override; +  void endFunclet() override;  };  } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 3e80cd8e5db..8b0ef1b0ebc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1182,6 +1182,7 @@ void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {    // Don't emit any special code for the cleanuppad instruction. It just marks    // the start of a funclet.    FuncInfo.MBB->setIsEHFuncletEntry(); +  FuncInfo.MBB->setIsCleanupFuncletEntry();  }  /// When an invoke or a cleanupret unwinds to the next EH pad, there are diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index e4c35b115e0..0e6b5c4b404 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -713,8 +713,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,        // Reset EBP / ESI to something good.        MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL);      } else { -      // FIXME: Add SEH directives. -      NeedsWinCFI = false;        // Immediately spill RDX into the home slot. The runtime cares about this.        unsigned RDX = Uses64BitFramePtr ? X86::RDX : X86::EDX;        // MOV64mr %rdx, 16(%rsp) @@ -727,6 +725,9 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,        BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64r))            .addReg(MachineFramePtr, RegState::Kill)            .setMIFlag(MachineInstr::FrameSetup); +      BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)) +          .addImm(MachineFramePtr) +          .setMIFlag(MachineInstr::FrameSetup);        // MOV64rr %rdx, %rbp        unsigned MOVrr = Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr;        BuildMI(MBB, MBBI, DL, TII.get(MOVrr), FramePtr) diff --git a/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll b/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll index d4ff04c9fe1..51ffe7bb3bd 100644 --- a/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll +++ b/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll @@ -35,6 +35,9 @@ __try.cont:                                       ; preds = %lpad1, %entry  ; CHECK: .seh_handler __C_specific_handler  ; CHECK-NOT: jmpq *  ; CHECK: .seh_handlerdata +; CHECK-NEXT: .text +; CHECK: .seh_endproc +; CHECK: .section .xdata,"dr"  ; CHECK-NEXT: .long 1  ; CHECK-NEXT: .long .Ltmp{{.*}}  ; CHECK-NEXT: .long .Ltmp{{.*}} diff --git a/llvm/test/CodeGen/X86/gcc_except_table.ll b/llvm/test/CodeGen/X86/gcc_except_table.ll index 82064c2a390..92ea539bcf7 100644 --- a/llvm/test/CodeGen/X86/gcc_except_table.ll +++ b/llvm/test/CodeGen/X86/gcc_except_table.ll @@ -18,9 +18,9 @@ define i32 @main() uwtable optsize ssp personality i8* bitcast (i32 (...)* @__gx  ; MINGW64: .seh_setframe 5, 32  ; MINGW64: callq _Unwind_Resume  ; MINGW64: .seh_handlerdata +; MINGW64: .seh_endproc  ; MINGW64: GCC_except_table0:  ; MINGW64: Lexception0: -; MINGW64: .seh_endproc  ; MINGW32: .cfi_startproc  ; MINGW32: .cfi_personality 0, ___gxx_personality_v0 diff --git a/llvm/test/CodeGen/X86/seh-catch-all.ll b/llvm/test/CodeGen/X86/seh-catch-all.ll index 1c1a3c2139d..00a2455655b 100644 --- a/llvm/test/CodeGen/X86/seh-catch-all.ll +++ b/llvm/test/CodeGen/X86/seh-catch-all.ll @@ -38,6 +38,10 @@ eh.resume:  ; CHECK: callq printf  ; CHECK: .seh_handlerdata +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .seh_endproc +; CHECK-NEXT: .section .xdata,"dr"  ; CHECK-NEXT: .long 1  ; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL  ; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL+1 diff --git a/llvm/test/CodeGen/X86/seh-except-finally.ll b/llvm/test/CodeGen/X86/seh-except-finally.ll index 0630d001bb7..5a529cd8d7a 100644 --- a/llvm/test/CodeGen/X86/seh-except-finally.ll +++ b/llvm/test/CodeGen/X86/seh-except-finally.ll @@ -103,6 +103,10 @@ eh.resume:                                        ; preds = %catch.dispatch  ; CHECK: retq  ;  ; CHECK: .seh_handlerdata +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .seh_endproc +; CHECK-NEXT: .section .xdata,"dr"  ; CHECK-NEXT: .long 3  ; CHECK-NEXT: .long .Ltmp0@IMGREL  ; CHECK-NEXT: .long .Ltmp1@IMGREL+1 diff --git a/llvm/test/CodeGen/X86/seh-finally.ll b/llvm/test/CodeGen/X86/seh-finally.ll index 350cd932f48..99f3b658a51 100644 --- a/llvm/test/CodeGen/X86/seh-finally.ll +++ b/llvm/test/CodeGen/X86/seh-finally.ll @@ -38,6 +38,10 @@ terminate.lpad:                                   ; preds = %lpad  ; X64: retq  ; X64: .seh_handlerdata +; X64-NEXT: .text +; X64-NEXT: .Ltmp{{[0-9]+}}: +; X64-NEXT: .seh_endproc +; X64-NEXT: .section .xdata,"dr"  ; X64-NEXT: .long 1  ; X64-NEXT: .long .Ltmp0@IMGREL  ; X64-NEXT: .long .Ltmp1@IMGREL diff --git a/llvm/test/CodeGen/X86/seh-safe-div.ll b/llvm/test/CodeGen/X86/seh-safe-div.ll index 699e58ee8ba..cd0ef717195 100644 --- a/llvm/test/CodeGen/X86/seh-safe-div.ll +++ b/llvm/test/CodeGen/X86/seh-safe-div.ll @@ -90,6 +90,10 @@ __try.cont:  ; CHECK: jmp [[cont_bb]]  ; CHECK: .seh_handlerdata +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .seh_endproc +; CHECK-NEXT: .section .xdata,"dr"  ; CHECK-NEXT: .long 2  ; CHECK-NEXT: .long .Ltmp0@IMGREL  ; CHECK-NEXT: .long .Ltmp1@IMGREL+1 diff --git a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll index c64dcfe058d..6603f4e6d92 100644 --- a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll +++ b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll @@ -71,7 +71,8 @@ catchendblock:                                    ; preds = %catch,  ; X86: addl $12, %ebp  ; X86: jmp [[contbb]] -; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}} +; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X86: LBB0_[[catch1bb]]: # %catch{{$}}  ; X86: pushl %ebp  ; X86-NOT: pushl  ; X86: addl $12, %ebp @@ -89,7 +90,7 @@ catchendblock:                                    ; preds = %catch,  ; X86:   .long   0  ; X86:   .long   "??_R0H@8"  ; X86:   .long   0 -; X86:   .long   [[catch1bb]] +; X86:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"  ; X64-LABEL: try_catch_catch:  ; X64: pushq %rbp @@ -116,7 +117,8 @@ catchendblock:                                    ; preds = %catch,  ; X64: popq %rbp  ; X64: retq -; X64: [[catch1bb:\.LBB0_[0-9]+]]: # %catch{{$}} +; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X64: LBB0_[[catch1bb]]: # %catch{{$}}  ; X64: movq %rdx, 16(%rsp)  ; X64: pushq %rbp  ; X64: movq %rdx, %rbp @@ -132,5 +134,5 @@ catchendblock:                                    ; preds = %catch,  ; X64:   .long   0  ; X64:   .long   "??_R0H@8"@IMGREL  ; X64:   .long   0 -; X64:   .long   [[catch1bb]]@IMGREL +; X64:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL  ; X64:   .long   56 diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll index 597f0e8ae80..7af13e67975 100644 --- a/llvm/test/CodeGen/X86/win-catchpad.ll +++ b/llvm/test/CodeGen/X86/win-catchpad.ll @@ -78,7 +78,8 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X86: addl $12, %ebp  ; X86: jmp [[contbb]] -; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}} +; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X86: LBB0_[[catch1bb]]: # %catch{{$}}  ; X86: pushl %ebp  ; X86: addl $12, %ebp  ; X86: subl $8, %esp @@ -93,7 +94,8 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X86-NEXT: movl $[[restorebb]], %eax  ; X86-NEXT: retl -; X86: [[catch2bb:LBB0_[0-9]+]]: # %catch.2{{$}} +; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X86: LBB0_[[catch2bb]]: # %catch.2{{$}}  ; X86: pushl %ebp  ; X86: addl $12, %ebp  ; X86: subl $8, %esp @@ -112,11 +114,11 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X86-NEXT:   .long   0  ; X86-NEXT:   .long   "??_R0H@8"  ; X86-NEXT:   .long   -20 -; X86-NEXT:   .long   [[catch1bb]] +; X86-NEXT:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"  ; X86-NEXT:   .long   64  ; X86-NEXT:   .long   0  ; X86-NEXT:   .long   0 -; X86-NEXT:   .long   [[catch2bb]] +; X86-NEXT:   .long   "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"  ; X64-LABEL: try_catch_catch:  ; X64: Lfunc_begin0: @@ -135,7 +137,8 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X64: popq %rbp  ; X64: retq -; X64: [[catch1bb:\.LBB0_[0-9]+]]: # %catch{{$}} +; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X64: LBB0_[[catch1bb]]: # %catch{{$}}  ; X64: movq %rdx, 16(%rsp)  ; X64: pushq %rbp  ; X64: movq %rdx, %rbp @@ -149,7 +152,8 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X64-NEXT: leaq [[contbb]](%rip), %rax  ; X64-NEXT: retq -; X64: [[catch2bb:\.LBB0_[0-9]+]]: # %catch.2{{$}} +; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": +; X64: LBB0_[[catch2bb]]: # %catch.2{{$}}  ; X64: movq %rdx, 16(%rsp)  ; X64: pushq %rbp  ; X64: movq %rdx, %rbp @@ -187,12 +191,12 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c  ; X64-NEXT:   .long   "??_R0H@8"@IMGREL  ; FIXME: This should probably be offset from rsp, not rbp.  ; X64-NEXT:   .long   [[e_addr]] -; X64-NEXT:   .long   [[catch1bb]]@IMGREL +; X64-NEXT:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL  ; X64-NEXT:   .long   56  ; X64-NEXT:   .long   64  ; X64-NEXT:   .long   0  ; X64-NEXT:   .long   0 -; X64-NEXT:   .long   [[catch2bb]]@IMGREL +; X64-NEXT:   .long   "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"@IMGREL  ; X64-NEXT:   .long   56  ; X64: $ip2state$try_catch_catch: diff --git a/llvm/test/CodeGen/X86/win-cleanuppad.ll b/llvm/test/CodeGen/X86/win-cleanuppad.ll index a08fd976fa9..02ead25603f 100644 --- a/llvm/test/CodeGen/X86/win-cleanuppad.ll +++ b/llvm/test/CodeGen/X86/win-cleanuppad.ll @@ -65,14 +65,16 @@ cleanup.outer:                                      ; preds = %invoke.cont.1, %c  ; X86: movl    $3, (%esp)  ; X86: calll   _f -; X86: LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner +; X86: "?dtor$[[cleanup_inner:[0-9]+]]@?0?nested_cleanup@4HA": +; X86: LBB1_[[cleanup_inner]]: # %cleanup.inner{{$}}  ; X86: pushl %ebp  ; X86: leal    {{.*}}(%ebp), %ecx  ; X86: calll   "??1Dtor@@QAE@XZ"  ; X86: popl %ebp  ; X86: retl -; X86: LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer +; X86: "?dtor$[[cleanup_outer:[0-9]+]]@?0?nested_cleanup@4HA": +; X86: LBB1_[[cleanup_outer]]: # %cleanup.outer{{$}}  ; X86: pushl %ebp  ; X86: leal    {{.*}}(%ebp), %ecx  ; X86: calll   "??1Dtor@@QAE@XZ" @@ -91,41 +93,46 @@ cleanup.outer:                                      ; preds = %invoke.cont.1, %c  ; X86:         .long   1  ; X86: $stateUnwindMap$nested_cleanup:  ; X86:         .long   -1 -; X86:         .long   LBB1_[[cleanup_outer]] +; X86:         .long   "?dtor$[[cleanup_outer]]@?0?nested_cleanup@4HA"  ; X86:         .long   0 -; X86:         .long   LBB1_[[cleanup_inner]] +; X86:         .long   "?dtor$[[cleanup_inner]]@?0?nested_cleanup@4HA"  ; X64-LABEL: nested_cleanup:  ; X64: .Lfunc_begin1: -; X64: .Ltmp8: +; X64: .Ltmp14:  ; X64: movl    $1, %ecx  ; X64: callq   f -; X64: .Ltmp10: +; X64: .Ltmp16:  ; X64: movl    $2, %ecx  ; X64: callq   f -; X64: .Ltmp11: +; X64: .Ltmp17:  ; X64: callq   "??1Dtor@@QAE@XZ" -; X64: .Ltmp12: +; X64: .Ltmp18:  ; X64: movl    $3, %ecx  ; X64: callq   f -; X64: .Ltmp13: +; X64: .Ltmp19: -; X64: .LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner +; X64: "?dtor$[[cleanup_inner:[0-9]+]]@?0?nested_cleanup@4HA": +; X64: LBB1_[[cleanup_inner]]: # %cleanup.inner{{$}}  ; X64: pushq %rbp  ; X64: leaq    {{.*}}(%rbp), %rcx  ; X64: callq   "??1Dtor@@QAE@XZ"  ; X64: popq %rbp  ; X64: retq -; X64: .LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer +; X64:        .seh_handlerdata +; X64:        .text +; X64:        .seh_endproc + +; X64: "?dtor$[[cleanup_outer:[0-9]+]]@?0?nested_cleanup@4HA": +; X64: LBB1_[[cleanup_outer]]: # %cleanup.outer{{$}}  ; X64: pushq %rbp  ; X64: leaq    {{.*}}(%rbp), %rcx  ; X64: callq   "??1Dtor@@QAE@XZ"  ; X64: popq %rbp  ; X64: retq -; X64: .seh_handlerdata -; X64-NEXT: .long   ($cppxdata$nested_cleanup)@IMGREL +; X64:        .section .xdata,"dr"  ; X64-NEXT: .align  4  ; X64: $cppxdata$nested_cleanup:  ; X64-NEXT: .long   429065506 @@ -141,20 +148,20 @@ cleanup.outer:                                      ; preds = %invoke.cont.1, %c  ; X64: $stateUnwindMap$nested_cleanup:  ; X64-NEXT: .long   -1 -; X64-NEXT: .long   .LBB1_[[cleanup_outer]]@IMGREL +; X64-NEXT: .long   "?dtor$[[cleanup_outer]]@?0?nested_cleanup@4HA"@IMGREL  ; X64-NEXT: .long   0 -; X64-NEXT: .long   .LBB1_[[cleanup_inner]]@IMGREL +; X64-NEXT: .long   "?dtor$[[cleanup_inner]]@?0?nested_cleanup@4HA"@IMGREL  ; X64: $ip2state$nested_cleanup:  ; X64-NEXT: .long   .Lfunc_begin1@IMGREL  ; X64-NEXT: .long   -1 -; X64-NEXT: .long   .Ltmp8@IMGREL +; X64-NEXT: .long   .Ltmp14@IMGREL  ; X64-NEXT: .long   0 -; X64-NEXT: .long   .Ltmp10@IMGREL +; X64-NEXT: .long   .Ltmp16@IMGREL  ; X64-NEXT: .long   1 -; X64-NEXT: .long   .Ltmp12@IMGREL +; X64-NEXT: .long   .Ltmp18@IMGREL  ; X64-NEXT: .long   0 -; X64-NEXT: .long   .Ltmp13@IMGREL+1 +; X64-NEXT: .long   .Ltmp19@IMGREL+1  ; X64-NEXT: .long   -1  attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/llvm/test/CodeGen/X86/win-funclet-cfi.ll b/llvm/test/CodeGen/X86/win-funclet-cfi.ll new file mode 100644 index 00000000000..30883791d8e --- /dev/null +++ b/llvm/test/CodeGen/X86/win-funclet-cfi.ll @@ -0,0 +1,100 @@ +; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define void @"\01?f@@YAXXZ"(i1 %B) personality i32 (...)* @__CxxFrameHandler3 { +entry: +  invoke void @g() +          to label %unreachable unwind label %cleanupblock + +cleanupblock: +  %cleanp = cleanuppad [] +  call void @g() +  cleanupret %cleanp unwind label %catch.dispatch + +catch.dispatch: +  %cp = catchpad [i8* null, i32 64, i8* null] +          to label %catch unwind label %catchendblock + +catch: +  call void @g() +  catchret %cp to label %try.cont + +try.cont: +  ret void + +catchendblock: +  catchendpad unwind to caller + +unreachable: +  unreachable +} + + +declare void @g() + +declare i32 @__CxxFrameHandler3(...) + +; Destructors need CFI but they shouldn't use the .seh_handler directive. +; CHECK: "?dtor$[[cleanup:[0-9]+]]@?0??f@@YAXXZ@4HA": +; CHECK: .seh_proc "?dtor$[[cleanup]]@?0??f@@YAXXZ@4HA" +; CHECK-NOT: .seh_handler __CxxFrameHandler3 +; CHECK: LBB0_[[cleanup]]: # %cleanupblock{{$}} + +; Emit CFI for pushing RBP. +; CHECK: movq    %rdx, 16(%rsp) +; CHECK: pushq   %rbp +; CHECK: .seh_pushreg 5 + +; Emit CFI for allocating from the stack pointer. +; CHECK: subq    $32, %rsp +; CHECK: .seh_stackalloc 32 + +; FIXME: This looks wrong... +; CHECK: leaq    32(%rsp), %rbp +; CHECK: .seh_setframe 5, 32 + +; Prologue is done, emit the .seh_endprologue directive. +; CHECK: .seh_endprologue + +; Make sure there is a nop after a call if the call precedes the epilogue. +; CHECK: callq g +; CHECK-NEXT: nop + +; Don't emit a reference to the LSDA. +; CHECK: .seh_handlerdata +; CHECK-NOT:  .long   ("$cppxdata$?f@@YAXXZ")@IMGREL +; CHECK-NEXT: .text +; CHECK: .seh_endproc + +; CHECK: "?catch$[[catch:[0-9]+]]@?0??f@@YAXXZ@4HA": +; CHECK: .seh_proc "?catch$[[catch]]@?0??f@@YAXXZ@4HA" +; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except +; CHECK: LBB0_[[catch]]: # %catch{{$}} + +; Emit CFI for pushing RBP. +; CHECK: movq    %rdx, 16(%rsp) +; CHECK: pushq   %rbp +; CHECK: .seh_pushreg 5 + +; Emit CFI for allocating from the stack pointer. +; CHECK: subq    $32, %rsp +; CHECK: .seh_stackalloc 32 + +; FIXME: This looks wrong... +; CHECK: leaq    32(%rsp), %rbp +; CHECK: .seh_setframe 5, 32 + +; Prologue is done, emit the .seh_endprologue directive. +; CHECK: .seh_endprologue + +; Make sure there is a nop after a call if the call precedes the epilogue. +; CHECK: callq g +; CHECK-NEXT: nop + +; Emit a reference to the LSDA. +; CHECK: .seh_handlerdata +; CHECK-NEXT:  .long   ("$cppxdata$?f@@YAXXZ")@IMGREL +; CHECK-NEXT: .text +; CHECK: .seh_endproc  | 

