[WinEH] Create an llvm.x86.seh.exceptioninfo intrinsic
authorReid Kleckner <reid@kleckner.net>
Thu, 11 Jun 2015 22:32:23 +0000 (22:32 +0000)
committerReid Kleckner <reid@kleckner.net>
Thu, 11 Jun 2015 22:32:23 +0000 (22:32 +0000)
This intrinsic is like framerecover plus a load. It recovers the EH
registration stack allocation from the parent frame and loads the
exception information field out of it, giving back a pointer to an
EXCEPTION_POINTERS struct. It's designed for clang to use in SEH filter
expressions instead of accessing the EXCEPTION_POINTERS parameter that
is available on x64.

This required a minor change to MC to allow defining a label variable to
another absolute framerecover label variable.

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

include/llvm/CodeGen/WinEHFuncInfo.h
include/llvm/IR/Intrinsics.td
include/llvm/IR/IntrinsicsX86.td
lib/CodeGen/AsmPrinter/WinException.cpp
lib/MC/WinCOFFObjectWriter.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86WinEHState.cpp
test/CodeGen/X86/seh-catch-all-win32.ll [new file with mode: 0644]
test/CodeGen/X86/seh-catch-all.ll
test/CodeGen/X86/seh-safe-div-win32.ll

index 1cff3203f2bbf7416f1b4b4af34c491b6293d56f..291f3905512c549a5a28012b6ffb48ed91a215ab 100644 (file)
@@ -144,14 +144,15 @@ struct WinEHFuncInfo {
   SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
   SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
   SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList;
   SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
   SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
   SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList;
-  int UnwindHelpFrameIdx;
-  int UnwindHelpFrameOffset;
+  int UnwindHelpFrameIdx = INT_MAX;
+  int UnwindHelpFrameOffset = -1;
+  unsigned NumIPToStateFuncsVisited = 0;
 
 
-  unsigned NumIPToStateFuncsVisited;
+  /// frameescape index of the 32-bit EH registration node. Set by
+  /// WinEHStatePass and used indirectly by SEH filter functions of the parent.
+  int EHRegNodeEscapeIndex = INT_MAX;
 
 
-  WinEHFuncInfo()
-      : UnwindHelpFrameIdx(INT_MAX), UnwindHelpFrameOffset(-1),
-        NumIPToStateFuncsVisited(0) {}
+  WinEHFuncInfo() {}
 };
 
 /// Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which
 };
 
 /// Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which
index c4c574103957cf6264cd701d4ad9b1d94ce0743b..152c7fcfcca2d48e7d4d5b9921457ebf85740249 100644 (file)
@@ -429,7 +429,6 @@ def int_eh_endcatch : Intrinsic<[], []>;
 def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
 
 def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
 def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
 
 def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
-def int_eh_exceptioninfo : Intrinsic<[llvm_ptr_ty], [], [IntrReadMem]>;
 
 // __builtin_unwind_init is an undocumented GCC intrinsic that causes all
 // callee-saved registers to be saved and restored (regardless of whether they
 
 // __builtin_unwind_init is an undocumented GCC intrinsic that causes all
 // callee-saved registers to be saved and restored (regardless of whether they
index 0826aa2287e9c4ee9b1428fda72a564b9fd26c1b..cb0f53d71b8da534bb9309667850e78746331713 100644 (file)
@@ -18,9 +18,12 @@ let TargetPrefix = "x86" in {  // All intrinsics start with "llvm.x86.".
 }
 
 //===----------------------------------------------------------------------===//
 }
 
 //===----------------------------------------------------------------------===//
-// SEH LSDA for Windows
+// SEH intrinsics for Windows
 let TargetPrefix = "x86" in {
   def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>;
 let TargetPrefix = "x86" in {
   def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>;
+  def int_x86_seh_exceptioninfo : Intrinsic<[llvm_ptr_ty],
+                                            [llvm_ptr_ty, llvm_ptr_ty],
+                                           [IntrReadMem]>;
 }
 
 //===----------------------------------------------------------------------===//
 }
 
 //===----------------------------------------------------------------------===//
index 40d6bab8b6d3806493110bfafd839666bbbe4962..75287fd985579115b1122f0c31445bab24d823cb 100644 (file)
@@ -449,7 +449,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
               Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
                   GlobalValue::getRealLinkageName(HT.Handler->getName()));
           const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
               Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
                   GlobalValue::getRealLinkageName(HT.Handler->getName()));
           const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
