[llvm] r236339 - [WinEH] Add an EH registration and state insertion pass for 32-bit x86

Reid Kleckner reid at kleckner.net
Fri May 1 13:04:55 PDT 2015


Author: rnk
Date: Fri May  1 15:04:54 2015
New Revision: 236339

URL: http://llvm.org/viewvc/llvm-project?rev=236339&view=rev
Log:
[WinEH] Add an EH registration and state insertion pass for 32-bit x86

This pass is responsible for constructing the EH registration object
that gets linked into fs:00, which is all it does in this change. In the
future, it will also insert stores to update the EH state number.

I considered keeping this functionality in WinEHPrepare, but it's pretty
separable and X86 specific. It has conceptually very little to do with
the task of WinEHPrepare, which is currently outlining.  WinEHPrepare is
also in theory useful on ARM, but this logic is pretty x86 specific.

Reviewers: andrew.w.kaylor, majnemer

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

Added:
    llvm/trunk/lib/Target/X86/X86WinEHState.cpp
    llvm/trunk/test/CodeGen/X86/win32-eh.ll
Modified:
    llvm/trunk/include/llvm/MC/MCAsmInfo.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/lib/Target/X86/CMakeLists.txt
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
    llvm/trunk/lib/Target/X86/X86.h
    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
    llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll

Modified: llvm/trunk/include/llvm/MC/MCAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmInfo.h?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAsmInfo.h (original)
+++ llvm/trunk/include/llvm/MC/MCAsmInfo.h Fri May  1 15:04:54 2015
@@ -37,6 +37,7 @@ enum class EncodingType {
   ARM,     /// Windows NT (Windows on ARM)
   CE,      /// Windows CE ARM, PowerPC, SH3, SH4
   Itanium, /// Windows x64, Windows Itanium (IA-64)
+  X86,     /// Windows x86, uses no CFI, just EH tables
   MIPS = Alpha,
 };
 }
