[llvm] r327767 - [X86] Added support for nocf_check attribute for indirect Branch Tracking

Oren Ben Simhon via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 17 06:29:47 PDT 2018


Author: orenb
Date: Sat Mar 17 06:29:46 2018
New Revision: 327767

URL: http://llvm.org/viewvc/llvm-project?rev=327767&view=rev
Log:
[X86] Added support for nocf_check attribute for indirect Branch Tracking

X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow Enforcement Technology (CET).
IBT instruments ENDBR instructions used to specify valid targets of indirect call / jmp.
TheĀ `nocf_check` attribute has two roles in the context of X86 IBT technology:
	1. Appertains to a function - do not add ENDBR instruction at the beginning of the function.
	2. Appertains to a function pointer - do not track the target function of this pointer by adding nocf_check prefix to the indirect-call instruction.

This patch implementsĀ `nocf_check` context for Indirect Branch Tracking.
It also auto generatesĀ `nocf_check` prefixes before indirect branchs to jump tables that are guarded by range checks.

Differential Revision: https://reviews.llvm.org/D41879

Added:
    llvm/trunk/test/CodeGen/X86/nocf_check.ll
Modified:
    llvm/trunk/bindings/go/llvm/ir_test.go
    llvm/trunk/docs/BitCodeFormat.rst
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/CodeGen/TargetLowering.h
    llvm/trunk/include/llvm/IR/Attributes.td
    llvm/trunk/include/llvm/IR/Function.h
    llvm/trunk/include/llvm/IR/Instructions.h
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/trunk/lib/IR/Attributes.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
    llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
    llvm/trunk/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
    llvm/trunk/lib/Target/X86/X86FastISel.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h
    llvm/trunk/lib/Target/X86/X86IndirectBranchTracking.cpp
    llvm/trunk/lib/Target/X86/X86InstrControl.td
    llvm/trunk/lib/Target/X86/X86InstrFormats.td
    llvm/trunk/lib/Target/X86/X86InstrInfo.td
    llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp
    llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
    llvm/trunk/test/CodeGen/X86/indirect-branch-tracking.ll
    llvm/trunk/test/MC/X86/x86-32-coverage.s
    llvm/trunk/utils/TableGen/X86FoldTablesEmitter.cpp

Modified: llvm/trunk/bindings/go/llvm/ir_test.go
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/go/llvm/ir_test.go?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/bindings/go/llvm/ir_test.go (original)
+++ llvm/trunk/bindings/go/llvm/ir_test.go Sat Mar 17 06:29:46 2018
@@ -89,6 +89,7 @@ func TestAttributes(t *testing.T) {
 		"uwtable",
 		"zeroext",
 		"cold",
+		"nocf_check"
 	}
 
 	for _, name := range attrTests {

Modified: llvm/trunk/docs/BitCodeFormat.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/docs/BitCodeFormat.rst (original)
+++ llvm/trunk/docs/BitCodeFormat.rst Sat Mar 17 06:29:46 2018
@@ -1054,6 +1054,7 @@ The integer codes are mapped to well-kno
 * code 53: ``speculatable``
 * code 54: ``strictfp``
 * code 55: ``sanitize_hwaddress``
+* code 56: ``nocf_check``
 
 .. note::
   The ``allocsize`` attribute has a special encoding for its arguments. Its two

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Sat Mar 17 06:29:46 2018
@@ -1699,6 +1699,12 @@ example:
     show that no exceptions passes by it. This is normally the case for
     the ELF x86-64 abi, but it can be disabled for some compilation
     units.
+``nocf_check``
+    This attribute indicates that no control-flow check will be perfomed on
+    the attributed entity. It disables -fcf-protection=<> for a specific
+    entity to fine grain the HW control flow protection mechanism. The flag
+    is target independant and currently appertains to a function or function
+    pointer.
 
 .. _glattrs:
 

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Sat Mar 17 06:29:46 2018
@@ -587,6 +587,7 @@ enum AttributeKindCodes {
   ATTR_KIND_SPECULATABLE = 53,
   ATTR_KIND_STRICT_FP = 54,
   ATTR_KIND_SANITIZE_HWADDRESS = 55,
+  ATTR_KIND_NOCF_CHECK = 56,
 };
 
 enum ComdatSelectionKindCodes {

Modified: llvm/trunk/include/llvm/CodeGen/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLowering.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h Sat Mar 17 06:29:46 2018
@@ -3584,6 +3584,13 @@ public:
   virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
                                           SelectionDAG &DAG) const;
 
+  /// Expands target specific indirect branch for the case of JumpTable
+  /// expanasion.
+  virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr,
+                                         SelectionDAG &DAG) const {
+    return DAG.getNode(ISD::BRIND, dl, MVT::Other, Value, Addr);
+  }
+
   // seteq(x, 0) -> truncate(srl(ctlz(zext(x)), log2(#bits)))
   // If we're comparing for equality to zero and isCtlzFast is true, expose the
   // fact that this can be implemented as a ctlz/srl pair, so that the dag

Modified: llvm/trunk/include/llvm/IR/Attributes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Sat Mar 17 06:29:46 2018
@@ -106,6 +106,9 @@ def NoRedZone : EnumAttr<"noredzone">;
 /// Mark the function as not returning.
 def NoReturn : EnumAttr<"noreturn">;
 
