Add Windows Control Flow Guard checks (/guard:cf).

Summary:
A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on
indirect function calls, using either the check mechanism (X86, ARM, AArch64) or
or the dispatch mechanism (X86-64). The check mechanism requires a new calling
convention for the supported targets. The dispatch mechanism adds the target as
an operand bundle, which is processed by SelectionDAG. Another pass
(CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as
required by /guard:cf. This feature is enabled using the `cfguard` CC1 option.

Reviewers: thakis, rnk, theraven, pcc

Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D65761
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5292b0e..819f8a0 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -585,6 +585,7 @@
   KEYWORD(ccc);
   KEYWORD(fastcc);
   KEYWORD(coldcc);
+  KEYWORD(cfguard_checkcc);
   KEYWORD(x86_stdcallcc);
   KEYWORD(x86_fastcallcc);
   KEYWORD(x86_thiscallcc);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 664ef8d..41e1d0b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1921,6 +1921,7 @@
 ///   ::= 'fastcc'
 ///   ::= 'intel_ocl_bicc'
 ///   ::= 'coldcc'
+///   ::= 'cfguard_checkcc'
 ///   ::= 'x86_stdcallcc'
 ///   ::= 'x86_fastcallcc'
 ///   ::= 'x86_thiscallcc'
@@ -1965,6 +1966,7 @@
   case lltok::kw_ccc:            CC = CallingConv::C; break;
   case lltok::kw_fastcc:         CC = CallingConv::Fast; break;
   case lltok::kw_coldcc:         CC = CallingConv::Cold; break;
+  case lltok::kw_cfguard_checkcc: CC = CallingConv::CFGuard_Check; break;
   case lltok::kw_x86_stdcallcc:  CC = CallingConv::X86_StdCall; break;
   case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break;
   case lltok::kw_x86_regcallcc:  CC = CallingConv::X86_RegCall; break;
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index f49feb2..2ebfb9d 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -132,6 +132,7 @@
   kw_fastcc,
   kw_coldcc,
   kw_intel_ocl_bicc,
+  kw_cfguard_checkcc,
   kw_x86_stdcallcc,
   kw_x86_fastcallcc,
   kw_x86_thiscallcc,
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 73c53d6..3692a03 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -139,7 +139,7 @@
 static const char *const EHTimerName = "write_exception";
 static const char *const EHTimerDescription = "DWARF Exception Writer";
 static const char *const CFGuardName = "Control Flow Guard";
-static const char *const CFGuardDescription = "Control Flow Guard Tables";
+static const char *const CFGuardDescription = "Control Flow Guard";
 static const char *const CodeViewLineTablesGroupName = "linetables";
 static const char *const CodeViewLineTablesGroupDescription =
   "CodeView Line Tables";
@@ -381,12 +381,12 @@
                           EHTimerDescription, DWARFGroupName,
                           DWARFGroupDescription);
 
+  // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2).
   if (mdconst::extract_or_null<ConstantInt>(
-          MMI->getModule()->getModuleFlag("cfguardtable")))
+          MMI->getModule()->getModuleFlag("cfguard")))
     Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName,
                           CFGuardDescription, DWARFGroupName,
                           DWARFGroupDescription);
-
   return false;
 }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
index 290be81..f071a25 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
@@ -6,7 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file contains support for writing Win64 exception info into asm files.
+// This file contains support for writing the metadata for Windows Control Flow
+// Guard, including address-taken functions, and valid longjmp targets.
 //
 //===----------------------------------------------------------------------===//
 
@@ -29,16 +30,33 @@
 
 WinCFGuard::~WinCFGuard() {}
 
+void WinCFGuard::endFunction(const MachineFunction *MF) {
+
+  // Skip functions without any longjmp targets.
+  if (MF->getLongjmpTargets().empty())
+    return;
+
+  // Copy the function's longjmp targets to a module-level list.
+  LongjmpTargets.insert(LongjmpTargets.end(), MF->getLongjmpTargets().begin(),
+                        MF->getLongjmpTargets().end());
+}
+
 void WinCFGuard::endModule() {
   const Module *M = Asm->MMI->getModule();
   std::vector<const Function *> Functions;
   for (const Function &F : *M)
     if (F.hasAddressTaken())
       Functions.push_back(&F);
-  if (Functions.empty())
+  if (Functions.empty() && LongjmpTargets.empty())
     return;
   auto &OS = *Asm->OutStreamer;
   OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection());
   for (const Function *F : Functions)
     OS.EmitCOFFSymbolIndex(Asm->getSymbol(F));
+
+  // Emit the symbol index of each longjmp target.
+  OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection());
+  for (const MCSymbol *S : LongjmpTargets) {
+    OS.EmitCOFFSymbolIndex(S);
+  }
 }
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
index def0a59..494a153 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
+++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
@@ -6,7 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file contains support for writing windows exception info into asm files.
+// This file contains support for writing the metadata for Windows Control Flow
+// Guard, including address-taken functions, and valid longjmp targets.
 //
 //===----------------------------------------------------------------------===//
 
@@ -15,12 +16,14 @@
 
 #include "llvm/CodeGen/AsmPrinterHandler.h"
 #include "llvm/Support/Compiler.h"