-              ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+              ParentFrameOffset, Asm->OutContext);
           OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
         }
       }
           OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
         }
       }
@@ -551,11 +551,26 @@ void WinException::extendIP2StateTable(const MachineFunction *MF,
 /// functionally equivalent to the __C_specific_handler table, except it is
 /// indexed by state number instead of IP.
 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
 /// functionally equivalent to the __C_specific_handler table, except it is
 /// indexed by state number instead of IP.
 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
-  auto &OS = *Asm->OutStreamer;
+  MCStreamer &OS = *Asm->OutStreamer;
 
 
-  // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
+  // Define the EH registration node offset label in terms of its frameescape
+  // label. The WinEHStatePass ensures that the registration node is passed to
+  // frameescape. This allows SEH filter functions to access the
+  // EXCEPTION_POINTERS field, which is filled in by the _except_handlerN.
   const Function *F = MF->getFunction();
   const Function *F = MF->getFunction();
+  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
+  assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
+         "no EH reg node frameescape index");
   StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
   StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
+  MCSymbol *ParentFrameOffset =
+      Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
+  MCSymbol *FrameAllocSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
+      FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
+  const MCSymbolRefExpr *FrameAllocSymRef =
+      MCSymbolRefExpr::create(FrameAllocSym, Asm->OutContext);
+  OS.EmitAssignment(ParentFrameOffset, FrameAllocSymRef);
+
+  // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
   MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
   OS.EmitLabel(LSDALabel);
 
   MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
   OS.EmitLabel(LSDALabel);
 
index 423c7dce45da1eb6297664e08d509ac8a5ac3e37..56ef1c7a2735d2fcf3c979c5b77d163c04cc329f 100644 (file)
@@ -526,13 +526,12 @@ bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol,
   if (!Symbol.isTemporary())
     return true;
 
   if (!Symbol.isTemporary())
     return true;
 
-  // Absolute temporary labels are never visible.
-  if (!Symbol.isInSection())
+  // Temporary variable symbols are invisible.
+  if (Symbol.isVariable())
     return false;
 
     return false;
 
-  // For now, all non-variable symbols are exported,
-  // the linker will sort the rest out for us.
-  return !Symbol.isVariable();
+  // Absolute temporary labels are never visible.
+  return !Symbol.isAbsolute();
 }
 
 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
 }
 
 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
index 8e663097d71d8ce8c2a63ee34418e15c8d149921..a4c7d1620fc3de3d7e8eaf5c2342c4b1b5e226a9 100644 (file)
@@ -15506,23 +15506,6 @@ static SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, const X86Subtarget *Subtarget
         DAG.getTargetExternalSymbol(Name.data(), VT, X86II::MO_NOPREFIX);
     return DAG.getNode(X86ISD::Wrapper, dl, VT, Result);
   }
         DAG.getTargetExternalSymbol(Name.data(), VT, X86II::MO_NOPREFIX);
     return DAG.getNode(X86ISD::Wrapper, dl, VT, Result);
   }
-
-  case Intrinsic::eh_exceptioninfo: {
-    // Compute the symbol for the LSDA. We know it'll get emitted later.
-    MachineFunction &MF = DAG.getMachineFunction();
-    SDValue Op1 = Op.getOperand(1);
-    auto *Fn = cast<Function>(cast<GlobalAddressSDNode>(Op1)->getGlobal());
-    MCSymbol *LSDASym = MF.getMMI().getContext().getOrCreateLSDASymbol(
-        GlobalValue::getRealLinkageName(Fn->getName()));
-    StringRef Name = LSDASym->getName();
-    assert(Name.data()[Name.size()] == '\0' && "not null terminated");
-
-    // Generate a simple absolute symbol reference. This intrinsic is only
-    // supported on 32-bit Windows, which isn't PIC.
-    SDValue Result =
-        DAG.getTargetExternalSymbol(Name.data(), VT, X86II::MO_NOPREFIX);
-    return DAG.getNode(X86ISD::Wrapper, dl, VT, Result);
-  }
   }
 }
 
   }
 }
 