+/// Disable Indirect Branch Tracking.
+def NoCfCheck : EnumAttr<"nocf_check">;
+
 /// Function doesn't unwind stack.
 def NoUnwind : EnumAttr<"nounwind">;
 

Modified: llvm/trunk/include/llvm/IR/Function.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Function.h (original)
+++ llvm/trunk/include/llvm/IR/Function.h Sat Mar 17 06:29:46 2018
@@ -494,6 +494,9 @@ public:
     addFnAttr(Attribute::NoReturn);
   }
 
+  /// Determine if the function should not perform indirect branch tracking.
+  bool doesNoCfCheck() const { return hasFnAttribute(Attribute::NoCfCheck); }
+
   /// @brief Determine if the function cannot unwind.
   bool doesNotThrow() const {
     return hasFnAttribute(Attribute::NoUnwind);

Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Sat Mar 17 06:29:46 2018
@@ -1795,6 +1795,9 @@ public:
     addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
   }
 
+  /// Determine if the call should not perform indirect branch tracking.
+  bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); }
+
   /// Determine if the call cannot unwind.
   bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
   void setDoesNotThrow() {
@@ -3830,8 +3833,15 @@ public:
   static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles,
                             Instruction *InsertPt = nullptr);
 
+  /// Determine if the call should not perform indirect branch tracking.
+  bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); }
 
-
+  /// Determine if the call cannot unwind.
+  bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
+  void setDoesNotThrow() {
+    addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
+  }
+  
   /// Return the function called, or null if this is an
   /// indirect function invocation.
   ///

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Sat Mar 17 06:29:46 2018
@@ -648,6 +648,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(nonnull);
   KEYWORD(noredzone);
   KEYWORD(noreturn);
+  KEYWORD(nocf_check);
   KEYWORD(nounwind);
   KEYWORD(optnone);
   KEYWORD(optsize);

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Sat Mar 17 06:29:46 2018
@@ -1131,6 +1131,7 @@ bool LLParser::ParseFnAttributeValuePair
     case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break;
     case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break;
     case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break;
+    case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break;
     case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
     case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
     case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break;