+#include <vector>
 
 namespace llvm {
 
 class LLVM_LIBRARY_VISIBILITY WinCFGuard : public AsmPrinterHandler {
   /// Target of directive emission.
   AsmPrinter *Asm;
+  std::vector<const MCSymbol *> LongjmpTargets;
 
 public:
   WinCFGuard(AsmPrinter *A);
@@ -28,7 +31,7 @@
 
   void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
 
-  /// Emit the Control Flow Guard function ID table
+  /// Emit the Control Flow Guard function ID table.
   void endModule() override;
 
   /// Gather pre-function debug information.
@@ -39,7 +42,7 @@
   /// Gather post-function debug information.
   /// Please note that some AsmPrinter implementations may not call
   /// beginFunction at all.
-  void endFunction(const MachineFunction *MF) override {}
+  void endFunction(const MachineFunction *MF) override;
 
   /// Process beginning of an instruction.
   void beginInstruction(const MachineInstr *MI) override {}
diff --git a/llvm/lib/CodeGen/CFGuardLongjmp.cpp b/llvm/lib/CodeGen/CFGuardLongjmp.cpp
new file mode 100644
index 0000000..42ad22b
--- /dev/null
+++ b/llvm/lib/CodeGen/CFGuardLongjmp.cpp
@@ -0,0 +1,119 @@
+//===-- CFGuardLongjmp.cpp - Longjmp symbols for CFGuard --------*- C++ -*-===//

+//

+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.

+// See https://llvm.org/LICENSE.txt for license information.

+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

+//

+//===----------------------------------------------------------------------===//

+///

+/// \file

+/// This file contains a machine function pass to insert a symbol after each

+/// call to _setjmp and store this in the MachineFunction's LongjmpTargets

+/// vector. This will be used to emit the table of valid longjmp targets used

+/// by Control Flow Guard.

+///

+//===----------------------------------------------------------------------===//

+

+#include "llvm/ADT/Statistic.h"

+#include "llvm/CodeGen/MachineBasicBlock.h"

+#include "llvm/CodeGen/MachineFunctionPass.h"

+#include "llvm/CodeGen/MachineInstr.h"

+#include "llvm/CodeGen/MachineModuleInfo.h"

+#include "llvm/CodeGen/MachineOperand.h"

+#include "llvm/CodeGen/Passes.h"

+

+using namespace llvm;

+

+#define DEBUG_TYPE "cfguard-longjmp"

+

+STATISTIC(CFGuardLongjmpTargets,

+          "Number of Control Flow Guard longjmp targets");

+

+namespace {

+

+/// MachineFunction pass to insert a symbol after each call to _setjmp and store

+/// this in the MachineFunction's LongjmpTargets vector.

+class CFGuardLongjmp : public MachineFunctionPass {

+public:

+  static char ID;

+

+  CFGuardLongjmp() : MachineFunctionPass(ID) {

+    initializeCFGuardLongjmpPass(*PassRegistry::getPassRegistry());

+  }

+

+  StringRef getPassName() const override {

+    return "Control Flow Guard longjmp targets";

+  }

+

+  bool runOnMachineFunction(MachineFunction &MF) override;

+};

+

+} // end anonymous namespace

+

+char CFGuardLongjmp::ID = 0;

+

+INITIALIZE_PASS(CFGuardLongjmp, "CFGuardLongjmp",

+                "Insert symbols at valid longjmp targets for /guard:cf", false,

+                false)

+FunctionPass *llvm::createCFGuardLongjmpPass() { return new CFGuardLongjmp(); }

+

+bool CFGuardLongjmp::runOnMachineFunction(MachineFunction &MF) {

+

+  // Skip modules for which the cfguard flag is not set.

+  if (!MF.getMMI().getModule()->getModuleFlag("cfguard"))

+    return false;

+

+  // Skip functions that do not have calls to _setjmp.

+  if (!MF.getFunction().callsFunctionThatReturnsTwice())

+    return false;

+

+  SmallVector<MachineInstr *, 8> SetjmpCalls;

+

+  // Iterate over all instructions in the function and add calls to functions

+  // that return twice to the list of targets.

+  for (MachineBasicBlock &MBB : MF) {

+    for (MachineInstr &MI : MBB) {

+

+      // Skip instructions that are not calls.

+      if (!MI.isCall() || MI.getNumOperands() < 1)

+        continue;

+

+      // Iterate over operands to find calls to global functions.

+      for (MachineOperand &MO : MI.operands()) {

+        if (!MO.isGlobal())

+          continue;

+

+        auto *F = dyn_cast<Function>(MO.getGlobal());

+        if (!F)

+          continue;

+

+        // If the instruction calls a function that returns twice, add

+        // it to the list of targets.

+        if (F->hasFnAttribute(Attribute::ReturnsTwice)) {

+          SetjmpCalls.push_back(&MI);

+          break;

+        }

+      }

+    }

+  }

+

+  if (SetjmpCalls.empty())

+    return false;

+

+  unsigned SetjmpNum = 0;

+

+  // For each possible target, create a new symbol and insert it immediately

+  // after the call to setjmp. Add this symbol to the MachineFunction's list

+  // of longjmp targets.

+  for (MachineInstr *Setjmp : SetjmpCalls) {

+    SmallString<128> SymbolName;

+    raw_svector_ostream(SymbolName) << "$cfgsj_" << MF.getName() << SetjmpNum++;

+    MCSymbol *SjSymbol = MF.getContext().getOrCreateSymbol(SymbolName);

+

+    Setjmp->setPostInstrSymbol(MF, SjSymbol);

+    MF.addLongjmpTarget(SjSymbol);

+    CFGuardLongjmpTargets++;

+  }

+

+  return true;

+}

diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 50b469d..1d561c3 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -10,6 +10,7 @@
   BuiltinGCs.cpp
   CalcSpillWeights.cpp
   CallingConvLower.cpp
+  CFGuardLongjmp.cpp
   CFIInstrInserter.cpp
   CodeGen.cpp
   CodeGenPrepare.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index ad9525f..85696cc 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -22,6 +22,7 @@
   initializeAtomicExpandPass(Registry);
   initializeBranchFolderPassPass(Registry);
   initializeBranchRelaxationPass(Registry);
+  initializeCFGuardLongjmpPass(Registry);
   initializeCFIInstrInserterPass(Registry);
   initializeCodeGenPreparePass(Registry);
   initializeDeadMachineInstructionElimPass(Registry);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 45cef4a..6e2d220 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1590,6 +1590,10 @@
   if (F && F->hasDLLImportStorageClass())
     return false;
 
+  // FIXME: support control flow guard targets.
+  if (CI.countOperandBundlesOfType(LLVMContext::OB_cfguardtarget))
+    return false;
+
   if (CI.isInlineAsm())
     return translateInlineAsm(CI, MIRBuilder);
 
@@ -1683,6 +1687,10 @@
   if (I.countOperandBundlesOfType(LLVMContext::OB_deopt))
     return false;
 
+  // FIXME: support control flow guard targets.
+  if (I.countOperandBundlesOfType(LLVMContext::OB_cfguardtarget))
+    return false;
+
   // FIXME: support Windows exception handling.
   if (!isa<LandingPadInst>(EHPadBB->front()))
     return false;
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 6d7260d..4586a20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1190,6 +1190,8 @@
       Flags.setSwiftSelf();
     if (Arg.IsSwiftError)
       Flags.setSwiftError();
+    if (Arg.IsCFGuardTarget)
+      Flags.setCFGuardTarget();
     if (Arg.IsByVal)
       Flags.setByVal();
     if (Arg.IsInAlloca) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 51f5b19..e8e2bb4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2746,8 +2746,9 @@
 
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
   // have to do anything here to lower funclet bundles.
-  assert(!I.hasOperandBundlesOtherThan(
-             {LLVMContext::OB_deopt, LLVMContext::OB_funclet}) &&
+  assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,
+                                        LLVMContext::OB_funclet,
+                                        LLVMContext::OB_cfguardtarget}) &&
          "Cannot lower invokes with arbitrary operand bundles yet!");
 
   const Value *Callee(I.getCalledValue());