@@ -15707,14 +15690,49 @@ static SDValue LowerREADCYCLECOUNTER(SDValue Op, const X86Subtarget *Subtarget,
   return DAG.getMergeValues(Results, DL);
 }
 
   return DAG.getMergeValues(Results, DL);
 }
 
+static SDValue LowerEXCEPTIONINFO(SDValue Op, const X86Subtarget *Subtarget,
+                                  SelectionDAG &DAG) {
+  MachineFunction &MF = DAG.getMachineFunction();
+  SDLoc dl(Op);
+  SDValue FnOp = Op.getOperand(2);
+  SDValue FPOp = Op.getOperand(3);
+
+  // Compute the symbol for the parent EH registration. We know it'll get
+  // emitted later.
+  auto *Fn = cast<Function>(cast<GlobalAddressSDNode>(FnOp)->getGlobal());
+  MCSymbol *ParentFrameSym =
+      MF.getMMI().getContext().getOrCreateParentFrameOffsetSymbol(
+          GlobalValue::getRealLinkageName(Fn->getName()));
+  StringRef Name = ParentFrameSym->getName();
+  assert(Name.data()[Name.size()] == '\0' && "not null terminated");
+
+  // Create a TargetExternalSymbol for the label to avoid any target lowering
+  // that would make this PC relative.
+  MVT PtrVT = Op.getSimpleValueType();
+  SDValue OffsetSym = DAG.getTargetExternalSymbol(Name.data(), PtrVT);
+  SDValue OffsetVal =
+      DAG.getNode(ISD::FRAME_ALLOC_RECOVER, dl, PtrVT, OffsetSym);
+
+  // Add the offset to the FP.
+  SDValue Add = DAG.getNode(ISD::ADD, dl, PtrVT, FPOp, OffsetVal);
+
+  // Load the second field of the struct, which is 4 bytes in. See
+  // WinEHStatePass for more info.
+  Add = DAG.getNode(ISD::ADD, dl, PtrVT, Add, DAG.getConstant(4, dl, PtrVT));
+  return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Add, MachinePointerInfo(),
+                     false, false, false, 0);
+}
 
 static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget,
                                       SelectionDAG &DAG) {
   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
 
   const IntrinsicData* IntrData = getIntrinsicWithChain(IntNo);
 
 static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget,
                                       SelectionDAG &DAG) {
   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
 
   const IntrinsicData* IntrData = getIntrinsicWithChain(IntNo);
-  if (!IntrData)
+  if (!IntrData) {
+    if (IntNo == Intrinsic::x86_seh_exceptioninfo)
+      return LowerEXCEPTIONINFO(Op, Subtarget, DAG);
     return SDValue();
     return SDValue();
+  }
 
   SDLoc dl(Op);
   switch(IntrData->Type) {
 
   SDLoc dl(Op);
   switch(IntrData->Type) {
index afad3f930daf3cdcfb9307b9a2d59a0cd26e6538..e037f08790c3daedf0b6a98ab0687bf49b0adfd8 100644 (file)
@@ -67,8 +67,6 @@ private:
   void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
                                   Function &F, int BaseState);
   void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
   void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
                                   Function &F, int BaseState);
   void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
-  iplist<Instruction>::iterator
-  rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin);
 
   Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
 
 
   Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
 
@@ -487,6 +485,12 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
 void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
   WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
 
 void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
   WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
 
+  // Remember and return the index that we used. We save it in WinEHFuncInfo so
+  // that we can lower llvm.x86.seh.exceptioninfo later in filter functions
+  // without too much trouble.
+  int RegNodeEscapeIndex = escapeRegNode(F);
+  FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex;
+
   // Iterate all the instructions and emit state number stores.
   int CurState = 0;
   SmallPtrSet<BasicBlock *, 4> ExceptBlocks;
   // Iterate all the instructions and emit state number stores.
   int CurState = 0;
   SmallPtrSet<BasicBlock *, 4> ExceptBlocks;
