[llvm] r237852 - [WinEH] Store pointers to the LSDA in the exception registration object

Reid Kleckner reid at kleckner.net
Wed May 20 16:08:05 PDT 2015


Author: rnk
Date: Wed May 20 18:08:04 2015
New Revision: 237852

URL: http://llvm.org/viewvc/llvm-project?rev=237852&view=rev
Log:
[WinEH] Store pointers to the LSDA in the exception registration object

We aren't yet emitting the LSDA yet, so this will still fail to
assemble.

Modified:
    llvm/trunk/include/llvm/IR/IntrinsicsX86.td
    llvm/trunk/include/llvm/MC/MCContext.h
    llvm/trunk/lib/MC/MCContext.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86WinEHState.cpp
    llvm/trunk/test/CodeGen/X86/win32-eh.ll

Modified: llvm/trunk/include/llvm/IR/IntrinsicsX86.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicsX86.td?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IntrinsicsX86.td (original)
+++ llvm/trunk/include/llvm/IR/IntrinsicsX86.td Wed May 20 18:08:04 2015
@@ -18,6 +18,12 @@ let TargetPrefix = "x86" in {  // All in
 }
 
 //===----------------------------------------------------------------------===//
+// SEH LSDA for Windows
+let TargetPrefix = "x86" in {
+  def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>;
+}
+
+//===----------------------------------------------------------------------===//
 // Read Time Stamp Counter.
 let TargetPrefix = "x86" in {
   def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">,

Modified: llvm/trunk/include/llvm/MC/MCContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCContext.h (original)
+++ llvm/trunk/include/llvm/MC/MCContext.h Wed May 20 18:08:04 2015
@@ -275,6 +275,8 @@ namespace llvm {
 
     MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName);
 
+    MCSymbol *getOrCreateLSDASymbol(StringRef FuncName);
+
     /// Get the symbol for \p Name, or null.
     MCSymbol *lookupSymbol(const Twine &Name) const;
 

Modified: llvm/trunk/lib/MC/MCContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCContext.cpp (original)
+++ llvm/trunk/lib/MC/MCContext.cpp Wed May 20 18:08:04 2015
@@ -144,6 +144,11 @@ MCSymbol *MCContext::getOrCreateParentFr
                            "$parent_frame_offset");
 }
 
+MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) {
+  return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + "__ehtable$" +
+                           FuncName);
+}
+
 MCSymbol *MCContext::CreateSymbol(StringRef Name, bool AlwaysAddSuffix) {
   // Determine whether this is an assembler temporary or normal label, if used.
   bool IsTemporary = false;

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed May 20 18:08:04 2015
@@ -15288,6 +15288,24 @@ static SDValue LowerINTRINSIC_WO_CHAIN(S
     SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32);
     return DAG.getNode(Opcode, dl, VTs, NewOps);
   }
+
+  case Intrinsic::x86_seh_lsda: {
+    // Compute the symbol for the LSDA. We know it'll get emitted later.
+    MachineFunction &MF = DAG.getMachineFunction();
+    SDValue Op1 = Op.getOperand(1);
+    Op1->dump();
+    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);
+  }
   }
 }
 

Modified: llvm/trunk/lib/Target/X86/X86WinEHState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinEHState.cpp?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86WinEHState.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86WinEHState.cpp Wed May 20 18:08:04 2015
@@ -63,6 +63,10 @@ private:
                                  Value *Handler);
   void unlinkExceptionRegistration(IRBuilder<> &Builder, Value *RegNode);
 
+  Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
+
+  Function *generateLSDAInEAXThunk(Function *ParentFunc);
+
   // Module-level type getters.
   Type *getEHRegistrationType();
   Type *getSEH3RegistrationType();
@@ -108,6 +112,13 @@ void WinEHStatePass::getAnalysisUsage(An
 }
 
 bool WinEHStatePass::runOnFunction(Function &F) {
+  // If this is an outlined handler, don't do anything. We'll do state insertion
+  // for it in the parent.
+  StringRef WinEHParentName =
+      F.getFnAttribute("wineh-parent").getValueAsString();
+  if (WinEHParentName != F.getName() && !WinEHParentName.empty())
+    return false;
+
   // Check the personality. Do nothing if this is not an MSVC personality.
   LandingPadInst *LP = nullptr;
   for (BasicBlock &BB : F) {
@@ -135,9 +146,11 @@ bool WinEHStatePass::runOnFunction(Funct
 }
 
 /// Get the common EH registration subobject:
+///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
+///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
 ///   struct EHRegistrationNode {
 ///     EHRegistrationNode *Next;
-///     EXCEPTION_DISPOSITION (*Handler)(...);
+///     PEXCEPTION_ROUTINE Handler;
 ///   };
 Type *WinEHStatePass::getEHRegistrationType() {
   if (EHRegistrationTy)
@@ -237,20 +250,19 @@ void WinEHStatePass::emitExceptionRegist
     // 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.
+    // Handler = __ehhandler$F
+    Function *Trampoline = generateLSDAInEAXThunk(F);
     SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
-    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
+    linkExceptionRegistration(Builder, SubRecord, Trampoline);
   } 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));