@@ -7145,6 +7146,18 @@
       isTailCall = false;
   }
 
+  // If call site has a cfguardtarget operand bundle, create and add an
+  // additional ArgListEntry.
+  if (auto Bundle = CS.getOperandBundle(LLVMContext::OB_cfguardtarget)) {
+    TargetLowering::ArgListEntry Entry;
+    Value *V = Bundle->Inputs[0];
+    SDValue ArgNode = getValue(V);
+    Entry.Node = ArgNode;
+    Entry.Ty = V->getType();
+    Entry.IsCFGuardTarget = true;
+    Args.push_back(Entry);
+  }
+
   // Check if target-independent constraints permit a tail call here.
   // Target-dependent constraints are checked within TLI->LowerCallTo.
   if (isTailCall && !isInTailCallPosition(CS, DAG.getTarget()))
@@ -7686,8 +7699,10 @@
 
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
   // have to do anything here to lower funclet bundles.
-  assert(!I.hasOperandBundlesOtherThan(
-             {LLVMContext::OB_deopt, LLVMContext::OB_funclet}) &&
+  // CFGuardTarget bundles are lowered in LowerCallTo.
+  assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,
+                                        LLVMContext::OB_funclet,
+                                        LLVMContext::OB_cfguardtarget}) &&
          "Cannot lower calls with arbitrary operand bundles!");
 
   SDValue Callee = getValue(I.getCalledValue());
@@ -9030,6 +9045,7 @@
     Entry.IsReturned = false;
     Entry.IsSwiftSelf = false;
     Entry.IsSwiftError = false;
+    Entry.IsCFGuardTarget = false;
     Entry.Alignment = Align;
     CLI.getArgs().insert(CLI.getArgs().begin(), Entry);
     CLI.NumFixedArgs += 1;
@@ -9142,6 +9158,8 @@
         Flags.setSwiftSelf();
       if (Args[i].IsSwiftError)
         Flags.setSwiftError();
+      if (Args[i].IsCFGuardTarget)
+        Flags.setCFGuardTarget();
       if (Args[i].IsByVal)
         Flags.setByVal();
       if (Args[i].IsInAlloca) {
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index b0c26e0..f811c84 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -353,6 +353,7 @@
   case CallingConv::CXX_FAST_TLS:  Out << "cxx_fast_tlscc"; break;
   case CallingConv::GHC:           Out << "ghccc"; break;
   case CallingConv::Tail:          Out << "tailcc"; break;
+  case CallingConv::CFGuard_Check: Out << "cfguard_checkcc"; break;
   case CallingConv::X86_StdCall:   Out << "x86_stdcallcc"; break;
   case CallingConv::X86_FastCall:  Out << "x86_fastcallcc"; break;
   case CallingConv::X86_ThisCall:  Out << "x86_thiscallcc"; break;
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 5e87721..cb13b27 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -62,6 +62,11 @@
          "gc-transition operand bundle id drifted!");
   (void)GCTransitionEntry;
 
+  auto *CFGuardTargetEntry = pImpl->getOrInsertBundleTag("cfguardtarget");
+  assert(CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget &&
+         "cfguardtarget operand bundle id drifted!");
+  (void)CFGuardTargetEntry;
+
   SyncScope::ID SingleThreadSSID =
       pImpl->getOrInsertSyncScopeID("singlethread");
   assert(SingleThreadSSID == SyncScope::SingleThread &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b17fc43..497dc39 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2975,10 +2975,10 @@
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCall(ID, Call);
 
-  // Verify that a callsite has at most one "deopt", at most one "funclet" and
-  // at most one "gc-transition" operand bundle.
+  // Verify that a callsite has at most one "deopt", at most one "funclet", at
+  // most one "gc-transition", and at most one "cfguardtarget" operand bundle.
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,
-       FoundGCTransitionBundle = false;
+       FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false;
   for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {
     OperandBundleUse BU = Call.getOperandBundleAt(i);
     uint32_t Tag = BU.getTagID();
@@ -2997,6 +2997,12 @@
       Assert(isa<FuncletPadInst>(BU.Inputs.front()),
              "Funclet bundle operands should correspond to a FuncletPadInst",
              Call);
+    } else if (Tag == LLVMContext::OB_cfguardtarget) {
+      Assert(!FoundCFGuardTargetBundle,
+             "Multiple CFGuardTarget operand bundles", Call);
+      FoundCFGuardTargetBundle = true;
+      Assert(BU.Inputs.size() == 1,
+             "Expected exactly one cfguardtarget bundle operand", Call);
     }
   }
 
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 70c0409..1a9ceb0 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -715,6 +715,11 @@
                                          COFF::IMAGE_SCN_MEM_READ,
                                      SectionKind::getMetadata());
 
+  GLJMPSection = Ctx->getCOFFSection(".gljmp$y",
+                                     COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                         COFF::IMAGE_SCN_MEM_READ,
+                                     SectionKind::getMetadata());
+
   TLSDataSection = Ctx->getCOFFSection(
       ".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
                    COFF::IMAGE_SCN_MEM_WRITE,
diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.h b/llvm/lib/Target/AArch64/AArch64CallingConvention.h
index 5a55d09..59939e0 100644
--- a/llvm/lib/Target/AArch64/AArch64CallingConvention.h
+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.h
@@ -31,6 +31,9 @@
 bool CC_AArch64_Win64_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT,
                              CCValAssign::LocInfo LocInfo,
                              ISD::ArgFlagsTy ArgFlags, CCState &State);
+bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT,
+                                    CCValAssign::LocInfo LocInfo,
+                                    ISD::ArgFlagsTy ArgFlags, CCState &State);
 bool CC_AArch64_WebKit_JS(unsigned ValNo, MVT ValVT, MVT LocVT,
                           CCValAssign::LocInfo LocInfo,
                           ISD::ArgFlagsTy ArgFlags, CCState &State);
diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td
index bccbbd4..3c4121b 100644
--- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td
+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td
@@ -170,6 +170,13 @@
   CCDelegateTo<CC_AArch64_AAPCS>
 ]>;
 
+// Windows Control Flow Guard checks take a single argument (the target function
+// address) and have no return value.
+let Entry = 1 in
+def CC_AArch64_Win64_CFGuard_Check : CallingConv<[
+  CCIfType<[i64], CCAssignToReg<[X15]>>
+]>;
+
 
 // Darwin uses a calling convention which differs in only two ways
 // from the standard one at this level:
@@ -384,6 +391,12 @@
                                                D8, D9, D10, D11,
                                                D12, D13, D14, D15)>;
 
+// The Control Flow Guard check call uses a custom calling convention that also
+// preserves X0-X8 and Q0-Q7.
+def CSR_Win_AArch64_CFGuard_Check : CalleeSavedRegs<(add CSR_Win_AArch64_AAPCS,
+                                               (sequence "X%u", 0, 8),
+                                               (sequence "Q%u", 0, 7))>;
+
 // AArch64 PCS for vector functions (VPCS)
 // must (additionally) preserve full Q8-Q23 registers
 def CSR_AArch64_AAVPCS : CalleeSavedRegs<(add X19, X20, X21, X22, X23, X24,
diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
index 277a305..98410c2 100644
--- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
@@ -348,6 +348,8 @@
     return CC_AArch64_WebKit_JS;
   if (CC == CallingConv::GHC)
     return CC_AArch64_GHC;
+  if (CC == CallingConv::CFGuard_Check)
+    return CC_AArch64_Win64_CFGuard_Check;
   return Subtarget->isTargetDarwin() ? CC_AArch64_DarwinPCS : CC_AArch64_AAPCS;
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index aa9e26c..8e3a524 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3118,8 +3118,10 @@
                                       : CC_AArch64_DarwinPCS_VarArg;
    case CallingConv::Win64:
     return IsVarArg ? CC_AArch64_Win64_VarArg : CC_AArch64_AAPCS;
-  case CallingConv::AArch64_VectorCall:
-    return CC_AArch64_AAPCS;
+   case CallingConv::CFGuard_Check:
+     return CC_AArch64_Win64_CFGuard_Check;
+   case CallingConv::AArch64_VectorCall:
+     return CC_AArch64_AAPCS;
   }
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index de17608..918e89f 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -43,6 +43,8 @@
 const MCPhysReg *
 AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   assert(MF && "Invalid MachineFunction pointer.");
+  if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
+    return CSR_Win_AArch64_CFGuard_Check_SaveList;
   if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows())
     return CSR_Win_AArch64_AAPCS_SaveList;
   if (MF->getFunction().getCallingConv() == CallingConv::GHC)
@@ -124,6 +126,8 @@
     return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
   if (CC == CallingConv::AArch64_SVE_VectorCall)
     return CSR_AArch64_SVE_AAPCS_RegMask;
+  if (CC == CallingConv::CFGuard_Check)
+    return CSR_Win_AArch64_CFGuard_Check_RegMask;
   if (MF.getSubtarget<AArch64Subtarget>().getTargetLowering()
           ->supportSwiftError() &&
       MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index b3ed96e..0ec1e66 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 #include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/CFGuard.h"
 #include "llvm/Transforms/Scalar.h"
 #include <memory>
 #include <string>
@@ -459,6 +460,10 @@
 
   addPass(createAArch64StackTaggingPass(/* MergeInit = */ TM->getOptLevel() !=
                                         CodeGenOpt::None));
+
+  // Add Control Flow Guard checks.
+  if (TM->getTargetTriple().isOSWindows())
+    addPass(createCFGuardCheckPass());
 }
 
 // Pass Pipeline Configuration
@@ -617,6 +622,10 @@
   if (EnableBranchTargets)
     addPass(createAArch64BranchTargetsPass());
 
+  // Identify valid longjmp targets for Windows Control Flow Guard.
+  if (TM->getTargetTriple().isOSWindows())
+    addPass(createCFGuardLongjmpPass());
+
   if (TM->getOptLevel() != CodeGenOpt::None && EnableCompressJumpTables)
     addPass(createAArch64CompressJumpTablesPass());
 
diff --git a/llvm/lib/Target/AArch64/LLVMBuild.txt b/llvm/lib/Target/AArch64/LLVMBuild.txt
index 620d3a8..08ff464 100644
--- a/llvm/lib/Target/AArch64/LLVMBuild.txt
+++ b/llvm/lib/Target/AArch64/LLVMBuild.txt
@@ -30,5 +30,5 @@
 type = Library
 name = AArch64CodeGen
 parent = AArch64
-required_libraries = AArch64Desc AArch64Info AArch64Utils Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target TransformUtils GlobalISel
+required_libraries = AArch64Desc AArch64Info AArch64Utils Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target TransformUtils GlobalISel CFGuard
 add_to_library_groups = AArch64
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 1eaf871..0276ff1 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -75,6 +75,8 @@
     // GHC set of callee saved regs is empty as all those regs are
     // used for passing STG regs around
     return CSR_NoRegs_SaveList;
+  } else if (F.getCallingConv() == CallingConv::CFGuard_Check) {
+    return CSR_Win_AAPCS_CFGuard_Check_SaveList;
   } else if (F.hasFnAttribute("interrupt")) {
     if (STI.isMClass()) {
       // M-class CPUs have hardware which saves the registers needed to allow a
@@ -123,7 +125,8 @@
   if (CC == CallingConv::GHC)
     // This is academic because all GHC calls are (supposed to be) tail calls
     return CSR_NoRegs_RegMask;
-
+  if (CC == CallingConv::CFGuard_Check)
+    return CSR_Win_AAPCS_CFGuard_Check_RegMask;
   if (STI.getTargetLowering()->supportSwiftError() &&
       MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
     return STI.isTargetDarwin() ? CSR_iOS_SwiftError_RegMask
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.h b/llvm/lib/Target/ARM/ARMCallingConv.h
index 6156345..7c692f0 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.h
+++ b/llvm/lib/Target/ARM/ARMCallingConv.h
@@ -32,6 +32,9 @@
 bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT,
                      CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
                      CCState &State);
+bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT,
+                                CCValAssign::LocInfo LocInfo,
+                                ISD::ArgFlagsTy ArgFlags, CCState &State);
 bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
                      CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
                      CCState &State);
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.td b/llvm/lib/Target/ARM/ARMCallingConv.td
index 61d2d83..55111f5 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.td
+++ b/llvm/lib/Target/ARM/ARMCallingConv.td
@@ -246,6 +246,16 @@
   CCDelegateTo<RetCC_ARM_AAPCS_Common>
 ]>;
 
