Classify functions by EH personality type rather than using the triple
authorReid Kleckner <reid@kleckner.net>
Fri, 23 Jan 2015 18:49:01 +0000 (18:49 +0000)
committerReid Kleckner <reid@kleckner.net>
Fri, 23 Jan 2015 18:49:01 +0000 (18:49 +0000)
This mostly reverts commit r222062 and replaces it with a new enum. At
some point this enum will grow at least for other MSVC EH personalities.

Also beefs up the way we were sniffing the personality function.
Previously we would emit the Itanium LSDA despite using
__C_specific_handler.

Reviewers: majnemer

Differential Revision: http://reviews.llvm.org/D6987

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226920 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineModuleInfo.h
include/llvm/MC/MCAsmInfo.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
lib/CodeGen/AsmPrinter/EHStreamer.cpp
lib/CodeGen/AsmPrinter/Win64Exception.cpp
lib/CodeGen/MachineModuleInfo.cpp
lib/CodeGen/Passes.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
test/CodeGen/X86/seh-finally.ll [new file with mode: 0755]

index f0d0b2dbcdbc972f51811bdf9e5fe45b0a0550f0..a6fe01b8ce8689b9b08492c005ea7ead867c9325 100644 (file)
 
 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 @@ class MachineModuleInfo : public ImmutablePass {
   /// details.
   bool UsesMorestackAddr;
 
+  EHPersonality PersonalityTypeCache;
+
+  EHPersonality getPersonalityTypeSlow();
+
 public:
   static char ID; // Pass identification, replacement for typeid
 
@@ -413,6 +424,13 @@ public:
   /// 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 a750a0fd5cefd7ac122e97af07b7e0acd692dd49..ee245e94ac9f32b4bcc354f99e7eea7db0d37838 100644 (file)
@@ -42,12 +42,11 @@ enum class EncodingType {
 }
 
 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 @@ public:
   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 a57807f8ee943198fad6332228e554ed90158795..8206d088b99dc99e58e6572bc5ad54ccd050e31f 100644 (file)
@@ -254,8 +254,7 @@ bool AsmPrinter::doInitialization(Module &M) {
   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 0bbe1ab1e5cdfadcd0028c08bc7a84b318a31bf7..f45b24c17f7cb99e46b4a28270c74928a01e28cd 100644 (file)
@@ -51,7 +51,8 @@ void DwarfCFIException::endModule() {
   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 1bc86f6c222a914893da634fb1b421bcae943037..4841814afff954b64c4e242831f84374d2c56cb0 100644 (file)
@@ -253,7 +253,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
       // 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 73278c835bc9f6f4d821255dafd5b96f2199164a..a1719a51889034be02266568bc867a2df3a75ddc 100644 (file)
@@ -105,8 +105,8 @@ void Win64Exception::endFunction(const MachineFunction *) {
 
     // 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 b5a31925e6b252024fd7961baa3c56eb0286aa51..b4ce673659f79cb2541406e777392642d7ed6de4 100644 (file)
@@ -276,6 +276,7 @@ bool MachineModuleInfo::doInitialization(Module &M) {
   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 @@ try_next:;
 
 /// 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 88cee03fa161866fb658201476d471dc39f14a1a..0797f2335c29f3fa3b97155c12bf4bacada8cc64 100644 (file)
@@ -447,8 +447,7 @@ void TargetPassConfig::addPassesToHandleExceptions() {
     // 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 d37de980e067f3d0b70dbbcf45ec58fd9fc82976..c56973a44fa3f23a6cf8cbd43eb45e6c46ba6ef7 100644 (file)
@@ -924,8 +924,13 @@ void SelectionDAGISel::PrepareEHLandingPad() {
   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();
@@ -937,8 +942,6 @@ void SelectionDAGISel::PrepareEHLandingPad() {
 
     // 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 5795514beec9a807f5cbcc0bfa05cc88de9a3289..e64b9635ba011a8dd277df33da8797bceec8edac 100644 (file)
@@ -132,9 +132,7 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
     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 @@ X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {
     PrivateLabelPrefix = ".L";
     PointerSize = 8;
     WinEHEncodingType = WinEH::EncodingType::Itanium;
-    ExceptionsType = ExceptionHandling::ItaniumWinEH;
+    ExceptionsType = ExceptionHandling::WinEH;
   } else {
     ExceptionsType = ExceptionHandling::DwarfCFI;
   }
diff --git a/test/CodeGen/X86/seh-finally.ll b/test/CodeGen/X86/seh-finally.ll
new file mode 100755 (executable)
index 0000000..d883663
--- /dev/null
@@ -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()