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;
/// details.
bool UsesMorestackAddr;
+ EHPersonality PersonalityTypeCache;
+
+ EHPersonality getPersonalityTypeSlow();
+
public:
static char ID; // Pass identification, replacement for typeid
/// 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,
}
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 {
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 {
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:
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();
// 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;
// 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();
DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
// Always emit some info, by default "no personality" info.
Personalities.push_back(nullptr);
+ PersonalityTypeCache = EHPersonality::None;
AddrLabelSymbols = nullptr;
TheModule = nullptr;
/// 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
// 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:
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<Function>(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();
// 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);
PrivateLabelPrefix = ".L";
PointerSize = 8;
WinEHEncodingType = WinEH::EncodingType::Itanium;
-
- // Use MSVC-compatible EH data.
- ExceptionsType = ExceptionHandling::MSVC;
+ ExceptionsType = ExceptionHandling::WinEH;
}
AssemblerDialect = AsmWriterFlavor;
PrivateLabelPrefix = ".L";
PointerSize = 8;
WinEHEncodingType = WinEH::EncodingType::Itanium;
- ExceptionsType = ExceptionHandling::ItaniumWinEH;
+ ExceptionsType = ExceptionHandling::WinEH;
} else {
ExceptionsType = ExceptionHandling::DwarfCFI;
}
--- /dev/null
+; 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()