+
+// Windows Control Flow Guard checks take a single argument (the target function
+// address) and have no return value.
+let Entry = 1 in
+def CC_ARM_Win32_CFGuard_Check : CallingConv<[
+  CCIfType<[i32], CCAssignToReg<[R0]>>
+]>;
+
+
+
 //===----------------------------------------------------------------------===//
 // Callee-saved register lists.
 //===----------------------------------------------------------------------===//
@@ -256,6 +266,11 @@
 def CSR_AAPCS : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7, R6, R5, R4,
                                      (sequence "D%u", 15, 8))>;
 
+// The Windows Control Flow Guard Check function preserves the same registers as
+// AAPCS, and also preserves all floating point registers.
+def CSR_Win_AAPCS_CFGuard_Check : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7,
+                                     R6, R5, R4, (sequence "D%u", 15, 0))>;
+
 // R8 is used to pass swifterror, remove it from CSR.
 def CSR_AAPCS_SwiftError : CalleeSavedRegs<(sub CSR_AAPCS, R8)>;
 
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp
index 1fc5ff6..6c204bc 100644
--- a/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -1879,6 +1879,8 @@
       report_fatal_error("Can't return in GHC call convention");
     else
       return CC_ARM_APCS_GHC;
+  case CallingConv::CFGuard_Check:
+    return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
   }
 }
 
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index bb6bca5..6e511e6 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1855,6 +1855,7 @@
   case CallingConv::ARM_AAPCS:
   case CallingConv::ARM_APCS:
   case CallingConv::GHC:
+  case CallingConv::CFGuard_Check:
     return CC;
   case CallingConv::PreserveMost:
     return CallingConv::PreserveMost;
@@ -1914,6 +1915,8 @@
     return (Return ? RetCC_ARM_APCS : CC_ARM_APCS_GHC);
   case CallingConv::PreserveMost:
     return (Return ? RetCC_ARM_AAPCS : CC_ARM_AAPCS);
+  case CallingConv::CFGuard_Check:
+    return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
   }
 }
 
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 5c8007f..7f85b93 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -46,6 +46,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 #include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/CFGuard.h"
 #include "llvm/Transforms/Scalar.h"
 #include <cassert>
 #include <memory>
@@ -420,6 +421,10 @@
   // Match interleaved memory accesses to ldN/stN intrinsics.
   if (TM->getOptLevel() != CodeGenOpt::None)
     addPass(createInterleavedAccessPass());
+
+  // Add Control Flow Guard checks.
+  if (TM->getTargetTriple().isOSWindows())
+    addPass(createCFGuardCheckPass());
 }
 
 void ARMPassConfig::addCodeGenPrepare() {
@@ -534,4 +539,8 @@
 
   addPass(createARMConstantIslandPass());
   addPass(createARMLowOverheadLoopsPass());
+
+  // Identify valid longjmp targets for Windows Control Flow Guard.
+  if (TM->getTargetTriple().isOSWindows())
+    addPass(createCFGuardLongjmpPass());
 }
diff --git a/llvm/lib/Target/ARM/LLVMBuild.txt b/llvm/lib/Target/ARM/LLVMBuild.txt
index 7a6b3a8..40f8c2c 100644
--- a/llvm/lib/Target/ARM/LLVMBuild.txt
+++ b/llvm/lib/Target/ARM/LLVMBuild.txt
@@ -30,5 +30,5 @@
 type = Library
 name = ARMCodeGen
 parent = ARM
-required_libraries = ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel ARMUtils TransformUtils
+required_libraries = ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel ARMUtils TransformUtils CFGuard
 add_to_library_groups = ARM
diff --git a/llvm/lib/Target/X86/LLVMBuild.txt b/llvm/lib/Target/X86/LLVMBuild.txt
index bfc0eda..5d09ced 100644
--- a/llvm/lib/Target/X86/LLVMBuild.txt
+++ b/llvm/lib/Target/X86/LLVMBuild.txt
@@ -30,5 +30,5 @@
 type = Library
 name = X86CodeGen
 parent = X86
-required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG Support Target X86Desc X86Info X86Utils GlobalISel ProfileData
+required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG Support Target X86Desc X86Info X86Utils GlobalISel ProfileData CFGuard
 add_to_library_groups = X86
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 8d27be3..cc1e79d 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -614,7 +614,7 @@
       Feat00Flags |= 1;
     }
 
-    if (M.getModuleFlag("cfguardtable"))
+    if (M.getModuleFlag("cfguard"))
       Feat00Flags |= 0x800; // Object is CFG-aware.
 
     OutStreamer->EmitSymbolAttribute(S, MCSA_Global);
diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td
index 4c49d68..30d05c6 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -434,6 +434,7 @@
   // If FastCC, use RetCC_X86_32_Fast.
   CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_X86_32_Fast>>,
   CCIfCC<"CallingConv::Tail", CCDelegateTo<RetCC_X86_32_Fast>>,
+  // CFGuard_Check never returns a value so does not need a RetCC.
   // If HiPE, use RetCC_X86_32_HiPE.
   CCIfCC<"CallingConv::HiPE", CCDelegateTo<RetCC_X86_32_HiPE>>,
   CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo<RetCC_X86_32_VectorCall>>,
@@ -606,6 +607,9 @@
   // A SwiftError is passed in R12.
   CCIfSwiftError<CCIfType<[i64], CCAssignToReg<[R12]>>>,
 
+  // The 'CFGuardTarget' parameter, if any, is passed in RAX.
+  CCIfCFGuardTarget<CCAssignToReg<[RAX]>>,
+
   // 128 bit vectors are passed by pointer
   CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCPassIndirect<i64>>,
 
@@ -936,6 +940,12 @@
   CCDelegateTo<CC_X86_32_Common>
 ]>;
 