@@ -495,7 +499,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
       if (auto *CI = dyn_cast<CallInst>(I)) {
         auto *Intrin = dyn_cast<IntrinsicInst>(CI);
         if (Intrin) {
       if (auto *CI = dyn_cast<CallInst>(I)) {
         auto *Intrin = dyn_cast<IntrinsicInst>(CI);
         if (Intrin) {
-          I = rewriteExceptionInfoIntrinsics(Intrin);
           // Calls that "don't throw" are considered to be able to throw asynch
           // exceptions, but intrinsics cannot.
           continue;
           // Calls that "don't throw" are considered to be able to throw asynch
           // exceptions, but intrinsics cannot.
           continue;
@@ -542,32 +545,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
   }
 }
 
   }
 }
 
-/// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in
-/// IR.
-iplist<Instruction>::iterator
-WinEHStatePass::rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin) {
-  Intrinsic::ID ID = Intrin->getIntrinsicID();
-  if (ID != Intrinsic::eh_exceptioncode && ID != Intrinsic::eh_exceptioninfo)
-    return Intrin;
-
-  // RegNode->ExceptionPointers
-  IRBuilder<> Builder(Intrin);
-  Value *Ptrs =
-      Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
-  Value *Res;
-  if (ID == Intrinsic::eh_exceptioncode) {
-    // Ptrs->ExceptionRecord->Code
-    Ptrs = Builder.CreateBitCast(
-        Ptrs, Builder.getInt32Ty()->getPointerTo()->getPointerTo());
-    Value *Rec = Builder.CreateLoad(Ptrs);
-    Res = Builder.CreateLoad(Rec);
-  } else {
-    Res = Ptrs;
-  }
-  Intrin->replaceAllUsesWith(Res);
-  return Intrin->eraseFromParent();
-}
-
 void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode,
                                             Instruction *IP, int State) {
   IRBuilder<> Builder(IP);
 void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode,
                                             Instruction *IP, int State) {
   IRBuilder<> Builder(IP);
diff --git a/test/CodeGen/X86/seh-catch-all-win32.ll b/test/CodeGen/X86/seh-catch-all-win32.ll
new file mode 100644 (file)
index 0000000..0c6b7f7
--- /dev/null
@@ -0,0 +1,85 @@
+; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck %s
+
+; 32-bit catch-all has to use a filter function because that's how it saves the
+; exception code.
+
+@str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
+
+declare i32 @_except_handler3(...)
+declare void @crash()
+declare i32 @printf(i8* nocapture readonly, ...) nounwind
+declare i32 @llvm.eh.typeid.for(i8*)
+declare i8* @llvm.frameaddress(i32)
+declare i8* @llvm.framerecover(i8*, i8*, i32)
+declare void @llvm.frameescape(...)
+declare i8* @llvm.x86.seh.exceptioninfo(i8*, i8*)
+
+define i32 @main() {
+entry:
+  %__exceptioncode = alloca i32, align 4
+  call void (...) @llvm.frameescape(i32* %__exceptioncode)
+  invoke void @crash() #5
+          to label %__try.cont unwind label %lpad
+
+lpad:                                             ; preds = %entry
+  %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+          catch i8* bitcast (i32 ()* @"filt$main" to i8*)
+  %1 = extractvalue { i8*, i32 } %0, 1
+  %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
+  %matches = icmp eq i32 %1, %2
+  br i1 %matches, label %__except, label %eh.resume
+
+__except:                                         ; preds = %lpad
+  %3 = load i32, i32* %__exceptioncode, align 4
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %3) #4
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %entry, %__except
+  ret i32 0
+
+eh.resume:                                        ; preds = %lpad
+  resume { i8*, i32 } %0
+}
+
+define internal i32 @"filt$main"() {
+entry:
+  %0 = tail call i8* @llvm.frameaddress(i32 1)
+  %1 = tail call i8* @llvm.framerecover(i8* bitcast (i32 ()* @main to i8*), i8* %0, i32 0)
+  %__exceptioncode = bitcast i8* %1 to i32*
+  %2 = tail call i8* @llvm.x86.seh.exceptioninfo(i8* bitcast (i32 ()* @main to i8*), i8* %0)
+  %3 = bitcast i8* %2 to i32**
+  %4 = load i32*, i32** %3, align 4
+  %5 = load i32, i32* %4, align 4
+  store i32 %5, i32* %__exceptioncode, align 4
+  ret i32 1
+}
+
+; Check that we can get the exception code from eax to the printf.
+
+; CHECK-LABEL: _main:
+; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]]
+; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]]
+; CHECK: movl %esp, [[reg_offs]](%ebp)
+; CHECK: movl $L__ehtable$main,
+;      EH state 0
+; CHECK: movl $0, -4(%ebp)
+; CHECK: calll _crash
+; CHECK: retl
+; CHECK: # Block address taken
+;      stackrestore
+; CHECK: movl [[reg_offs]](%ebp), %esp
+;      EH state -1
+; CHECK: movl [[code_offs]](%ebp), %[[code:[a-z]+]]
+; CHECK: movl $-1, -4(%ebp)
+; CHECK-DAG: movl %[[code]], 4(%esp)
+; CHECK-DAG: movl $_str, (%esp)
+; CHECK: calll _printf
+
+; CHECK: .section .xdata,"dr"
+; CHECK: L__ehtable$main
+; CHECK-NEXT: .long -1
+; CHECK-NEXT: .long _filt$main
+; CHECK-NEXT: .long Ltmp{{[0-9]+}}
+
+; CHECK-LABEL: _filt$main:
+; CHECK: movl
index 5586f95dba02dc23c76c63e2365d606d4546c7c8..c40e010535314c5dce40edd667ae5423354c56d2 100644 (file)
@@ -1,6 +1,4 @@
-; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=X64
-; RUN: sed -e 's/__C_specific_handler/_except_handler3/' %s | \
-; RUN:         llc -mtriple=i686-windows-msvc | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
 
 @str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
 
 
 @str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
 