@@ -506,12 +507,13 @@ public:
   /// frame information to unwind.
   bool usesCFIForEH() const {
     return (ExceptionsType == ExceptionHandling::DwarfCFI ||
-            ExceptionsType == ExceptionHandling::ARM ||
-            ExceptionsType == ExceptionHandling::WinEH);
+            ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI());
   }
 
   bool usesWindowsCFI() const {
-    return ExceptionsType == ExceptionHandling::WinEH;
+    return ExceptionsType == ExceptionHandling::WinEH &&
+           (WinEHEncodingType != WinEH::EncodingType::Invalid &&
+            WinEHEncodingType != WinEH::EncodingType::X86);
   }
 
   bool doesDwarfUseRelocationsAcrossSections() const {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Fri May  1 15:04:54 2015
@@ -266,6 +266,8 @@ bool AsmPrinter::doInitialization(Module
   case ExceptionHandling::WinEH:
     switch (MAI->getWinEHEncodingType()) {
     default: llvm_unreachable("unsupported unwinding information encoding");
+    case WinEH::EncodingType::Invalid:
+      break;
     case WinEH::EncodingType::Itanium:
       ES = new Win64Exception(this);
       break;

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Fri May  1 15:04:54 2015
@@ -8,9 +8,11 @@
 //===----------------------------------------------------------------------===//
 //
 // This pass lowers LLVM IR exception handling into something closer to what the
-// backend wants. It snifs the personality function to see which kind of
-// preparation is necessary. If the personality function uses the Itanium LSDA,
-// this pass delegates to the DWARF EH preparation pass.
+// backend wants for functions using a personality function from a runtime
+// provided by MSVC. Functions with other personality functions are left alone
+// and may be prepared by other passes. In particular, all supported MSVC
+// personality functions require cleanup code to be outlined, and the C++
+// personality requires catch handler code to be outlined.
 //
 //===----------------------------------------------------------------------===//
 
@@ -31,7 +33,6 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Pass.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
@@ -922,7 +923,7 @@ bool WinEHPrepare::prepareExceptionHandl
   if (SEHExceptionCodeSlot) {
     if (SEHExceptionCodeSlot->hasNUses(0))
       SEHExceptionCodeSlot->eraseFromParent();
-    else
+    else if (isAllocaPromotable(SEHExceptionCodeSlot))
       PromoteMemToReg(SEHExceptionCodeSlot, *DT);
   }
 

Modified: llvm/trunk/lib/Target/X86/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/CMakeLists.txt?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/X86/CMakeLists.txt Fri May  1 15:04:54 2015
@@ -32,6 +32,7 @@ set(sources
   X86TargetTransformInfo.cpp
   X86VZeroUpper.cpp
   X86FixupLEAs.cpp
+  X86WinEHState.cpp
   )
 
 if( CMAKE_CL_64 )

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp Fri May  1 15:04:54 2015
@@ -132,9 +132,10 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicro
     PrivateLabelPrefix = ".L";
     PointerSize = 8;
     WinEHEncodingType = WinEH::EncodingType::Itanium;
-    ExceptionsType = ExceptionHandling::WinEH;
   }
 
+  ExceptionsType = ExceptionHandling::WinEH;
+
   AssemblerDialect = AsmWriterFlavor;
 
   TextAlignFillValue = 0x90;

Modified: llvm/trunk/lib/Target/X86/X86.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.h?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86.h (original)
+++ llvm/trunk/lib/Target/X86/X86.h Fri May  1 15:04:54 2015
@@ -69,6 +69,12 @@ FunctionPass *createX86FixupLEAs();
 /// esp-relative movs with pushes.
 FunctionPass *createX86CallFrameOptimization();
 
+/// createX86WinEHStatePass - Return an IR pass that inserts EH registration
+/// stack objects and explicit EH state updates. This pass must run after EH
+/// preparation, which does Windows-specific but architecture-neutral
+/// preparation.
+FunctionPass *createX86WinEHStatePass();
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Fri May  1 15:04:54 2015
@@ -185,6 +185,7 @@ public:
   void addIRPasses() override;
   bool addInstSelector() override;
   bool addILPOpts() override;
+  bool addPreISel() override;
   void addPreRegAlloc() override;
   void addPostRegAlloc() override;
   void addPreEmitPass() override;
@@ -220,6 +221,14 @@ bool X86PassConfig::addILPOpts() {
   return true;
 }
 
+bool X86PassConfig::addPreISel() {
+  // Only add this pass for 32-bit x86.
+  Triple TT(TM->getTargetTriple());
+  if (TT.getArch() == Triple::x86)
+    addPass(createX86WinEHStatePass());
+  return true;
+}
+
 void X86PassConfig::addPreRegAlloc() {
   addPass(createX86CallFrameOptimization());
 }

Added: llvm/trunk/lib/Target/X86/X86WinEHState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinEHState.cpp?rev=236339&view=auto
==============================================================================
--- llvm/trunk/lib/Target/X86/X86WinEHState.cpp (added)
+++ llvm/trunk/lib/Target/X86/X86WinEHState.cpp Fri May  1 15:04:54 2015
@@ -0,0 +1,317 @@
+//===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// All functions using an MSVC EH personality use an explicitly updated state
+// number stored in an exception registration stack object. The registration
+// object is linked into a thread-local chain of registrations stored at fs:00.
+// This pass adds the registration object and EH state updates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "llvm/Analysis/LibCallSemantics.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/WinEHFuncInfo.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+using namespace llvm::PatternMatch;
+
+#define DEBUG_TYPE "winehstate"
+
+namespace {
+class WinEHStatePass : public FunctionPass {
+public:
+  static char ID; // Pass identification, replacement for typeid.
+
+  WinEHStatePass() : FunctionPass(ID) {}
+
+  bool runOnFunction(Function &Fn) override;
+
+  bool doInitialization(Module &M) override;
+
+  bool doFinalization(Module &M) override;
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+  const char *getPassName() const override {
+    return "Windows 32-bit x86 EH state insertion";
+  }
+
+private:
+  void emitExceptionRegistrationRecord(Function *F);
+
+  void linkExceptionRegistration(IRBuilder<> &Builder, Value *RegNode,
+                                 Value *Handler);
+  void unlinkExceptionRegistration(IRBuilder<> &Builder, Value *RegNode);
+
+  // Module-level type getters.
+  Type *getEHRegistrationType();
+  Type *getSEH3RegistrationType();
+  Type *getSEH4RegistrationType();
+  Type *getCXXEH3RegistrationType();
+
+  // Per-module data.
+  Module *TheModule = nullptr;
+  StructType *EHRegistrationTy = nullptr;
+  StructType *CXXEH3RegistrationTy = nullptr;
+  StructType *SEH3RegistrationTy = nullptr;
+  StructType *SEH4RegistrationTy = nullptr;
+
+  // Per-function state
+  EHPersonality Personality = EHPersonality::Unknown;
+  Function *PersonalityFn = nullptr;
+};
+}
+
+FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
+
+char WinEHStatePass::ID = 0;
+
+bool WinEHStatePass::doInitialization(Module &M) {
+  TheModule = &M;
+  return false;
+}
+
+bool WinEHStatePass::doFinalization(Module &M) {
+  assert(TheModule == &M);
+  TheModule = nullptr;
+  EHRegistrationTy = nullptr;
+  CXXEH3RegistrationTy = nullptr;
+  SEH3RegistrationTy = nullptr;
+  SEH4RegistrationTy = nullptr;
+  return false;
+}
+
+void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
+  // This pass should only insert a stack allocation, memory accesses, and
+  // framerecovers.
+  AU.setPreservesCFG();
+}
+
+bool WinEHStatePass::runOnFunction(Function &F) {
+  // Check the personality. Do nothing if this is not an MSVC personality.
+  LandingPadInst *LP = nullptr;
+  for (BasicBlock &BB : F) {
+    LP = BB.getLandingPadInst();
+    if (LP)
+      break;
+  }
+  if (!LP)
+    return false;
+  PersonalityFn =
+      dyn_cast<Function>(LP->getPersonalityFn()->stripPointerCasts());
+  if (!PersonalityFn)
+    return false;
+  Personality = classifyEHPersonality(PersonalityFn);
+  if (!isMSVCEHPersonality(Personality))
+    return false;
+
+  emitExceptionRegistrationRecord(&F);
+  // FIXME: State insertion.
+
+  // Reset per-function state.
+  PersonalityFn = nullptr;
+  Personality = EHPersonality::Unknown;
+  return true;
+}
+
+/// Get the common EH registration subobject:
+///   struct EHRegistrationNode {
+///     EHRegistrationNode *Next;
+///     EXCEPTION_DISPOSITION (*Handler)(...);
+///   };
+Type *WinEHStatePass::getEHRegistrationType() {
+  if (EHRegistrationTy)
+    return EHRegistrationTy;
+  LLVMContext &Context = TheModule->getContext();
+  EHRegistrationTy = StructType::create(Context, "EHRegistrationNode");
+  Type *FieldTys[] = {
+      EHRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
+      Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
+  };
+  EHRegistrationTy->setBody(FieldTys, false);
+  return EHRegistrationTy;
+}
+
+/// The __CxxFrameHandler3 registration node:
+///   struct CXXExceptionRegistration {
+///     void *SavedESP;
+///     EHRegistrationNode SubRecord;
+///     int32_t TryLevel;
+///   };
+Type *WinEHStatePass::getCXXEH3RegistrationType() {
+  if (CXXEH3RegistrationTy)
+    return CXXEH3RegistrationTy;
+  LLVMContext &Context = TheModule->getContext();
+  Type *FieldTys[] = {
+      Type::getInt8PtrTy(Context), // void *SavedESP
+      getEHRegistrationType(),     // EHRegistrationNode SubRecord
+      Type::getInt32Ty(Context)    // int32_t TryLevel
+  };
+  CXXEH3RegistrationTy =
+      StructType::create(FieldTys, "CXXExceptionRegistration");
+  return CXXEH3RegistrationTy;
+}
+
+/// The _except_handler3 registration node:
+///   struct EH3ExceptionRegistration {
+///     EHRegistrationNode SubRecord;
+///     void *ScopeTable;
+///     int32_t TryLevel;
+///   };
+Type *WinEHStatePass::getSEH3RegistrationType() {
+  if (SEH3RegistrationTy)
+    return SEH3RegistrationTy;
+  LLVMContext &Context = TheModule->getContext();
+  Type *FieldTys[] = {
+      getEHRegistrationType(),     // EHRegistrationNode SubRecord
+      Type::getInt8PtrTy(Context), // void *ScopeTable
+      Type::getInt32Ty(Context)    // int32_t TryLevel
+  };
+  SEH3RegistrationTy = StructType::create(FieldTys, "EH3ExceptionRegistration");
+  return SEH3RegistrationTy;
+}
+
+/// The _except_handler4 registration node:
+///   struct EH4ExceptionRegistration {
+///     void *SavedESP;
+///     _EXCEPTION_POINTERS *ExceptionPointers;
+///     EHRegistrationNode SubRecord;
+///     int32_t EncodedScopeTable;
+///     int32_t TryLevel;
+///   };
+Type *WinEHStatePass::getSEH4RegistrationType() {
+  if (SEH4RegistrationTy)
+    return SEH4RegistrationTy;
+  LLVMContext &Context = TheModule->getContext();
+  Type *FieldTys[] = {
+      Type::getInt8PtrTy(Context), // void *SavedESP
+      Type::getInt8PtrTy(Context), // void *ExceptionPointers
+      getEHRegistrationType(),     // EHRegistrationNode SubRecord
+      Type::getInt32Ty(Context),   // int32_t EncodedScopeTable
+      Type::getInt32Ty(Context)    // int32_t TryLevel
+  };
+  SEH4RegistrationTy = StructType::create(FieldTys, "EH4ExceptionRegistration");
+  return SEH4RegistrationTy;
+}
+
+// Emit an exception registration record. These are stack allocations with the
+// common subobject of two pointers: the previous registration record (the old
+// fs:00) and the personality function for the current frame. The data before
+// and after that is personality function specific.
+void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
+  assert(Personality == EHPersonality::MSVC_CXX ||
+         Personality == EHPersonality::MSVC_X86SEH);
+
+  StringRef PersonalityName = PersonalityFn->getName();
+  IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
+  Type *Int8PtrType = Builder.getInt8PtrTy();
+  Value *SubRecord = nullptr;
+  if (PersonalityName == "__CxxFrameHandler3") {
+    Type *RegNodeTy = getCXXEH3RegistrationType();
+    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
+    // FIXME: We can skip this in -GS- mode, when we figure that out.
+    // SavedESP = llvm.stacksave()
+    Value *SP = Builder.CreateCall(
+        Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave));
+    Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
+    // TryLevel = -1
+    Builder.CreateStore(Builder.getInt32(-1),
+                        Builder.CreateStructGEP(RegNodeTy, RegNode, 2));
+    // FIXME: 'Personality' is incorrect here. We need to generate a trampoline
+    // that effectively gets the LSDA.
+    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
+    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
+  } else if (PersonalityName == "_except_handler3") {
+    Type *RegNodeTy = getSEH3RegistrationType();
+    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
+    // TryLevel = -1
+    Builder.CreateStore(Builder.getInt32(-1),
+                        Builder.CreateStructGEP(RegNodeTy, RegNode, 2));
+    // FIXME: Generalize llvm.eh.sjljl.lsda for this.
+    // ScopeTable = nullptr
+    Builder.CreateStore(Constant::getNullValue(Int8PtrType),
+                        Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
+    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 0);
+    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
+  } else if (PersonalityName == "_except_handler4") {
+    Type *RegNodeTy = getSEH4RegistrationType();
+    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
+    // SavedESP = llvm.stacksave()
+    Value *SP = Builder.CreateCall(
+        Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave));
+    Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
+    // TryLevel = -2
+    Builder.CreateStore(Builder.getInt32(-2),
+                        Builder.CreateStructGEP(RegNodeTy, RegNode, 4));
+    // FIXME: Generalize llvm.eh.sjljl.lsda for this, and then do the stack
+    // cookie xor.
+    // ScopeTable = nullptr
+    Builder.CreateStore(Builder.getInt32(0),
+                        Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
+    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
+    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
+  } else {
+    llvm_unreachable("unexpected personality function");
+  }
+
+  // FIXME: Insert an unlink before all returns.
+  for (BasicBlock &BB : *F) {
+    TerminatorInst *T = BB.getTerminator();
+    if (!isa<ReturnInst>(T))
+      continue;
+    Builder.SetInsertPoint(T);
+    unlinkExceptionRegistration(Builder, SubRecord);
+  }
+}
+
+void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
+                                               Value *RegNode, Value *Handler) {
+  Type *RegNodeTy = getEHRegistrationType();
+  // Handler = Handler
+  Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
+  Builder.CreateStore(Handler, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
+  // Next = [fs:00]
+  Constant *FSZero =
+      Constant::getNullValue(RegNodeTy->getPointerTo()->getPointerTo(257));
+  Value *Next = Builder.CreateLoad(FSZero);
+  Builder.CreateStore(Next, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
+  // [fs:00] = RegNode
+  Builder.CreateStore(RegNode, FSZero);
+}
+
+void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder,
+                                                 Value *RegNode) {
+  // Clone RegNode into the current BB for better address mode folding.
+  if (auto *GEP = dyn_cast<GetElementPtrInst>(RegNode)) {
+    GEP = cast<GetElementPtrInst>(GEP->clone());
+    Builder.Insert(GEP);
+    RegNode = GEP;
+  }
+  Type *RegNodeTy = getEHRegistrationType();
+  // [fs:00] = RegNode->Next
+  Value *Next =
+      Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
+  Constant *FSZero =
+      Constant::getNullValue(RegNodeTy->getPointerTo()->getPointerTo(257));
+  Builder.CreateStore(Next, FSZero);
+}

Modified: llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll?rev=236339&r1=236338&r2=236339&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll (original)
+++ llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll Fri May  1 15:04:54 2015
@@ -4,6 +4,7 @@
 
 %frame.reverse = type { %Iter, %Iter }
 
+declare i32 @pers(...)
 declare void @llvm.stackrestore(i8*)
 declare i8* @llvm.stacksave()
 declare void @begin(%Iter* sret)
@@ -22,8 +23,7 @@ blah:
 
 ; CHECK:  calll   __chkstk
 ; CHECK:  movl %esp, %[[beg:[^ ]*]]
-; CHECK:  movl %esp, %[[end:[^ ]*]]
-; CHECK:  addl $12, %[[end]]
+; CHECK:  leal 12(%[[beg]]), %[[end:[^ ]*]]
 
   call void @begin(%Iter* sret %temp.lvalue)
 ; CHECK:  calll _begin
@@ -49,7 +49,7 @@ invoke.cont5:
   ret i32 0
 
 lpad:                                             ; preds = %invoke.cont, %entry
-  %lp = landingpad { i8*, i32 } personality i8* null
+  %lp = landingpad { i8*, i32 } personality i32 (...)* @pers
           cleanup
   unreachable
 }