+def CC_X86_Win32_CFGuard_Check : CallingConv<[
+  // The CFGuard check call takes exactly one integer argument
+  // (i.e. the target function address), which is passed in ECX.
+  CCIfType<[i32], CCAssignToReg<[ECX]>>
+]>;
+
 def CC_X86_32_GHC : CallingConv<[
   // Promote i8/i16 arguments to i32.
   CCIfType<[i8, i16], CCPromoteToType<i32>>,
@@ -1000,6 +1010,7 @@
   CCIfCC<"CallingConv::X86_FastCall", CCDelegateTo<CC_X86_32_FastCall>>,
   CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo<CC_X86_Win32_VectorCall>>,
   CCIfCC<"CallingConv::X86_ThisCall", CCDelegateTo<CC_X86_32_ThisCall>>,
+  CCIfCC<"CallingConv::CFGuard_Check", CCDelegateTo<CC_X86_Win32_CFGuard_Check>>,
   CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_X86_32_FastCC>>,
   CCIfCC<"CallingConv::Tail", CCDelegateTo<CC_X86_32_FastCC>>,
   CCIfCC<"CallingConv::GHC", CCDelegateTo<CC_X86_32_GHC>>,
@@ -1136,7 +1147,9 @@
 // Register calling convention preserves few GPR and XMM8-15
 def CSR_32_RegCall_NoSSE : CalleeSavedRegs<(add ESI, EDI, EBX, EBP, ESP)>;
 def CSR_32_RegCall       : CalleeSavedRegs<(add CSR_32_RegCall_NoSSE,
-                                           (sequence "XMM%u", 4, 7))>;                                            
+                                           (sequence "XMM%u", 4, 7))>;
+def CSR_Win32_CFGuard_Check_NoSSE : CalleeSavedRegs<(add CSR_32_RegCall_NoSSE, ECX)>;
+def CSR_Win32_CFGuard_Check       : CalleeSavedRegs<(add CSR_32_RegCall, ECX)>;
 def CSR_Win64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, RSP,
                                               (sequence "R%u", 10, 15))>;
 def CSR_Win64_RegCall       : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE,                                  
diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp
index e5e089d..e5e84bb 100644
--- a/llvm/lib/Target/X86/X86FastISel.cpp
+++ b/llvm/lib/Target/X86/X86FastISel.cpp
@@ -3218,6 +3218,7 @@
   case CallingConv::X86_ThisCall:
   case CallingConv::Win64:
   case CallingConv::X86_64_SysV:
+  case CallingConv::CFGuard_Check:
     break;
   }
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index ff62532..9362c60 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -341,6 +341,10 @@
       return (HasSSE ? CSR_32_RegCall_SaveList :
                        CSR_32_RegCall_NoSSE_SaveList);
     }
+  case CallingConv::CFGuard_Check:
+    assert(!Is64Bit && "CFGuard check mechanism only used on 32-bit X86");
+    return (HasSSE ? CSR_Win32_CFGuard_Check_SaveList
+                   : CSR_Win32_CFGuard_Check_NoSSE_SaveList);
   case CallingConv::Cold:
     if (Is64Bit)
       return CSR_64_MostRegs_SaveList;
@@ -455,6 +459,10 @@
       return (HasSSE ? CSR_32_RegCall_RegMask :
                        CSR_32_RegCall_NoSSE_RegMask);
     }
+  case CallingConv::CFGuard_Check:
+    assert(!Is64Bit && "CFGuard check mechanism only used on 32-bit X86");
+    return (HasSSE ? CSR_Win32_CFGuard_Check_RegMask
+                   : CSR_Win32_CFGuard_Check_NoSSE_RegMask);
   case CallingConv::Cold:
     if (Is64Bit)
       return CSR_64_MostRegs_RegMask;
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index c152971..21f1ef9 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -46,6 +46,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 #include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/CFGuard.h"
 #include <memory>
 #include <string>
 
@@ -414,6 +415,16 @@
   // thunk. These will be a no-op unless a function subtarget has the retpoline
   // feature enabled.
   addPass(createIndirectBrExpandPass());
+
+  // Add Control Flow Guard checks.
+  const Triple &TT = TM->getTargetTriple();
+  if (TT.isOSWindows()) {
+    if (TT.getArch() == Triple::x86_64) {
+      addPass(createCFGuardDispatchPass());
+    } else {
+      addPass(createCFGuardCheckPass());
+    }
+  }
 }
 
 bool X86PassConfig::addInstSelector() {
@@ -530,6 +541,9 @@
       (!TT.isOSWindows() ||
        MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI))
     addPass(createCFIInstrInserter());