@@ -31,41 +29,17 @@ eh.resume:
 
 ; Check that we can get the exception code from eax to the printf.
 
 
 ; Check that we can get the exception code from eax to the printf.
 
-; X64-LABEL: main:
-; X64: callq crash
-; X64: retq
-; X64: # Block address taken
-; X64: leaq str(%rip), %rcx
-; X64: movl %eax, %edx
-; X64: callq printf
-
-; X64: .seh_handlerdata
-; X64-NEXT: .long 1
-; X64-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
-; X64-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL+1
-; X64-NEXT: .long 1
-; X64-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
-
-; X86-LABEL: _main:
-;      The EH code load should be this offset +4.
-; X86: movl %esp, -24(%ebp)
-; X86: movl $L__ehtable$main,
-;      EH state 0
-; X86: movl $0, -4(%ebp)
-; X86: calll _crash
-; X86: retl
-; X86: # Block address taken
-; X86: movl -20(%ebp), %[[ptrs:[^ ,]*]]
-; X86: movl (%[[ptrs]]), %[[rec:[^ ,]*]]
-; X86: movl (%[[rec]]), %[[code:[^ ,]*]]
-;      EH state -1
-; X86: movl $-1, -4(%ebp)
-; X86-DAG: movl %[[code]], 4(%esp)
-; X86-DAG: movl $_str, (%esp)
-; X86: calll _printf
-
-; X86: .section .xdata,"dr"
-; X86-NEXT: L__ehtable$main
-; X86-NEXT: .long -1
-; X86-NEXT: .long 0
-; X86-NEXT: .long Ltmp{{[0-9]+}}
+; CHECK-LABEL: main:
+; CHECK: callq crash
+; CHECK: retq
+; CHECK: # Block address taken
+; CHECK: leaq str(%rip), %rcx
+; CHECK: movl %eax, %edx
+; CHECK: callq printf
+
+; CHECK: .seh_handlerdata
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL+1
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
index e5cbc587bb257747f42b57ca7d1caaaa207ed2bb..ab58a4b99ca2f7a2fd525d426d97959f3d9fd4e4 100644 (file)
@@ -90,7 +90,7 @@ __try.cont:
 ; CHECK: jmp [[cont_bb]]
 
 ; CHECK: .section .xdata,"dr"
 ; CHECK: jmp [[cont_bb]]
 
 ; CHECK: .section .xdata,"dr"
-; CHECK-NEXT: L__ehtable$safe_div:
+; CHECK: L__ehtable$safe_div:
 ; CHECK-NEXT: .long -1
 ; CHECK-NEXT: .long _safe_div_filt0
 ; CHECK-NEXT: .long [[handler0]]
 ; CHECK-NEXT: .long -1
 ; CHECK-NEXT: .long _safe_div_filt0
 ; CHECK-NEXT: .long [[handler0]]