Added: llvm/trunk/test/CodeGen/X86/win32-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-eh.ll?rev=236339&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-eh.ll (added)
+++ llvm/trunk/test/CodeGen/X86/win32-eh.ll Fri May  1 15:04:54 2015
@@ -0,0 +1,77 @@
+; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
+
+declare void @may_throw_or_crash()
+declare i32 @_except_handler3(...)
+declare i32 @_except_handler4(...)
+declare i32 @__CxxFrameHandler3(...)
+declare void @llvm.eh.begincatch(i8*, i8*)
+declare void @llvm.eh.endcatch()
+
+define void @use_except_handler3() {
+  invoke void @may_throw_or_crash()
+      to label %cont unwind label %catchall
+cont:
+  ret void
+catchall:
+  landingpad { i8*, i32 } personality i32 (...)* @_except_handler3
+      catch i8* null
+  br label %cont
+}
+
+; CHECK-LABEL: _use_except_handler3:
+; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: movl %fs:0, %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], (%esp)
+; CHECK: leal (%esp), %[[node:[^ ,]*]]
+; CHECK: movl %[[node]], %fs:0
+; CHECK: calll _may_throw_or_crash
+; CHECK: movl (%esp), %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], %fs:0
+; CHECK: retl
+
+define void @use_except_handler4() {
+  invoke void @may_throw_or_crash()
+      to label %cont unwind label %catchall
+cont:
+  ret void
+catchall:
+  landingpad { i8*, i32 } personality i32 (...)* @_except_handler4
+      catch i8* null
+  br label %cont
+}
+
+; CHECK-LABEL: _use_except_handler4:
+; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: leal 8(%esp), %[[node:[^ ,]*]]
+; CHECK: movl %fs:0, %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], 8(%esp)
+; CHECK: movl %[[node]], %fs:0
+; CHECK: calll _may_throw_or_crash
+; CHECK: movl 8(%esp), %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], %fs:0
+; CHECK: retl
+
+define void @use_CxxFrameHandler3() {
+  invoke void @may_throw_or_crash()
+      to label %cont unwind label %catchall
+cont:
+  ret void
+catchall:
+  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__CxxFrameHandler3
+      catch i8* null
+  %ehptr = extractvalue { i8*, i32 } %ehvals, 0
+  call void @llvm.eh.begincatch(i8* %ehptr, i8* null)
+  call void @llvm.eh.endcatch()
+  br label %cont
+}
+
+; CHECK-LABEL: _use_CxxFrameHandler3:
+; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: leal 4(%esp), %[[node:[^ ,]*]]
+; CHECK: movl %fs:0, %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], 4(%esp)
+; CHECK: movl %[[node]], %fs:0
+; CHECK: calll _may_throw_or_crash
+; CHECK: movl 4(%esp), %[[next:[^ ,]*]]
+; CHECK: movl %[[next]], %fs:0
+; CHECK: retl





More information about the llvm-commits mailing list