+  // Identify valid longjmp targets for Windows Control Flow Guard.
+  if (TT.isOSWindows())
+    addPass(createCFGuardLongjmpPass());
 }
 
 std::unique_ptr<CSEConfigBase> X86PassConfig::getCSEConfig() const {
diff --git a/llvm/lib/Transforms/CFGuard/CFGuard.cpp b/llvm/lib/Transforms/CFGuard/CFGuard.cpp
new file mode 100644
index 0000000..9517e21
--- /dev/null
+++ b/llvm/lib/Transforms/CFGuard/CFGuard.cpp
@@ -0,0 +1,307 @@
+//===-- CFGuard.cpp - Control Flow Guard checks -----------------*- C++ -*-===//

+//

+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.

+// See https://llvm.org/LICENSE.txt for license information.

+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

+//

+//===----------------------------------------------------------------------===//

+///

+/// \file

+/// This file contains the IR transform to add Microsoft's Control Flow Guard

+/// checks on Windows targets.

+///

+//===----------------------------------------------------------------------===//

+

+#include "llvm/Transforms/CFGuard.h"

+#include "llvm/ADT/SmallVector.h"

+#include "llvm/ADT/Statistic.h"

+#include "llvm/ADT/Triple.h"

+#include "llvm/IR/CallingConv.h"

+#include "llvm/IR/IRBuilder.h"

+#include "llvm/IR/Instruction.h"

+#include "llvm/InitializePasses.h"

+#include "llvm/Pass.h"

+

+using namespace llvm;

+

+using OperandBundleDef = OperandBundleDefT<Value *>;

+

+#define DEBUG_TYPE "cfguard"

+

+STATISTIC(CFGuardCounter, "Number of Control Flow Guard checks added");

+

+namespace {

+

+/// Adds Control Flow Guard (CFG) checks on indirect function calls/invokes.

+/// These checks ensure that the target address corresponds to the start of an

+/// address-taken function. X86_64 targets use the CF_Dispatch mechanism. X86,

+/// ARM, and AArch64 targets use the CF_Check machanism.

+class CFGuard : public FunctionPass {

+public:

+  static char ID;

+

+  enum Mechanism { CF_Check, CF_Dispatch };

+

+  // Default constructor required for the INITIALIZE_PASS macro.

+  CFGuard() : FunctionPass(ID) {

+    initializeCFGuardPass(*PassRegistry::getPassRegistry());

+    // By default, use the guard check mechanism.

+    GuardMechanism = CF_Check;

+  }

+

+  // Recommended constructor used to specify the type of guard mechanism.

+  CFGuard(Mechanism Var) : FunctionPass(ID) {

+    initializeCFGuardPass(*PassRegistry::getPassRegistry());

+    GuardMechanism = Var;

+  }

+

+  /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG

+  /// check mechanism. When the image is loaded, the loader puts the appropriate

+  /// guard check function pointer in the __guard_check_icall_fptr global

+  /// symbol. This checks that the target address is a valid address-taken

+  /// function. The address of the target function is passed to the guard check

+  /// function in an architecture-specific register (e.g. ECX on 32-bit X86,

+  /// X15 on Aarch64, and R0 on ARM). The guard check function has no return

+  /// value (if the target is invalid, the guard check funtion will raise an

+  /// error).

+  ///

+  /// For example, the following LLVM IR:

+  /// \code

+  ///   %func_ptr = alloca i32 ()*, align 8

+  ///   store i32 ()* @target_func, i32 ()** %func_ptr, align 8

+  ///   %0 = load i32 ()*, i32 ()** %func_ptr, align 8

+  ///   %1 = call i32 %0()

+  /// \endcode

+  ///

+  /// is transformed to:

+  /// \code

+  ///   %func_ptr = alloca i32 ()*, align 8

+  ///   store i32 ()* @target_func, i32 ()** %func_ptr, align 8

+  ///   %0 = load i32 ()*, i32 ()** %func_ptr, align 8

+  ///   %1 = load void (i8*)*, void (i8*)** @__guard_check_icall_fptr

+  ///   %2 = bitcast i32 ()* %0 to i8*

+  ///   call cfguard_checkcc void %1(i8* %2)

+  ///   %3 = call i32 %0()

+  /// \endcode

+  ///

+  /// For example, the following X86 assembly code:

+  /// \code

+  ///   movl  $_target_func, %eax

+  ///   calll *%eax

+  /// \endcode

+  ///

+  /// is transformed to:

+  /// \code

+  /// 	movl	$_target_func, %ecx

+  /// 	calll	*___guard_check_icall_fptr

+  /// 	calll	*%ecx

+  /// \endcode

+  ///

+  /// \param CB indirect call to instrument.

+  void insertCFGuardCheck(CallBase *CB);

+

+  /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG

+  /// dispatch mechanism. When the image is loaded, the loader puts the

+  /// appropriate guard check function pointer in the

+  /// __guard_dispatch_icall_fptr global symbol. This checks that the target

+  /// address is a valid address-taken function and, if so, tail calls the

+  /// target. The target address is passed in an architecture-specific register

+  /// (e.g. RAX on X86_64), with all other arguments for the target function

+  /// passed as usual.

+  ///

+  /// For example, the following LLVM IR:

+  /// \code

+  ///   %func_ptr = alloca i32 ()*, align 8

+  ///   store i32 ()* @target_func, i32 ()** %func_ptr, align 8

+  ///   %0 = load i32 ()*, i32 ()** %func_ptr, align 8

+  ///   %1 = call i32 %0()

+  /// \endcode

+  ///

+  /// is transformed to:

+  /// \code

+  ///   %func_ptr = alloca i32 ()*, align 8

+  ///   store i32 ()* @target_func, i32 ()** %func_ptr, align 8

+  ///   %0 = load i32 ()*, i32 ()** %func_ptr, align 8

+  ///   %1 = load i32 ()*, i32 ()** @__guard_dispatch_icall_fptr

+  ///   %2 = call i32 %1() [ "cfguardtarget"(i32 ()* %0) ]

+  /// \endcode

+  ///

+  /// For example, the following X86_64 assembly code:

+  /// \code

+  ///   leaq   target_func(%rip), %rax

+  ///	  callq  *%rax

+  /// \endcode

+  ///

+  /// is transformed to:

+  /// \code

+  ///   leaq   target_func(%rip), %rax

+  ///   callq  *__guard_dispatch_icall_fptr(%rip)

+  /// \endcode

+  ///

+  /// \param CB indirect call to instrument.

+  void insertCFGuardDispatch(CallBase *CB);

+

+  bool doInitialization(Module &M) override;

+  bool runOnFunction(Function &F) override;

+

+private:

+  // Only add checks if the module has the cfguard=2 flag.

+  int cfguard_module_flag = 0;

+  Mechanism GuardMechanism = CF_Check;

+  FunctionType *GuardFnType = nullptr;

+  PointerType *GuardFnPtrType = nullptr;

+  Constant *GuardFnGlobal = nullptr;

+};

+

+} // end anonymous namespace

+

+void CFGuard::insertCFGuardCheck(CallBase *CB) {

+

+  assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() &&

+         "Only applicable for Windows targets");

+  assert(CB->isIndirectCall() &&

+         "Control Flow Guard checks can only be added to indirect calls");

+

+  IRBuilder<> B(CB);

+  Value *CalledOperand = CB->getCalledOperand();

+

+  // Load the global symbol as a pointer to the check function.

+  LoadInst *GuardCheckLoad = B.CreateLoad(GuardFnPtrType, GuardFnGlobal);

+

+  // Create new call instruction. The CFGuard check should always be a call,

+  // even if the original CallBase is an Invoke or CallBr instruction.

+  CallInst *GuardCheck =

+      B.CreateCall(GuardFnType, GuardCheckLoad,

+                   {B.CreateBitCast(CalledOperand, B.getInt8PtrTy())});

+

+  // Ensure that the first argument is passed in the correct register

+  // (e.g. ECX on 32-bit X86 targets).

+  GuardCheck->setCallingConv(CallingConv::CFGuard_Check);

+}

+

+void CFGuard::insertCFGuardDispatch(CallBase *CB) {

+

+  assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() &&

+         "Only applicable for Windows targets");

+  assert(CB->isIndirectCall() &&

+         "Control Flow Guard checks can only be added to indirect calls");

+

+  IRBuilder<> B(CB);

+  Value *CalledOperand = CB->getCalledOperand();

+  Type *CalledOperandType = CalledOperand->getType();

+

+  // Cast the guard dispatch global to the type of the called operand.

+  PointerType *PTy = PointerType::get(CalledOperandType, 0);

+  if (GuardFnGlobal->getType() != PTy)