@@ -1468,6 +1469,7 @@ bool LLParser::ParseOptionalParamAttrs(A
     case lltok::kw_nonlazybind:
     case lltok::kw_noredzone:
     case lltok::kw_noreturn:
+    case lltok::kw_nocf_check:
     case lltok::kw_nounwind:
     case lltok::kw_optnone:
     case lltok::kw_optsize:
@@ -1561,6 +1563,7 @@ bool LLParser::ParseOptionalReturnAttrs(
     case lltok::kw_nonlazybind:
     case lltok::kw_noredzone:
     case lltok::kw_noreturn:
+    case lltok::kw_nocf_check:
     case lltok::kw_nounwind:
     case lltok::kw_optnone:
     case lltok::kw_optsize:

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Sat Mar 17 06:29:46 2018
@@ -199,6 +199,7 @@ enum Kind {
   kw_nonnull,
   kw_noredzone,
   kw_noreturn,
+  kw_nocf_check,
   kw_nounwind,
   kw_optnone,
   kw_optsize,

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sat Mar 17 06:29:46 2018
@@ -1160,6 +1160,7 @@ static uint64_t getRawAttributeMask(Attr
   case Attribute::Speculatable:    return 1ULL << 54;
   case Attribute::StrictFP:        return 1ULL << 55;
   case Attribute::SanitizeHWAddress: return 1ULL << 56;
+  case Attribute::NoCfCheck:       return 1ULL << 57;
   case Attribute::Dereferenceable:
     llvm_unreachable("dereferenceable attribute not supported in raw format");
     break;
@@ -1338,6 +1339,8 @@ static Attribute::AttrKind getAttrFromCo
     return Attribute::NoRedZone;
   case bitc::ATTR_KIND_NO_RETURN:
     return Attribute::NoReturn;
+  case bitc::ATTR_KIND_NOCF_CHECK:
+    return Attribute::NoCfCheck;
   case bitc::ATTR_KIND_NO_UNWIND:
     return Attribute::NoUnwind;
   case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE:

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sat Mar 17 06:29:46 2018
@@ -638,6 +638,8 @@ static uint64_t getAttrKindEncoding(Attr
     return bitc::ATTR_KIND_NO_RED_ZONE;
   case Attribute::NoReturn:
     return bitc::ATTR_KIND_NO_RETURN;
+  case Attribute::NoCfCheck:
+    return bitc::ATTR_KIND_NOCF_CHECK;
   case Attribute::NoUnwind:
     return bitc::ATTR_KIND_NO_UNWIND;
   case Attribute::OptimizeForSize:

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Sat Mar 17 06:29:46 2018
@@ -3706,7 +3706,8 @@ bool SelectionDAGLegalize::ExpandNode(SD
       Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr,
                           TLI.getPICJumpTableRelocBase(Table, DAG));
     }
-    Tmp1 = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr);
+
+    Tmp1 = TLI.expandIndirectJTBranch(dl, LD.getValue(1), Addr, DAG);
     Results.push_back(Tmp1);
     break;
   }

Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Sat Mar 17 06:29:46 2018
@@ -299,6 +299,8 @@ std::string Attribute::getAsString(bool
     return "noredzone";
   if (hasAttribute(Attribute::NoReturn))
     return "noreturn";
+  if (hasAttribute(Attribute::NoCfCheck))
+    return "nocf_check";
   if (hasAttribute(Attribute::NoRecurse))
     return "norecurse";
   if (hasAttribute(Attribute::NoUnwind))

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Sat Mar 17 06:29:46 2018
@@ -1404,6 +1404,7 @@ Verifier::visitModuleFlag(const MDNode *
 static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
   switch (Kind) {
   case Attribute::NoReturn:
+  case Attribute::NoCfCheck:
   case Attribute::NoUnwind:
   case Attribute::NoInline:
   case Attribute::AlwaysInline:

Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Sat Mar 17 06:29:46 2018
@@ -2353,21 +2353,22 @@ bool X86AsmParser::ParseInstruction(Pars
                       .Cases("acquire", "release", isParsingIntelSyntax())
                       .Default(false);
 
-  auto isLockRepeatPrefix = [](StringRef N) {
+  auto isLockRepeatNtPrefix = [](StringRef N) {
     return StringSwitch<bool>(N)
-        .Cases("lock", "rep", "repe", "repz", "repne", "repnz", true)
+        .Cases("lock", "rep", "repe", "repz", "repne", "repnz", "notrack", true)
         .Default(false);
   };
 
   bool CurlyAsEndOfStatement = false;
 
   unsigned Flags = X86::IP_NO_PREFIX;
-  while (isLockRepeatPrefix(Name.lower())) {
+  while (isLockRepeatNtPrefix(Name.lower())) {
     unsigned Prefix =
         StringSwitch<unsigned>(Name)
             .Cases("lock", "lock", X86::IP_HAS_LOCK)
             .Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)
             .Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)
+            .Cases("notrack", "notrack", X86::IP_HAS_NOTRACK)
             .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
     Flags |= Prefix;
     if (getLexer().is(AsmToken::EndOfStatement)) {

Modified: llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp Sat Mar 17 06:29:46 2018
@@ -54,6 +54,9 @@ void X86ATTInstPrinter::printInst(const
   if ((TSFlags & X86II::LOCK) || (Flags & X86::IP_HAS_LOCK))
     OS << "\tlock\t";
 
+  if ((TSFlags & X86II::NOTRACK) || (Flags & X86::IP_HAS_NOTRACK))
+    OS << "\tnotrack\t";
+
   if (Flags & X86::IP_HAS_REPEAT_NE)
     OS << "\trepne\t";
   else if (Flags & X86::IP_HAS_REPEAT)

Modified: llvm/trunk/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp Sat Mar 17 06:29:46 2018
@@ -49,6 +49,9 @@ void X86IntelInstPrinter::printInst(cons
   else if (Flags & X86::IP_HAS_REPEAT)
     OS << "\trep\t";
 
+  if ((TSFlags & X86II::NOTRACK) || (Flags & X86::IP_HAS_NOTRACK))
+    OS << "\tnotrack\t";
+
   printInstruction(MI, OS);
 
   // Next always print the annotation.

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86BaseInfo.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86BaseInfo.h (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86BaseInfo.h Sat Mar 17 06:29:46 2018
@@ -60,8 +60,9 @@ namespace X86 {
     IP_HAS_REPEAT_NE = 4,
     IP_HAS_REPEAT = 8,
     IP_HAS_LOCK = 16,
-    NO_SCHED_INFO = 32 // Don't add sched comment to the current instr because
-                       // it was already added
+    NO_SCHED_INFO = 32, // Don't add sched comment to the current instr because
+                        // it was already added
+    IP_HAS_NOTRACK = 64
   };
 } // end namespace X86;
 
@@ -572,7 +573,11 @@ namespace X86II {
 
     /// Explicitly specified rounding control
     EVEX_RCShift = Has3DNow0F0FOpcodeShift + 1,
-    EVEX_RC = 1ULL << EVEX_RCShift
+    EVEX_RC = 1ULL << EVEX_RCShift,
+
+    // NOTRACK prefix
+    NoTrackShift = EVEX_RCShift + 1,
+    NOTRACK = 1ULL << NoTrackShift
   };
 
   // getBaseOpcodeFor - This function returns the "base" X86 opcode for the

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Sat Mar 17 06:29:46 2018
@@ -1134,6 +1134,10 @@ bool X86MCCodeEmitter::emitOpcodePrefix(
   if (TSFlags & X86II::LOCK || MI.getFlags() & X86::IP_HAS_LOCK)
     EmitByte(0xF0, CurByte, OS);
 
+  // Emit the NOTRACK opcode prefix.
+  if (TSFlags & X86II::NOTRACK || MI.getFlags() & X86::IP_HAS_NOTRACK)
+    EmitByte(0x3E, CurByte, OS);
+
   switch (TSFlags & X86II::OpPrefixMask) {
   case X86II::PD:   // 66
     EmitByte(0x66, CurByte, OS);

Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Sat Mar 17 06:29:46 2018
@@ -3174,6 +3174,13 @@ bool X86FastISel::fastLowerCall(CallLowe
       CLI.CS ? dyn_cast<CallInst>(CLI.CS->getInstruction()) : nullptr;
   const Function *CalledFn = CI ? CI->getCalledFunction() : nullptr;
 
+  // Call / invoke instructions with NoCfCheck attribute require special
+  // handling.
+  const auto *II =
+      CLI.CS ? dyn_cast<InvokeInst>(CLI.CS->getInstruction()) : nullptr;
+  if ((CI && CI->doesNoCfCheck()) || (II && II->doesNoCfCheck()))
+    return false;
+
   // Functions with no_caller_saved_registers that need special handling.
   if ((CI && CI->hasFnAttr("no_caller_saved_registers")) ||
       (CalledFn && CalledFn->hasFnAttribute("no_caller_saved_registers")))

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Sat Mar 17 06:29:46 2018
@@ -3415,6 +3415,11 @@ X86TargetLowering::LowerCall(TargetLower
   const Function *Fn = CI ? CI->getCalledFunction() : nullptr;
   bool HasNCSR = (CI && CI->hasFnAttr("no_caller_saved_registers")) ||
                  (Fn && Fn->hasFnAttribute("no_caller_saved_registers"));
+  const auto *II = dyn_cast_or_null<InvokeInst>(CLI.CS.getInstruction());
+  bool HasNoCfCheck =
+      (CI && CI->doesNoCfCheck()) || (II && II->doesNoCfCheck());
+  const Module *M = MF.getMMI().getModule();
+  Metadata *IsCFProtectionSupported = M->getModuleFlag("cf-protection-branch");
 
   if (CallConv == CallingConv::X86_INTR)
     report_fatal_error("X86 interrupts may not be called directly");
@@ -3898,7 +3903,11 @@ X86TargetLowering::LowerCall(TargetLower
     return DAG.getNode(X86ISD::TC_RETURN, dl, NodeTys, Ops);
   }
 
-  Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops);
+  if (HasNoCfCheck && IsCFProtectionSupported) {
+    Chain = DAG.getNode(X86ISD::NT_CALL, dl, NodeTys, Ops);
+  } else {
+    Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops);
+  }
   InFlag = Chain.getValue(1);
 
   // Create the CALLSEQ_END node.
@@ -25852,6 +25861,8 @@ const char *X86TargetLowering::getTarget
   case X86ISD::GF2P8MULB:          return "X86ISD::GF2P8MULB";
   case X86ISD::GF2P8AFFINEQB:      return "X86ISD::GF2P8AFFINEQB";
   case X86ISD::GF2P8AFFINEINVQB:   return "X86ISD::GF2P8AFFINEINVQB";
+  case X86ISD::NT_CALL:            return "X86ISD::NT_CALL";
+  case X86ISD::NT_BRIND:           return "X86ISD::NT_BRIND";
   }
   return nullptr;
 }
@@ -38709,6 +38720,22 @@ void X86TargetLowering::finalizeLowering
   TargetLoweringBase::finalizeLowering(MF);
 }
 
+SDValue X86TargetLowering::expandIndirectJTBranch(const SDLoc& dl, 
+                                                  SDValue Value, SDValue Addr,
+                                                  SelectionDAG &DAG) const {
+  const Module *M = DAG.getMachineFunction().getMMI().getModule();
+  Metadata *IsCFProtectionSupported = M->getModuleFlag("cf-protection-branch");
+  if (IsCFProtectionSupported) {
+    // In case control-flow branch protection is enabled, we need to add
+    // notrack prefix to the indirect branch.
+    // In order to do that we create NT_BRIND SDNode.
+    // Upon ISEL, the pattern will convert it to jmp with NoTrack prefix.
+    return DAG.getNode(X86ISD::NT_BRIND, dl, MVT::Other, Value, Addr);
+  }
+
+  return TargetLowering::expandIndirectJTBranch(dl, Value, Addr, DAG);
+}
+
 /// This method query the target whether it is beneficial for dag combiner to
 /// promote the specified node. If true, it should return the desired promotion
 /// type by reference.

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Sat Mar 17 06:29:46 2018
@@ -75,6 +75,9 @@ namespace llvm {
       ///
       CALL,
 
+      /// Same as call except it adds the NoTrack prefix.
+      NT_CALL,
+
       /// This operation implements the lowering for readcyclecounter.
       RDTSC_DAG,
 
@@ -122,6 +125,10 @@ namespace llvm {
       /// or TEST instruction.
       BRCOND,
 
+      /// BRIND node with NoTrack prefix. Operand 0 is the chain operand and
+      /// operand 1 is the target address.
+      NT_BRIND,
+
       /// Return with a flag operand. Operand 0 is the chain operand, operand
       /// 1 is the number of bytes of stack to pop.
       RET_FLAG,
@@ -1114,9 +1121,12 @@ namespace llvm {
     bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI,
                                unsigned Factor) const override;
 
-
     void finalizeLowering(MachineFunction &MF) const override;
 
+    SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, 
+                                   SDValue Addr, SelectionDAG &DAG) 
+                                   const override;
+
   protected:
     std::pair<const TargetRegisterClass *, uint8_t>
     findRepresentativeClass(const TargetRegisterInfo *TRI,

Modified: llvm/trunk/lib/Target/X86/X86IndirectBranchTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86IndirectBranchTracking.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86IndirectBranchTracking.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86IndirectBranchTracking.cpp Sat Mar 17 06:29:46 2018
@@ -22,7 +22,6 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 
 using namespace llvm;
@@ -58,7 +57,8 @@ private:
   /// Adds a new ENDBR instruction to the begining of the MBB.
   /// The function will not add it if already exists.
   /// It will add ENDBR32 or ENDBR64 opcode, depending on the target.
-  void addENDBR(MachineBasicBlock &MBB) const;
+  /// \returns true if the ENDBR was added and false otherwise.
+  bool addENDBR(MachineBasicBlock &MBB) const;
 };
 
 } // end anonymous namespace
@@ -69,7 +69,7 @@ FunctionPass *llvm::createX86IndirectBra
   return new X86IndirectBranchTrackingPass();
 }
 
-void X86IndirectBranchTrackingPass::addENDBR(MachineBasicBlock &MBB) const {
+bool X86IndirectBranchTrackingPass::addENDBR(MachineBasicBlock &MBB) const {
   assert(TII && "Target instruction info was not initialized");
   assert((X86::ENDBR64 == EndbrOpcode || X86::ENDBR32 == EndbrOpcode) &&
          "Unexpected Endbr opcode");
@@ -80,13 +80,16 @@ void X86IndirectBranchTrackingPass::addE
   if (MI == MBB.end() || EndbrOpcode != MI->getOpcode()) {
     BuildMI(MBB, MI, MBB.findDebugLoc(MI), TII->get(EndbrOpcode));
     NumEndBranchAdded++;
+    return true;
   }
+
+  return false;
 }
 
 bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
   const X86Subtarget &SubTarget = MF.getSubtarget<X86Subtarget>();
 
-  // Make sure that the target supports ENDBR instruction.
+  // Make sure that the target supports IBT instruction.
   if (!SubTarget.hasIBT())
     return false;
 
@@ -103,50 +106,20 @@ bool X86IndirectBranchTrackingPass::runO
   EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32;
 
   // Non-internal function or function whose address was taken, can be
-  // invoked through indirect calls. Mark the first BB with ENDBR instruction.
-  // TODO: Do not add ENDBR instruction in case notrack attribute is used.
-  if (MF.getFunction().hasAddressTaken() ||
-      !MF.getFunction().hasLocalLinkage()) {
+  // accessed through indirect calls. Mark the first BB with ENDBR instruction
+  // unless nocf_check attribute is used.
+  if ((MF.getFunction().hasAddressTaken() ||
+       !MF.getFunction().hasLocalLinkage()) &&
+      !MF.getFunction().doesNoCfCheck()) {
     auto MBB = MF.begin();
-    addENDBR(*MBB);
-    Changed = true;
+    Changed |= addENDBR(*MBB);
   }
 
-  for (auto &MBB : MF) {
-    // Find all basic blocks that thier address was taken (for example
+  for (auto &MBB : MF)
+    // Find all basic blocks that their address was taken (for example
     // in the case of indirect jump) and add ENDBR instruction.
-    if (MBB.hasAddressTaken()) {
-      addENDBR(MBB);
-      Changed = true;
-    }
-  }
-
-  // Adds ENDBR instructions to MBB destinations of the jump table.
-  // TODO: In case of more than 50 destinations, do not add ENDBR and
-  // instead add DS_PREFIX.
-  if (MachineJumpTableInfo *JTI = MF.getJumpTableInfo()) {
-    for (const auto &JT : JTI->getJumpTables()) {
-      for (auto *MBB : JT.MBBs) {
-	// This assert verifies the assumption that this MBB has an indirect
-	// jump terminator in one of its predecessor.
-	// Jump tables are generated when lowering switch-case statements or
-	// setjmp/longjump functions. As a result only indirect jumps use jump
-	// tables.
-        #ifndef NDEBUG
-        bool hasIndirectJumpTerm = false;
-        for (auto &PredMBB : MBB->predecessors())
-          for (auto &TermI : PredMBB->terminators())
-            if (TermI.isIndirectBranch())
-              hasIndirectJumpTerm = true;
-        assert(hasIndirectJumpTerm &&
-               "The MBB is not the destination of an indirect jump");
-	(void)hasIndirectJumpTerm;
-	#endif
-        addENDBR(*MBB);
-        Changed = true;
-      }
-    }
-  }
+    if (MBB.hasAddressTaken())
+      Changed |= addENDBR(MBB);
 
   return Changed;
 }

Modified: llvm/trunk/lib/Target/X86/X86InstrControl.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrControl.td?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrControl.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrControl.td Sat Mar 17 06:29:46 2018
@@ -153,6 +153,30 @@ let isBranch = 1, isTerminator = 1, isBa
                      [(brind (loadi64 addr:$dst))], IIC_JMP_MEM>,
                    Requires<[In64BitMode]>, Sched<[WriteJumpLd]>;
 
+  let isCodeGenOnly = 1, Predicates = [HasIBT] in {
+    def JMP16r_NT : I<0xFF, MRM4r, (outs), (ins GR16 : $dst), "jmp{w}\t{*}$dst",
+                   [(X86NoTrackBrind GR16 : $dst)], IIC_JMP_REG>, Requires<[Not64BitMode]>,
+                 OpSize16, Sched<[WriteJump]>, NOTRACK;
+
+    def JMP16m_NT : I<0xFF, MRM4m, (outs), (ins i16mem : $dst), "jmp{w}\t{*}$dst",
+                   [(X86NoTrackBrind (loadi16 addr : $dst))], IIC_JMP_MEM>,
+                 Requires<[Not64BitMode]>, OpSize16, Sched<[WriteJumpLd]>, NOTRACK;
+
+    def JMP32r_NT : I<0xFF, MRM4r, (outs), (ins GR32 : $dst), "jmp{l}\t{*}$dst",
+                   [(X86NoTrackBrind GR32 : $dst)], IIC_JMP_REG>, Requires<[Not64BitMode]>,
+                 OpSize32, Sched<[WriteJump]>, NOTRACK;
+    def JMP32m_NT : I<0xFF, MRM4m, (outs), (ins i32mem : $dst), "jmp{l}\t{*}$dst",
+                   [(X86NoTrackBrind (loadi32 addr : $dst))], IIC_JMP_MEM>,
+                 Requires<[Not64BitMode]>, OpSize32, Sched<[WriteJumpLd]>, NOTRACK;
+
+    def JMP64r_NT : I<0xFF, MRM4r, (outs), (ins GR64 : $dst), "jmp{q}\t{*}$dst",
+                      [(X86NoTrackBrind GR64 : $dst)], IIC_JMP_REG>, Requires<[In64BitMode]>,
+                    Sched<[WriteJump]>, NOTRACK;
+    def JMP64m_NT : I<0xFF, MRM4m, (outs), (ins i64mem : $dst), "jmp{q}\t{*}$dst",
+                      [(X86NoTrackBrind(loadi64 addr : $dst))], IIC_JMP_MEM>,
+                    Requires<[In64BitMode]>, Sched<[WriteJumpLd]>, NOTRACK;
+  }
+
   let Predicates = [Not64BitMode] in {
     def FARJMP16i  : Iseg16<0xEA, RawFrmImm16, (outs),
                             (ins i16imm:$off, i16imm:$seg),
@@ -175,7 +199,6 @@ let isBranch = 1, isTerminator = 1, isBa
                    Sched<[WriteJumpLd]>;
 }
 
-
 // Loop instructions
 let SchedRW = [WriteJump] in {
 def LOOP   : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", [], IIC_LOOP>;
@@ -219,6 +242,25 @@ let isCall = 1 in
                       Requires<[Not64BitMode,FavorMemIndirectCall,NotUseRetpoline]>,
                       Sched<[WriteJumpLd]>;
 
+    let isCodeGenOnly = 1, Predicates = [HasIBT] in {
+      def CALL16r_NT : I<0xFF, MRM2r, (outs), (ins GR16 : $dst),
+                        "call{w}\t{*}$dst",[(X86NoTrackCall GR16 : $dst)], IIC_CALL_RI>,
+                        OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK;
+      def CALL16m_NT : I<0xFF, MRM2m, (outs), (ins i16mem : $dst),
+                        "call{w}\t{*}$dst",[(X86NoTrackCall(loadi16 addr : $dst))],
+                        IIC_CALL_MEM>, OpSize16,
+                        Requires<[Not64BitMode,FavorMemIndirectCall]>,
+                        Sched<[WriteJumpLd]>, NOTRACK;
+      def CALL32r_NT : I<0xFF, MRM2r, (outs), (ins GR32 : $dst),
+                        "call{l}\t{*}$dst",[(X86NoTrackCall GR32 : $dst)], IIC_CALL_RI>,
+                        OpSize32, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK;
+      def CALL32m_NT : I<0xFF, MRM2m, (outs), (ins i32mem : $dst),
+                        "call{l}\t{*}$dst",[(X86NoTrackCall(loadi32 addr : $dst))],
+                        IIC_CALL_MEM>, OpSize32,
+                        Requires<[Not64BitMode,FavorMemIndirectCall]>,
+                        Sched<[WriteJumpLd]>, NOTRACK;
+    }
+
     let Predicates = [Not64BitMode] in {
       def FARCALL16i  : Iseg16<0x9A, RawFrmImm16, (outs),
                                (ins i16imm:$off, i16imm:$seg),
@@ -306,6 +348,17 @@ let isCall = 1, Uses = [RSP, SSP], Sched
                       Requires<[In64BitMode,FavorMemIndirectCall,
                                 NotUseRetpoline]>;
 
+  let isCodeGenOnly = 1, Predicates = [HasIBT] in{
+    def CALL64r_NT : I<0xFF, MRM2r, (outs), (ins GR64 : $dst),
+                      "call{q}\t{*}$dst",[(X86NoTrackCall GR64 : $dst)],
+                      IIC_CALL_RI>,
+                      Requires<[In64BitMode]>, NOTRACK;
+    def CALL64m_NT : I<0xFF, MRM2m, (outs), (ins i64mem : $dst),
+                       "call{q}\t{*}$dst",[(X86NoTrackCall(loadi64 addr : $dst))],
+                       IIC_CALL_MEM>,
+                      Requires<[In64BitMode,FavorMemIndirectCall]>, NOTRACK;
+  }
+
   def FARCALL64   : RI<0xFF, MRM3m, (outs), (ins opaque80mem:$dst),
                        "lcall{q}\t{*}$dst", [], IIC_CALL_FAR_MEM>;
 }

Modified: llvm/trunk/lib/Target/X86/X86InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFormats.td?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrFormats.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrFormats.td Sat Mar 17 06:29:46 2018
@@ -215,6 +215,7 @@ class EVEX_RC { bit hasEVEX_RC = 1; }
 class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; }
 class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; }
 class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; }
+class NOTRACK { bit hasNoTrackPrefix = 1; }
 
 // Specify AVX512 8-bit compressed displacement encoding based on the vector
 // element size in bits (8, 16, 32, 64) and the CDisp8 form.
@@ -296,6 +297,7 @@ class X86Inst<bits<8> opcod, Format f, I
   int CD8_EltSize = 0;      // Compressed disp8 form - element-size in bytes.
   bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding?
   bit hasEVEX_RC = 0;       // Explicitly specified rounding control in FP instruction.
+  bit hasNoTrackPrefix = 0; // Does this inst has 0x3E (NoTrack) prefix?
 
   bits<2> EVEX_LL;
   let EVEX_LL{0} = hasVEX_L;
@@ -347,6 +349,7 @@ class X86Inst<bits<8> opcod, Format f, I
   let TSFlags{52-46} = CD8_Scale;
   let TSFlags{53}    = has3DNow0F0FOpcode;
   let TSFlags{54}    = hasEVEX_RC;
+  let TSFlags{55}    = hasNoTrackPrefix;
 }
 
 class PseudoI<dag oops, dag iops, list<dag> pattern,

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Sat Mar 17 06:29:46 2018
@@ -94,6 +94,8 @@ def SDT_X86CallSeqEnd   : SDCallSeqEnd<[
 
 def SDT_X86Call   : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
 
+def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+
 def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>,
                                                          SDTCisVT<1, iPTR>,
                                                          SDTCisVT<2, iPTR>]>;
@@ -196,6 +198,12 @@ def X86call    : SDNode<"X86ISD::CALL",
                         [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,
                          SDNPVariadic]>;
 
+def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call,
+                            [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, 
+                             SDNPVariadic]>;
+def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, 
+                             [SDNPHasChain]>;
+
 def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr,
                         [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>;
 def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr,

Modified: llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp Sat Mar 17 06:29:46 2018
@@ -42,6 +42,7 @@ static Attribute::AttrKind parseAttrKind
       .Case("nonlazybind", Attribute::NonLazyBind)
       .Case("noredzone", Attribute::NoRedZone)
       .Case("noreturn", Attribute::NoReturn)
+      .Case("nocf_check", Attribute::NoCfCheck)
       .Case("norecurse", Attribute::NoRecurse)
       .Case("nounwind", Attribute::NoUnwind)
       .Case("optnone", Attribute::OptimizeNone)

Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Sat Mar 17 06:29:46 2018
@@ -696,6 +696,7 @@ Function *CodeExtractor::constructFuncti
       case Attribute::StackProtectStrong:
       case Attribute::StrictFP:
       case Attribute::UWTable:
+      case Attribute::NoCfCheck:
         break;
       }
 

Modified: llvm/trunk/test/CodeGen/X86/indirect-branch-tracking.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/indirect-branch-tracking.ll?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/indirect-branch-tracking.ll (original)
+++ llvm/trunk/test/CodeGen/X86/indirect-branch-tracking.ll Sat Mar 17 06:29:46 2018
@@ -1,10 +1,11 @@
-; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+ibt -x86-indirect-branch-tracking < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86_64
-; RUN: llc -mtriple=i386-unknown-unknown -mattr=+ibt -x86-indirect-branch-tracking < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86
+; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+ibt < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86_64
+; RUN: llc -mtriple=i386-unknown-unknown -mattr=+ibt < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86
+; RUN: llc -mtriple i386-windows-gnu -mattr=+ibt -exception-model sjlj < %s | FileCheck %s --check-prefix=SJLJ
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Test1
 ;; -----
-;; Checks ENDBR insertion in case of indirect branch IR instruction.
+;; Checks ENDBR insertion in case of switch case statement.
 ;; Also since the function is not internal, make sure that endbr32/64 was 
 ;; added at the beginning of the function.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -34,7 +35,8 @@ bb6:
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Test2
 ;; -----
-;; Checks ENDBR insertion in case of switch case statement.
+;; Checks NOTRACK insertion in case of switch case statement.
+;; Check that there is no ENDBR insertion in the following case statements.
 ;; Also since the function is not internal, ENDBR instruction should be
 ;; added to its first basic block.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -43,25 +45,9 @@ define i32 @test2(i32 %a) {
 ; ALL-LABEL:   test2
 ; X86_64:      endbr64
 ; X86:         endbr32
-; ALL:         jmp{{q|l}} *
-; ALL:         .LBB1_2:
-; X86_64-NEXT: endbr64
-; X86-NEXT:    endbr32
-; ALL:         .LBB1_7:
+; ALL:         notrack jmp{{q|l}} *
 ; X86_64-NOT:      endbr64
 ; X86-NOT:         endbr32
-; ALL:         .LBB1_3:
-; X86_64-NEXT: endbr64
-; X86-NEXT:    endbr32
-; ALL:         .LBB1_4:
-; X86_64-NEXT: endbr64
-; X86-NEXT:    endbr32
-; ALL:         .LBB1_5:
-; X86_64-NEXT: endbr64
-; X86-NEXT:    endbr32
-; ALL:         .LBB1_6:
-; X86_64-NEXT: endbr64
-; X86-NEXT:    endbr32
 entry:
   %retval = alloca i32, align 4
   %a.addr = alloca i32, align 4
@@ -198,3 +184,38 @@ define i32 @test7() {
 ; X86:         endbr32
   ret i32 1
 }
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Test8
+;; -----
+;; Checks that NO TRACK prefix is not added for indirect jumps to a jump-
+;; table that was created for SJLJ dispatch.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare void @_Z20function_that_throwsv()
+declare i32 @__gxx_personality_sj0(...)
+declare i8* @__cxa_begin_catch(i8*)
+declare void @__cxa_end_catch()
+
+define void @test8() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+;SJLJ-LABEL:    test8
+;SJLJ-NOT:      ds
+entry:
+  invoke void @_Z20function_that_throwsv()
+          to label %try.cont unwind label %lpad
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          catch i8* null
+  %1 = extractvalue { i8*, i32 } %0, 0
+  %2 = tail call i8* @__cxa_begin_catch(i8* %1)
+  tail call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"cf-protection-branch", i32 1}
\ No newline at end of file

Added: llvm/trunk/test/CodeGen/X86/nocf_check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/nocf_check.ll?rev=327767&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/nocf_check.ll (added)
+++ llvm/trunk/test/CodeGen/X86/nocf_check.ll Sat Mar 17 06:29:46 2018
@@ -0,0 +1,46 @@
+; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+ibt -x86-indirect-branch-tracking < %s | FileCheck %s
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; This test verify the handling of ''nocf_check'' attribute by the backend. ;;
+;; The file was generated using the following C code:                        ;;
+;;                                                                           ;;
+;; void __attribute__((nocf_check)) NoCfCheckFunc(void) {}                   ;;
+;;                                                                           ;;
+;; typedef void(*FuncPointer)(void);                                         ;;
+;; void NoCfCheckCall(FuncPointer f) {                                       ;;
+;;   __attribute__((nocf_check)) FuncPointer p = f;                          ;;
+;;   (*p)();                                                                 ;;
+;; }                                                                         ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Make sure that a function with ''nocf_check'' attribute is not instrumented
+; with endbr instruction at the beginning.
+define void @NoCfCheckFunc() #0 {
+; CHECK-LABEL: NoCfCheckFunc
+; CHECK-NOT:   endbr64
+; CHECK:       retq
+entry:
+  ret void
+}
+
+; Make sure that notrack prefix is added before a call with ''nocf_check'' attribute.
+define void @NoCfCheckCall(void ()* %f) {
+; CHECK-LABEL: NoCfCheckCall
+; CHECK:       notrack call
+entry:
+  %f.addr = alloca void ()*, align 4
+  %p = alloca void ()*, align 4
+  store void ()* %f, void ()** %f.addr, align 4
+  %0 = load void ()*, void ()** %f.addr, align 4
+  store void ()* %0, void ()** %p, align 4
+  %1 = load void ()*, void ()** %p, align 4
+  call void %1() #1
+  ret void
+}
+
+attributes #0 = { noinline nocf_check nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nocf_check }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"cf-protection-branch", i32 1}

Modified: llvm/trunk/test/MC/X86/x86-32-coverage.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86-32-coverage.s?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/test/MC/X86/x86-32-coverage.s (original)
+++ llvm/trunk/test/MC/X86/x86-32-coverage.s Sat Mar 17 06:29:46 2018
@@ -1655,10 +1655,18 @@
 // CHECK:  encoding: [0xff,0xd1]
         	call	*%ecx
 
+// CHECK: notrack	calll	*%ecx
+// CHECK:  encoding: [0x3e,0xff,0xd1]
+            notrack	call	*%ecx
+
 // CHECK: calll	*3735928559(%ebx,%ecx,8)
 // CHECK:  encoding: [0xff,0x94,0xcb,0xef,0xbe,0xad,0xde]
         	call	*0xdeadbeef(%ebx,%ecx,8)
 
+// CHECK: notrack	calll	*3735928559(%ebx,%ecx,8)
+// CHECK:  encoding: [0x3e,0xff,0x94,0xcb,0xef,0xbe,0xad,0xde]
+            notrack	call	*0xdeadbeef(%ebx,%ecx,8)
+
 // CHECK: calll	*3135175374
 // CHECK:  encoding: [0xff,0x15,0xce,0xfa,0xde,0xba]
         	call	*0xbadeface
@@ -1687,6 +1695,10 @@
 // CHECK:  encoding: [0xff,0xa4,0xcb,0xef,0xbe,0xad,0xde]
         	jmp	*0xdeadbeef(%ebx,%ecx,8)
 
+// CHECK: notrack	jmpl	*3735928559(%ebx,%ecx,8)
+// CHECK:  encoding: [0x3e,0xff,0xa4,0xcb,0xef,0xbe,0xad,0xde]
+             notrack	jmp	*0xdeadbeef(%ebx,%ecx,8)
+
 // CHECK: jmpl	*3135175374
 // CHECK:  encoding: [0xff,0x25,0xce,0xfa,0xde,0xba]
         	jmp	*0xbadeface

Modified: llvm/trunk/utils/TableGen/X86FoldTablesEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/X86FoldTablesEmitter.cpp?rev=327767&r1=327766&r2=327767&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/X86FoldTablesEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/X86FoldTablesEmitter.cpp Sat Mar 17 06:29:46 2018
@@ -350,6 +350,8 @@ public:
             MemRec->getValueAsBit("hasREX_WPrefix") ||
         RegRec->getValueAsBit("hasLockPrefix") !=
             MemRec->getValueAsBit("hasLockPrefix") ||
+        RegRec->getValueAsBit("hasNoTrackPrefix") !=
+            MemRec->getValueAsBit("hasNoTrackPrefix") ||
         !equalBitsInits(RegRec->getValueAsBitsInit("EVEX_LL"),
                         MemRec->getValueAsBitsInit("EVEX_LL")) ||
         !equalBitsInits(RegRec->getValueAsBitsInit("VEX_WPrefix"),




More information about the llvm-commits mailing list