+    // ScopeTable = llvm.x86.seh.lsda(F)
+    Value *LSDA = emitEHLSDA(Builder, F);
+    Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
     SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 0);
     linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
   } else if (PersonalityName == "_except_handler4") {
@@ -263,11 +275,12 @@ void WinEHStatePass::emitExceptionRegist
     // 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));
+    // FIXME: XOR the LSDA with __security_cookie.
+    // ScopeTable = llvm.x86.seh.lsda(F)
+    Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
+    Value *LSDA = Builder.CreateCall(
+        Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
+    Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
     SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
     linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
   } else {
@@ -284,6 +297,50 @@ void WinEHStatePass::emitExceptionRegist
   }
 }
 
+Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
+  Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext()));
+  return Builder.CreateCall(
+      Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
+}
+
+/// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
+/// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
+///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
+///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
+/// We essentially want this code:
+///   movl $lsda, %eax
+///   jmpl ___CxxFrameHandler3
+Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
+  LLVMContext &Context = ParentFunc->getContext();
+  Type *Int32Ty = Type::getInt32Ty(Context);
+  Type *Int8PtrType = Type::getInt8PtrTy(Context);
+  Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
+                     Int8PtrType};
+  FunctionType *TrampolineTy =
+      FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4),
+                        /*isVarArg=*/false);
+  FunctionType *TargetFuncTy =
+      FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
+                        /*isVarArg=*/false);
+  Function *Trampoline = Function::Create(
+      TrampolineTy, GlobalValue::InternalLinkage,
+      Twine("__ehhandler$") + ParentFunc->getName(), TheModule);
+  BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
+  IRBuilder<> Builder(EntryBB);
+  Value *LSDA = emitEHLSDA(Builder, ParentFunc);
+  Value *CastPersonality =
+      Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo());
+  auto AI = Trampoline->arg_begin();
+  Value *Args[5] = {LSDA, AI++, AI++, AI++, AI++};
+  CallInst *Call = Builder.CreateCall(CastPersonality, Args);
+  // Can't use musttail due to prototype mismatch, but we can use tail.
+  Call->setTailCall(true);
+  // Set inreg so we pass it in EAX.
+  Call->addAttribute(1, Attribute::InReg);
+  Builder.CreateRet(Call);
+  return Trampoline;
+}
+
 void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
                                                Value *RegNode, Value *Handler) {
   Type *RegNodeTy = getEHRegistrationType();

Modified: llvm/trunk/test/CodeGen/X86/win32-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-eh.ll?rev=237852&r1=237851&r2=237852&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-eh.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-eh.ll Wed May 20 18:08:04 2015
@@ -20,6 +20,9 @@ catchall:
 
 ; CHECK-LABEL: _use_except_handler3:
 ; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: movl $-1, 12(%esp)
+; CHECK: movl $L__ehtable$use_except_handler3, 8(%esp)
+; CHECK: movl $__except_handler3, 4(%esp)
 ; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], (%esp)
 ; CHECK: leal (%esp), %[[node:[^ ,]*]]
@@ -42,7 +45,11 @@ catchall:
 
 ; CHECK-LABEL: _use_except_handler4:
 ; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: movl %esp, (%esp)
+; CHECK: movl $-2, 20(%esp)
+; CHECK: movl $L__ehtable$use_except_handler4, 4(%esp)
 ; CHECK: leal 8(%esp), %[[node:[^ ,]*]]
+; CHECK: movl $__except_handler4, 12(%esp)
 ; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], 8(%esp)
 ; CHECK: movl %[[node]], %fs:0
@@ -67,7 +74,10 @@ catchall:
 
 ; CHECK-LABEL: _use_CxxFrameHandler3:
 ; CHECK: subl ${{[0-9]+}}, %esp
+; CHECK: movl %esp, (%esp)
+; CHECK: movl $-1, 12(%esp)
 ; CHECK: leal 4(%esp), %[[node:[^ ,]*]]
+; CHECK: movl $___ehhandler$use_CxxFrameHandler3, 8(%esp)
 ; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], 4(%esp)
 ; CHECK: movl %[[node]], %fs:0
@@ -75,3 +85,7 @@ catchall:
 ; CHECK: movl 4(%esp), %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], %fs:0
 ; CHECK: retl
+
+; CHECK-LABEL: ___ehhandler$use_CxxFrameHandler3:
+; CHECK: movl $L__ehtable$use_CxxFrameHandler3, %eax
+; CHECK: jmp  ___CxxFrameHandler3 # TAILCALL





More information about the llvm-commits mailing list