+    GuardFnGlobal = ConstantExpr::getBitCast(GuardFnGlobal, PTy);

+

+  // Load the global as a pointer to a function of the same type.

+  LoadInst *GuardDispatchLoad = B.CreateLoad(CalledOperandType, GuardFnGlobal);

+

+  // Add the original call target as a cfguardtarget operand bundle.

+  SmallVector<llvm::OperandBundleDef, 1> Bundles;

+  CB->getOperandBundlesAsDefs(Bundles);

+  Bundles.emplace_back("cfguardtarget", CalledOperand);

+

+  // Create a copy of the call/invoke instruction and add the new bundle.

+  CallBase *NewCB;

+  if (CallInst *CI = dyn_cast<CallInst>(CB)) {

+    NewCB = CallInst::Create(CI, Bundles, CB);

+  } else {

+    assert(isa<InvokeInst>(CB) && "Unknown indirect call type");

+    InvokeInst *II = cast<InvokeInst>(CB);

+    NewCB = llvm::InvokeInst::Create(II, Bundles, CB);

+  }

+

+  // Change the target of the call to be the guard dispatch function.

+  NewCB->setCalledOperand(GuardDispatchLoad);

+

+  // Replace the original call/invoke with the new instruction.

+  CB->replaceAllUsesWith(NewCB);

+

+  // Delete the original call/invoke.

+  CB->eraseFromParent();

+}

+

+bool CFGuard::doInitialization(Module &M) {

+

+  // Check if this module has the cfguard flag and read its value.

+  if (auto *MD =

+          mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard")))

+    cfguard_module_flag = MD->getZExtValue();

+

+  // Skip modules for which CFGuard checks have been disabled.

+  if (cfguard_module_flag != 2)

+    return false;

+

+  // Set up prototypes for the guard check and dispatch functions.

+  GuardFnType = FunctionType::get(Type::getVoidTy(M.getContext()),

+                                  {Type::getInt8PtrTy(M.getContext())}, false);

+  GuardFnPtrType = PointerType::get(GuardFnType, 0);

+

+  // Get or insert the guard check or dispatch global symbols.

+  if (GuardMechanism == CF_Check) {

+    GuardFnGlobal =

+        M.getOrInsertGlobal("__guard_check_icall_fptr", GuardFnPtrType);

+  } else {

+    assert(GuardMechanism == CF_Dispatch && "Invalid CFGuard mechanism");

+    GuardFnGlobal =

+        M.getOrInsertGlobal("__guard_dispatch_icall_fptr", GuardFnPtrType);

+  }

+

+  return true;

+}

+

+bool CFGuard::runOnFunction(Function &F) {

+

+  // Skip modules and functions for which CFGuard checks have been disabled.

+  if (cfguard_module_flag != 2 || F.hasFnAttribute(Attribute::NoCfCheck))

+    return false;

+

+  SmallVector<CallBase *, 8> IndirectCalls;

+

+  // Iterate over the instructions to find all indirect call/invoke/callbr

+  // instructions. Make a separate list of pointers to indirect

+  // call/invoke/callbr instructions because the original instructions will be

+  // deleted as the checks are added.

+  for (BasicBlock &BB : F.getBasicBlockList()) {

+    for (Instruction &I : BB.getInstList()) {

+      auto *CB = dyn_cast<CallBase>(&I);

+      if (CB && CB->isIndirectCall()) {

+        IndirectCalls.push_back(CB);

+        CFGuardCounter++;

+      }

+    }

+  }

+

+  // If no checks are needed, return early and add this attribute to indicate

+  // that subsequent CFGuard passes can skip this function.

+  if (IndirectCalls.empty()) {

+    F.addFnAttr(Attribute::NoCfCheck);

+    return false;

+  }

+

+  // For each indirect call/invoke, add the appropriate dispatch or check.

+  if (GuardMechanism == CF_Dispatch) {

+    for (CallBase *CB : IndirectCalls) {

+      insertCFGuardDispatch(CB);

+    }

+  } else {

+    for (CallBase *CB : IndirectCalls) {

+      insertCFGuardCheck(CB);

+    }

+  }

+

+  return true;

+}

+

+char CFGuard::ID = 0;

+INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false)

+

+FunctionPass *llvm::createCFGuardCheckPass() {

+  return new CFGuard(CFGuard::CF_Check);

+}

+

+FunctionPass *llvm::createCFGuardDispatchPass() {

+  return new CFGuard(CFGuard::CF_Dispatch);

+}
\ No newline at end of file
diff --git a/llvm/lib/Transforms/CFGuard/CMakeLists.txt b/llvm/lib/Transforms/CFGuard/CMakeLists.txt
new file mode 100644
index 0000000..65d3a0f
--- /dev/null
+++ b/llvm/lib/Transforms/CFGuard/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_llvm_library(LLVMCFGuard

+  CFGuard.cpp

+

+  ADDITIONAL_HEADER_DIRS

+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms

+

+  DEPENDS

+  intrinsics_gen

+  )

diff --git a/llvm/lib/Transforms/CFGuard/LLVMBuild.txt b/llvm/lib/Transforms/CFGuard/LLVMBuild.txt
new file mode 100644
index 0000000..d20cdb4
--- /dev/null
+++ b/llvm/lib/Transforms/CFGuard/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./lib/Transforms/CFGuard/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = CFGuard
+parent = Transforms
+required_libraries = Core Support
diff --git a/llvm/lib/Transforms/CMakeLists.txt b/llvm/lib/Transforms/CMakeLists.txt
index 74db9e5..dda5f6d 100644
--- a/llvm/lib/Transforms/CMakeLists.txt
+++ b/llvm/lib/Transforms/CMakeLists.txt
@@ -8,3 +8,4 @@
 add_subdirectory(Hello)
 add_subdirectory(ObjCARC)
 add_subdirectory(Coroutines)
+add_subdirectory(CFGuard)
diff --git a/llvm/lib/Transforms/LLVMBuild.txt b/llvm/lib/Transforms/LLVMBuild.txt
index 75c614f..5fb5efc 100644
--- a/llvm/lib/Transforms/LLVMBuild.txt
+++ b/llvm/lib/Transforms/LLVMBuild.txt
@@ -15,7 +15,7 @@
 ;===------------------------------------------------------------------------===;
 
 [common]
-subdirectories = AggressiveInstCombine Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC
+subdirectories = AggressiveInstCombine Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC CFGuard
 
 [component_0]
 type = Group