Index: llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h +++ llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h @@ -46,6 +46,13 @@ namespace llvm { +/// Different personality functions used by a function. +enum class EHPersonality { + None, /// No exception handling + Itanium, /// An Itanium C++ EH personality like __gxx_personality_seh0 + Win64SEH, /// x86_64 SEH, uses __C_specific_handler +}; + //===----------------------------------------------------------------------===// // Forward declarations. class Constant; @@ -169,6 +176,10 @@ /// details. bool UsesMorestackAddr; + EHPersonality PersonalityTypeCache; + + EHPersonality getPersonalityTypeSlow(); + public: static char ID; // Pass identification, replacement for typeid @@ -413,6 +424,13 @@ /// of one is required to emit exception handling info. const Function *getPersonality() const; + /// Classify the personality function amongst known EH styles. + EHPersonality getPersonalityType() { + if (PersonalityTypeCache != EHPersonality::None) + return PersonalityTypeCache; + return getPersonalityTypeSlow(); + } + /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, Index: llvm/trunk/include/llvm/MC/MCAsmInfo.h =================================================================== --- llvm/trunk/include/llvm/MC/MCAsmInfo.h +++ llvm/trunk/include/llvm/MC/MCAsmInfo.h @@ -42,12 +42,11 @@ } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) - MSVC, /// MSVC compatible exception handling + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling }; namespace LCOMM { @@ -490,18 +489,16 @@ ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - /// Return true if the exception handling type uses the language-specific data - /// area (LSDA) format specified by the Itanium C++ ABI. - bool usesItaniumLSDAForExceptions() const { + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || ExceptionsType == ExceptionHandling::ARM || - // This Windows EH type uses the Itanium LSDA encoding. - ExceptionsType == ExceptionHandling::ItaniumWinEH); + ExceptionsType == ExceptionHandling::WinEH); } bool usesWindowsCFI() const { - return ExceptionsType == ExceptionHandling::ItaniumWinEH || - ExceptionsType == ExceptionHandling::MSVC; + return ExceptionsType == ExceptionHandling::WinEH; } bool doesDwarfUseRelocationsAcrossSections() const { Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -254,8 +254,7 @@ case ExceptionHandling::ARM: ES = new ARMException(this); break; - case ExceptionHandling::ItaniumWinEH: - case ExceptionHandling::MSVC: + case ExceptionHandling::WinEH: switch (MAI->getWinEHEncodingType()) { default: llvm_unreachable("unsupported unwinding information encoding"); case WinEH::EncodingType::Itanium: Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -51,7 +51,8 @@ if (moveTypeModule == AsmPrinter::CFI_M_Debug) Asm->OutStreamer.EmitCFISections(false, true); - if (!Asm->MAI->usesItaniumLSDAForExceptions()) + // SjLj uses this pass and it doesn't need this info. + if (!Asm->MAI->usesCFIForEH()) return; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); Index: llvm/trunk/lib/CodeGen/AsmPrinter/EHStreamer.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -253,7 +253,7 @@ // instruction between the previous try-range and this one may throw, // create a call-site entry with no landing pad for the region between the // try-ranges. - if (SawPotentiallyThrowing && !IsSJLJ) { + if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) { CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; Index: llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -105,8 +105,8 @@ // Emit the tables appropriate to the personality function in use. If we // don't recognize the personality, assume it uses an Itanium-style LSDA. - const Function *Per = MMI->getPersonality(); - if (Per && Per->getName() == "__C_specific_handler") + EHPersonality Per = MMI->getPersonalityType(); + if (Per == EHPersonality::Win64SEH) emitCSpecificHandlerTable(); else emitExceptionTable(); Index: llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp +++ llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp @@ -276,6 +276,7 @@ DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; // Always emit some info, by default "no personality" info. Personalities.push_back(nullptr); + PersonalityTypeCache = EHPersonality::None; AddrLabelSymbols = nullptr; TheModule = nullptr; @@ -554,7 +555,21 @@ /// getPersonality - Return the personality function for the current function. const Function *MachineModuleInfo::getPersonality() const { - return !LandingPads.empty() ? LandingPads[0].Personality : nullptr; + for (const LandingPadInfo &LPI : LandingPads) + if (LPI.Personality) + return LPI.Personality; + return nullptr; +} + +EHPersonality MachineModuleInfo::getPersonalityTypeSlow() { + const Function *Per = getPersonality(); + if (!Per) + PersonalityTypeCache = EHPersonality::None; + else if (Per->getName() == "__C_specific_handler") + PersonalityTypeCache = EHPersonality::Win64SEH; + else // Assume everything else is Itanium. + PersonalityTypeCache = EHPersonality::Itanium; + return PersonalityTypeCache; } /// getPersonalityIndex - Return unique index for current personality Index: llvm/trunk/lib/CodeGen/Passes.cpp =================================================================== --- llvm/trunk/lib/CodeGen/Passes.cpp +++ llvm/trunk/lib/CodeGen/Passes.cpp @@ -447,8 +447,7 @@ // FALLTHROUGH case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: - case ExceptionHandling::ItaniumWinEH: - case ExceptionHandling::MSVC: // FIXME: Needs preparation. + case ExceptionHandling::WinEH: addPass(createDwarfEHPass(TM)); break; case ExceptionHandling::None: Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -924,8 +924,13 @@ BuildMI(*MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) .addSym(Label); - if (TM.getMCAsmInfo()->getExceptionHandlingType() == - ExceptionHandling::MSVC) { + // If this is an MSVC-style personality function, we need to split the landing + // pad into several BBs. + const BasicBlock *LLVMBB = MBB->getBasicBlock(); + const LandingPadInst *LPadInst = LLVMBB->getLandingPadInst(); + MF->getMMI().addPersonality( + MBB, cast(LPadInst->getPersonalityFn()->stripPointerCasts())); + if (MF->getMMI().getPersonalityType() == EHPersonality::Win64SEH) { // Make virtual registers and a series of labels that fill in values for the // clauses. auto &RI = MF->getRegInfo(); @@ -937,8 +942,6 @@ // Emit separate machine basic blocks with separate labels for each clause // before the main landing pad block. - const BasicBlock *LLVMBB = MBB->getBasicBlock(); - const LandingPadInst *LPadInst = LLVMBB->getLandingPadInst(); MachineInstrBuilder SelectorPHI = BuildMI( *MBB, MBB->begin(), SDB->getCurDebugLoc(), TII->get(TargetOpcode::PHI), FuncInfo->ExceptionSelectorVirtReg); Index: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp +++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -132,9 +132,7 @@ PrivateLabelPrefix = ".L"; PointerSize = 8; WinEHEncodingType = WinEH::EncodingType::Itanium; - - // Use MSVC-compatible EH data. - ExceptionsType = ExceptionHandling::MSVC; + ExceptionsType = ExceptionHandling::WinEH; } AssemblerDialect = AsmWriterFlavor; @@ -155,7 +153,7 @@ PrivateLabelPrefix = ".L"; PointerSize = 8; WinEHEncodingType = WinEH::EncodingType::Itanium; - ExceptionsType = ExceptionHandling::ItaniumWinEH; + ExceptionsType = ExceptionHandling::WinEH; } else { ExceptionsType = ExceptionHandling::DwarfCFI; } Index: llvm/trunk/test/CodeGen/X86/seh-finally.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/seh-finally.ll +++ llvm/trunk/test/CodeGen/X86/seh-finally.ll @@ -0,0 +1,45 @@ +; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s + +@str_recovered = internal unnamed_addr constant [10 x i8] c"recovered\00", align 1 + +declare void @crash() + +define i32 @main() { +entry: + invoke void @crash() + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + %call = call i32 @puts(i8* getelementptr inbounds ([10 x i8]* @str_recovered, i64 0, i64 0)) + call void @abort() + ret i32 0 + +lpad: ; preds = %entry + %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) + cleanup + %1 = extractvalue { i8*, i32 } %0, 0 + %2 = extractvalue { i8*, i32 } %0, 1 + %call2 = invoke i32 @puts(i8* getelementptr inbounds ([10 x i8]* @str_recovered, i64 0, i64 0)) + to label %invoke.cont1 unwind label %terminate.lpad + +invoke.cont1: ; preds = %lpad + resume { i8*, i32 } %0 + +terminate.lpad: ; preds = %lpad + %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) + catch i8* null + call void @abort() + unreachable +} + +; CHECK: main: + +; FIXME: No handlers yet! +; CHECK: .seh_handlerdata +; CHECK-NEXT: .long 0 + +declare i32 @__C_specific_handler(...) + +declare i32 @puts(i8*) + +declare void @abort()