[WinEH] Create an llvm.x86.seh.exceptioninfo intrinsic
[oota-llvm.git] / lib / CodeGen / AsmPrinter / WinException.cpp
index 7e3a6d5a76fd2733d2714f79af5422a4fd08019b..75287fd985579115b1122f0c31445bab24d823cb 100644 (file)
@@ -50,6 +50,11 @@ WinException::~WinException() {}
 /// endModule - Emit all exception information that should come after the
 /// content.
 void WinException::endModule() {
+  auto &OS = *Asm->OutStreamer;
+  const Module *M = MMI->getModule();
+  for (const Function &F : *M)
+    if (F.hasFnAttribute("safeseh"))
+      OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
 }
 
 void WinException::beginFunction(const MachineFunction *MF) {
@@ -444,7 +449,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
               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
         }
       }
@@ -546,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) {
-  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();
+  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
+  assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
+         "no EH reg node frameescape index");
   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);
 
@@ -607,12 +627,10 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
            "gaps in the SEH scope table");
     for (const SEHHandler &Handler : LPInfo->SEHHandlers) {
       // Emit the filter or finally function pointer, if present. Otherwise,
-      // emit '1' to indicate a catch-all.
-      const MCExpr *FilterOrFinally;
-      if (const Function *F = Handler.FilterOrFinally)
-        FilterOrFinally = create32bitRef(Asm->getSymbol(F));
-      else
-        FilterOrFinally = MCConstantExpr::create(1, Asm->OutContext);
+      // emit '0' to indicate a catch-all.
+      const Function *F = Handler.FilterOrFinally;
+      const MCExpr *FilterOrFinally =
+          create32bitRef(F ? Asm->getSymbol(F) : nullptr);
 
       // Compute the recovery address, which is a block address or null.
       const BlockAddress *BA = Handler.RecoverBA;