[llvm] r221708 - Add Forward Control-Flow Integrity.

Tom Roeder tmroeder at google.com
Tue Nov 11 13:08:03 PST 2014


Author: tmroeder
Date: Tue Nov 11 15:08:02 2014
New Revision: 221708

URL: http://llvm.org/viewvc/llvm-project?rev=221708&view=rev
Log:
Add Forward Control-Flow Integrity.

This commit adds a new pass that can inject checks before indirect calls to
make sure that these calls target known locations. It supports three types of
checks and, at compile time, it can take the name of a custom function to call
when an indirect call check fails. The default failure function ignores the
error and continues.

This pass incidentally moves the function JumpInstrTables::transformType from
private to public and makes it static (with a new argument that specifies the
table type to use); this is so that the CFI code can transform function types
at call sites to determine which jump-instruction table to use for the check at
that site.

Also, this removes support for jumptables in ARM, pending further performance
analysis and discussion.

Review: http://reviews.llvm.org/D4167


Added:
    llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
    llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp
    llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll
    llvm/trunk/test/CodeGen/X86/cfi_invoke.ll
    llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll
    llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll
    llvm/trunk/test/CodeGen/X86/jump_table_align.ll
Removed:
    llvm/trunk/test/CodeGen/ARM/jump_tables.ll
Modified:
    llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
    llvm/trunk/include/llvm/CodeGen/CommandFlags.h
    llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
    llvm/trunk/include/llvm/CodeGen/Passes.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/include/llvm/Target/TargetInstrInfo.h
    llvm/trunk/include/llvm/Target/TargetOptions.h
    llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/CodeGen/CMakeLists.txt
    llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
    llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
    llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
    llvm/trunk/lib/Target/X86/X86InstrInfo.h
    llvm/trunk/test/CodeGen/X86/jump_table_alias.ll
    llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll
    llvm/trunk/test/CodeGen/X86/jump_tables.ll
    llvm/trunk/test/LTO/jump-table-type.ll

Modified: llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h Tue Nov 11 15:08:02 2014
@@ -37,7 +37,9 @@ class JumpInstrTableInfo : public Immuta
 public:
   static char ID;
 
-  JumpInstrTableInfo();
+  /// The default byte alignment for jump tables is 16, which is large but
+  /// usually safe.
+  JumpInstrTableInfo(uint64_t ByteAlign = 16);
   virtual ~JumpInstrTableInfo();
   const char *getPassName() const override {
     return "Jump-Instruction Table Info";
@@ -52,9 +54,19 @@ public:
   /// Gets the tables.
   const JumpTables &getTables() const { return Tables; }
 
+  /// Gets the alignment in bytes of a jumptable entry.
+  uint64_t entryByteAlignment() const { return ByteAlignment; }
 private:
   JumpTables Tables;
+
+  /// A power-of-two alignment of a jumptable entry.
+  uint64_t ByteAlignment;
 };
+
+/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This
+/// bound specifies the maximum number of bytes needed to represent an
+/// unconditional jump or a trap instruction in the back end currently in use.
+ModulePass *createJumpInstrTableInfoPass(unsigned Bound);
 }
 
 #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */

Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)
+++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Tue Nov 11 15:08:02 2014
@@ -222,6 +222,44 @@ JTableType("jump-table-type",
                          "Create one table per unique function type."),
               clEnumValEnd));
 
+cl::opt<bool>
+FCFI("fcfi",
+     cl::desc("Apply forward-edge control-flow integrity"),
+     cl::init(false));
+
+cl::opt<llvm::CFIntegrity>
+CFIType("cfi-type",
+        cl::desc("Choose the type of Control-Flow Integrity check to add"),
+        cl::init(CFIntegrity::Sub),
+        cl::values(
+            clEnumValN(CFIntegrity::Sub, "sub",
+                       "Subtract the pointer from the table base, then mask."),
+            clEnumValN(CFIntegrity::Ror, "ror",
+                       "Use rotate to check the offset from a table base."),
+            clEnumValN(CFIntegrity::Add, "add",
+                       "Mask out the high bits and add to an aligned base."),
+            clEnumValEnd));
+
+cl::opt<bool>
+CFIEnforcing("cfi-enforcing",
+             cl::desc("Enforce CFI or pass the violation to a function."),
+             cl::init(false));
+
+// Note that this option is linked to the cfi-enforcing option above: if
+// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If
+// cfi-enforcing is false and no cfi-func-name is set, then a default function
+// will be generated that ignores all CFI violations. The expected signature for
+// functions called with CFI violations is
+//
+// void (i8*, i8*)
+//
+// The first pointer is a C string containing the name of the function in which
+// the violation occurs, and the second pointer is the pointer that violated
+// CFI.
+cl::opt<std::string>
+CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"),
+            cl::init(""));
+
 // Common utility function tightly tied to the options listed here. Initializes
 // a TargetOptions object with CodeGen flags and returns it.
 static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
@@ -249,6 +287,10 @@ static inline TargetOptions InitTargetOp
 
   Options.MCOptions = InitMCTargetOptionsFromFlags();
   Options.JTType = JTableType;
+  Options.FCFI = FCFI;
+  Options.CFIType = CFIType;
+  Options.CFIEnforcing = CFIEnforcing;
+  Options.CFIFuncName = CFIFuncName;
 
   Options.ThreadModel = TMModel;
 

Added: llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h?rev=221708&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h (added)
+++ llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h Tue Nov 11 15:08:02 2014
@@ -0,0 +1,123 @@
+//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass instruments indirect calls with checks to ensure that these calls
+// pass through the appropriate jump-instruction table generated by
+// JumpInstrTables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
+#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Pass.h"
+#include "llvm/Target/TargetOptions.h"
+
+#include <string>
+
+namespace llvm {
+
+class AnalysisUsage;
+class BasicBlock;
+class Constant;
+class Function;
+class Instruction;
+class Module;
+class Value;
+
+/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to
+/// prepend checks to indirect calls to make sure that these calls target valid
+/// locations.
+class ForwardControlFlowIntegrity : public ModulePass {
+public:
+  static char ID;
+
+  ForwardControlFlowIntegrity();
+  ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT,
+                              CFIntegrity CFIType,
+                              bool CFIEnforcing, std::string CFIFuncName);
+  virtual ~ForwardControlFlowIntegrity() override;
+
+  /// Runs the CFI pass on a given module. This works best if the module in
+  /// question is the result of link-time optimization (see lib/LTO).
+  bool runOnModule(Module &M) override;
+  const char *getPassName() const override {
+    return "Forward Control-Flow Integrity";
+  }
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+private:
+  typedef SmallVector<Instruction *, 64> CallSet;
+
+  /// A structure that is used to keep track of constant table information.
+  struct CFIConstants {
+    Constant *StartValue;
+    Constant *MaskValue;
+    Constant *Size;
+  };
+
+  /// A map from function type to the base of the table for this type and a mask
+  /// for the table
+  typedef DenseMap<FunctionType *, CFIConstants> CFITables;
+
+  CallSet IndirectCalls;
+
+  /// The type of jumptable implementation.
+  JumpTable::JumpTableType JTType;
+
+  /// The type of CFI check to add before each indirect call.
+  CFIntegrity CFIType;
+
+  /// A value that controls whether or not CFI violations cause a halt.
+  bool CFIEnforcing;
+
+  /// The name of the function to call in case of a CFI violation when
+  /// CFIEnforcing is false. There is a default function that ignores
+  /// violations.
+  std::string CFIFuncName;
+
+  /// The alignment of each entry in the table, from JumpInstrTableInfo. The
+  /// JumpInstrTableInfo class always makes this a power of two.
+  uint64_t ByteAlignment;
+
+  /// The base-2 logarithm of ByteAlignment, needed for some of the transforms
+  /// (like CFIntegrity::Ror)
+  unsigned LogByteAlignment;
+
+  /// Adds checks to each indirect call site to make sure that it is calling a
+  /// function in our jump table.
+  void updateIndirectCalls(Module &M, CFITables &CFIT);
+
+  /// Walks the instructions to find all the indirect calls.
+  void getIndirectCalls(Module &M);
+
+  /// Adds a function that handles violations in non-enforcing mode
+  /// (!CFIEnforcing). The default warning function simply returns, since the
+  /// exact details of how to handle CFI violations depend on the application.
+  void addWarningFunction(Module &M);
+
+  /// Rewrites a function pointer in a call/invoke instruction to force it into
+  /// a table.
+  void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr,
+                              Constant *JumpTableStart, Constant *JumpTableMask,
+                              Constant *JumpTableSize);
+
+  /// Inserts a check and a call to a warning function at a given instruction
+  /// that must be an indirect call.
+  void insertWarning(Module &M, BasicBlock *Block, Instruction *I,
+                     Value *FunPtr);
+};
+
+ModulePass *
+createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT,
+                                      CFIntegrity CFIType,
+                                      bool CFIEnforcing, StringRef CFIFuncName);
+}
+
+#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H

Modified: llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h (original)
+++ llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h Tue Nov 11 15:08:02 2014
@@ -39,13 +39,14 @@ class Module;
 ///   jmp f_orig at PLT
 /// \endverbatim
 ///
-/// Support for an architecture depends on two functions in TargetInstrInfo:
-/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the
-/// appropriate instructions for the jump statement (an unconditional branch)
-/// and for padding to make the table have a size that is a power of two. This
-/// padding uses a trap instruction to ensure that calls to this area halt the
-/// program. The default implementations of these functions call
-/// llvm_unreachable.
+/// Support for an architecture depends on three functions in TargetInstrInfo:
+/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter
+/// uses these to generate the appropriate instructions for the jump statement
+/// (an unconditional branch) and for padding to make the table have a size that
+/// is a power of two. This padding uses a trap instruction to ensure that calls
+/// to this area halt the program. The default implementations of these
+/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound,
+/// which returns 0 by default.
 class JumpInstrTables : public ModulePass {
 public:
   static char ID;
@@ -64,6 +65,14 @@ public:
   /// Checks to see if there is already a table for the given FunctionType.
   bool hasTable(FunctionType *FunTy);
 
+  /// Maps the function into a subset of function types, depending on the
+  /// jump-instruction table style selected from JumpTableTypes in
+  /// JumpInstrTables.cpp. The choice of mapping determines the number of
+  /// jump-instruction tables generated by this pass. E.g., the simplest mapping
+  /// converts every function type into void f(); so, all functions end up in a
+  /// single table.
+  static FunctionType *transformType(JumpTable::JumpTableType JTT,
+                                     FunctionType *FunTy);
 private:
   /// The metadata used while a jump table is being built
   struct TableMeta {
@@ -76,14 +85,6 @@ private:
 
   typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;
 
-  /// Maps the function into a subset of function types, depending on the
-  /// jump-instruction table style selected from JumpTableTypes in
-  /// JumpInstrTables.cpp. The choice of mapping determines the number of
-  /// jump-instruction tables generated by this pass. E.g., the simplest mapping
-  /// converts every function type into void f(); so, all functions end up in a
-  /// single table.
-  FunctionType *transformType(FunctionType *FunTy);
-
   /// The current state of functions and jump entries in the table(s).
   JumpMap Metadata;
 

Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/Passes.h Tue Nov 11 15:08:02 2014
@@ -602,6 +602,10 @@ namespace llvm {
 
   /// createJumpInstrTables - This pass creates jump-instruction tables.
   ModulePass *createJumpInstrTablesPass();
+
+  /// createForwardControlFlowIntegrityPass - This pass adds control-flow
+  /// integrity.
+  ModulePass *createForwardControlFlowIntegrityPass();
 } // End llvm namespace
 
 /// This initializer registers TargetMachine constructor, so the pass being

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Tue Nov 11 15:08:02 2014
@@ -91,6 +91,7 @@ void initializeCFGOnlyViewerPass(PassReg
 void initializeCFGPrinterPass(PassRegistry&);
 void initializeCFGSimplifyPassPass(PassRegistry&);
 void initializeCFLAliasAnalysisPass(PassRegistry&);
+void initializeForwardControlFlowIntegrityPass(PassRegistry&);
 void initializeFlattenCFGPassPass(PassRegistry&);
 void initializeStructurizeCFGPass(PassRegistry&);
 void initializeCFGViewerPass(PassRegistry&);

Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Tue Nov 11 15:08:02 2014
@@ -428,6 +428,26 @@ public:
     llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
   }
 
+  /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold
+  /// either the instruction returned by getUnconditionalBranch or the
+  /// instruction returned by getTrap. This only makes sense because
+  /// getUnconditionalBranch returns a single, specific instruction. This
+  /// information is needed by the jumptable construction code, since it must
+  /// decide how many bytes to use for a jumptable entry so it can generate the
+  /// right mask.
+  ///
+  /// Note that if the jumptable instruction requires alignment, then that
+  /// alignment should be factored into this required bound so that the
+  /// resulting bound gives the right alignment for the instruction.
+  virtual unsigned getJumpInstrTableEntryBound() const {
+    // This method gets called by LLVMTargetMachine always, so it can't fail
+    // just because there happens to be no implementation for this target.
+    // Any code that tries to use a jumptable annotation without defining
+    // getUnconditionalBranch on the appropriate Target will fail anyway, and
+    // the value returned here won't matter in that case.
+    return 0;
+  }
+
   /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic
   /// block at the specified instruction (i.e. instruction would be the start
   /// of a new basic block).

Modified: llvm/trunk/include/llvm/Target/TargetOptions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetOptions.h (original)
+++ llvm/trunk/include/llvm/Target/TargetOptions.h Tue Nov 11 15:08:02 2014
@@ -57,6 +57,14 @@ namespace llvm {
     };
   }
 
+  enum class CFIntegrity {
+    Sub,             // Use subtraction-based checks.
+    Ror,             // Use rotation-based checks.
+    Add              // Use addition-based checks. This depends on having
+                     // sufficient alignment in the code and is usually not
+                     // feasible.
+  };
+
   class TargetOptions {
   public:
     TargetOptions()
@@ -70,10 +78,11 @@ namespace llvm {
           EnableFastISel(false), PositionIndependentExecutable(false),
           UseInitArray(false), DisableIntegratedAS(false),
           CompressDebugSections(false), FunctionSections(false),
-          DataSections(false), TrapUnreachable(false), TrapFuncName(""),
+          DataSections(false), TrapUnreachable(false), TrapFuncName(),
           FloatABIType(FloatABI::Default),
           AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
-          ThreadModel(ThreadModel::POSIX) {}
+          FCFI(false), ThreadModel(ThreadModel::POSIX),
+          CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
 
     /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
     /// option is specified on the command line, and should enable debugging
@@ -228,10 +237,28 @@ namespace llvm {
     /// create for functions that have the jumptable attribute.
     JumpTable::JumpTableType JTType;
 
+    /// FCFI - This flags controls whether or not forward-edge control-flow
+    /// integrity is applied.
+    bool FCFI;
+
     /// ThreadModel - This flag specifies the type of threading model to assume
     /// for things like atomics
     ThreadModel::Model ThreadModel;
 
+    /// CFIType - This flag specifies the type of control-flow integrity check
+    /// to add as a preamble to indirect calls.
+    CFIntegrity CFIType;
+
+    /// CFIEnforcing - This flags controls whether or not CFI violations cause
+    /// the program to halt.
+    bool CFIEnforcing;
+
+    /// getCFIFuncName - If this returns a non-empty string, then this is the
+    /// name of the function that will be called for each CFI violation in
+    /// non-enforcing mode.
+    std::string CFIFuncName;
+    StringRef getCFIFuncName() const;
+
     /// Machine level options.
     MCTargetOptions MCOptions;
   };

Modified: llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp Tue Nov 11 15:08:02 2014
@@ -17,6 +17,7 @@
 #include "llvm/Analysis/Passes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Type.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
 
@@ -28,7 +29,21 @@ ImmutablePass *llvm::createJumpInstrTabl
   return new JumpInstrTableInfo();
 }
 
-JumpInstrTableInfo::JumpInstrTableInfo() : ImmutablePass(ID), Tables() {
+ModulePass *llvm::createJumpInstrTableInfoPass(unsigned Bound) {
+  // This cast is always safe, since Bound is always in a subset of uint64_t.
+  uint64_t B = static_cast<uint64_t>(Bound);
+  return new JumpInstrTableInfo(B);
+}
+
+JumpInstrTableInfo::JumpInstrTableInfo(uint64_t ByteAlign)
+    : ImmutablePass(ID), Tables(), ByteAlignment(ByteAlign) {
+  if (!llvm::isPowerOf2_64(ByteAlign)) {
+    // Note that we don't explicitly handle overflow here, since we handle the 0
+    // case explicitly when a caller actually tries to create jumptable entries,
+    // and this is the return value on overflow.
+    ByteAlignment = llvm::NextPowerOf2(ByteAlign);
+  }
+
   initializeJumpInstrTableInfoPass(*PassRegistry::getPassRegistry());
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Tue Nov 11 15:08:02 2014
@@ -879,16 +879,17 @@ bool AsmPrinter::doFinalization(Module &
     bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);
     MCInst TrapInst;
     TM.getSubtargetImpl()->getInstrInfo()->getTrap(TrapInst);
+    unsigned LogAlignment = llvm::Log2_64(JITI->entryByteAlignment());
+
+    // Emit the right section for these functions.
+    OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection());
     for (const auto &KV : JITI->getTables()) {
       uint64_t Count = 0;
       for (const auto &FunPair : KV.second) {
         // Emit the function labels to make this be a function entry point.
         MCSymbol *FunSym =
           OutContext.GetOrCreateSymbol(FunPair.second->getName());
-        OutStreamer.EmitSymbolAttribute(FunSym, MCSA_Global);
-        // FIXME: JumpTableInstrInfo should store information about the required
-        // alignment of table entries and the size of the padding instruction.
-        EmitAlignment(3);
+        EmitAlignment(LogAlignment);
         if (IsThumb)
           OutStreamer.EmitThumbFunc(FunSym);
         if (MAI->hasDotTypeDotSizeDirective())
@@ -910,10 +911,9 @@ bool AsmPrinter::doFinalization(Module &
       }
 
       // Emit enough padding instructions to fill up to the next power of two.
-      // This assumes that the trap instruction takes 8 bytes or fewer.
       uint64_t Remaining = NextPowerOf2(Count) - Count;
       for (uint64_t C = 0; C < Remaining; ++C) {
-        EmitAlignment(3);
+        EmitAlignment(LogAlignment);
         OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo());
       }
 

Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Tue Nov 11 15:08:02 2014
@@ -19,6 +19,7 @@ add_llvm_library(LLVMCodeGen
   ExecutionDepsFix.cpp
   ExpandISelPseudos.cpp
   ExpandPostRAPseudos.cpp
+  ForwardControlFlowIntegrity.cpp
   GCMetadata.cpp
   GCMetadataPrinter.cpp
   GCStrategy.cpp

Added: llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp?rev=221708&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp (added)
+++ llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp Tue Nov 11 15:08:02 2014
@@ -0,0 +1,375 @@
+//===-- ForwardControlFlowIntegrity.cpp: Forward-Edge CFI -----------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief A pass that instruments code with fast checks for indirect calls and
+/// hooks for a function to check violations.
+///
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "cfi"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/JumpInstrTableInfo.h"
+#include "llvm/CodeGen/ForwardControlFlowIntegrity.h"
+#include "llvm/CodeGen/JumpInstrTables.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+STATISTIC(NumCFIIndirectCalls,
+          "Number of indirect call sites rewritten by the CFI pass");
+
+char ForwardControlFlowIntegrity::ID = 0;
+INITIALIZE_PASS_BEGIN(ForwardControlFlowIntegrity, "forward-cfi",
+                      "Control-Flow Integrity", true, true)
+INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo);
+INITIALIZE_PASS_DEPENDENCY(JumpInstrTables);
+INITIALIZE_PASS_END(ForwardControlFlowIntegrity, "forward-cfi",
+                    "Control-Flow Integrity", true, true)
+
+ModulePass *llvm::createForwardControlFlowIntegrityPass() {
+  return new ForwardControlFlowIntegrity();
+}
+
+ModulePass *llvm::createForwardControlFlowIntegrityPass(
+    JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing,
+    StringRef CFIFuncName) {
+  return new ForwardControlFlowIntegrity(JTT, CFIType, CFIEnforcing,
+                                         CFIFuncName);
+}
+
+// Checks to see if a given CallSite is making an indirect call, including
+// cases where the indirect call is made through a bitcast.
+static bool isIndirectCall(CallSite &CS) {
+  if (CS.getCalledFunction())
+    return false;
+
+  // Check the value to see if it is merely a bitcast of a function. In
+  // this case, it will translate to a direct function call in the resulting
+  // assembly, so we won't treat it as an indirect call here.
+  const Value *V = CS.getCalledValue();
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
+    return !(CE->isCast() && isa<Function>(CE->getOperand(0)));
+  }
+
+  // Otherwise, since we know it's a call, it must be an indirect call
+  return true;
+}
+
+static const char cfi_failure_func_name[] = "__llvm_cfi_pointer_warning";
+static const char cfi_func_name_prefix[] = "__llvm_cfi_function_";
+
+ForwardControlFlowIntegrity::ForwardControlFlowIntegrity()
+    : ModulePass(ID), IndirectCalls(), JTType(JumpTable::Single),
+      CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName("") {
+  initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry());
+}
+
+ForwardControlFlowIntegrity::ForwardControlFlowIntegrity(
+    JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing,
+    std::string CFIFuncName)
+    : ModulePass(ID), IndirectCalls(), JTType(JTT), CFIType(CFIType),
+      CFIEnforcing(CFIEnforcing), CFIFuncName(CFIFuncName) {
+  initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry());
+}
+
+ForwardControlFlowIntegrity::~ForwardControlFlowIntegrity() {}
+
+void ForwardControlFlowIntegrity::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<JumpInstrTableInfo>();
+  AU.addRequired<JumpInstrTables>();
+}
+
+void ForwardControlFlowIntegrity::getIndirectCalls(Module &M) {
+  // To get the indirect calls, we iterate over all functions and iterate over
+  // the list of basic blocks in each. We extract a total list of indirect calls
+  // before modifying any of them, since our modifications will modify the list
+  // of basic blocks.
+  for (Function &F : M) {
+    for (BasicBlock &BB : F) {
+      for (Instruction &I : BB) {
+        CallSite CS(&I);
+        if (!(CS && isIndirectCall(CS)))
+          continue;
+
+        Value *CalledValue = CS.getCalledValue();
+
+        // Don't rewrite this instruction if the indirect call is actually just
+        // inline assembly, since our transformation will generate an invalid
+        // module in that case.
+        if (isa<InlineAsm>(CalledValue))
+          continue;
+
+        IndirectCalls.push_back(&I);
+      }
+    }
+  }
+}
+
+void ForwardControlFlowIntegrity::updateIndirectCalls(Module &M,
+                                                      CFITables &CFIT) {
+  Type *Int64Ty = Type::getInt64Ty(M.getContext());
+  for (Instruction *I : IndirectCalls) {
+    CallSite CS(I);
+    Value *CalledValue = CS.getCalledValue();
+
+    // Get the function type for this call and look it up in the tables.
+    Type *VTy = CalledValue->getType();
+    PointerType *PTy = dyn_cast<PointerType>(VTy);
+    Type *EltTy = PTy->getElementType();
+    FunctionType *FunTy = dyn_cast<FunctionType>(EltTy);
+    FunctionType *TransformedTy = JumpInstrTables::transformType(JTType, FunTy);
+    ++NumCFIIndirectCalls;
+    Constant *JumpTableStart = nullptr;
+    Constant *JumpTableMask = nullptr;
+    Constant *JumpTableSize = nullptr;
+
+    // Some call sites have function types that don't correspond to any
+    // address-taken function in the module. This happens when function pointers
+    // are passed in from external code.
+    auto it = CFIT.find(TransformedTy);
+    if (it == CFIT.end()) {
+      // In this case, make sure that the function pointer will change by
+      // setting the mask and the start to be 0 so that the transformed
+      // function is 0.
+      JumpTableStart = ConstantInt::get(Int64Ty, 0);
+      JumpTableMask = ConstantInt::get(Int64Ty, 0);
+      JumpTableSize = ConstantInt::get(Int64Ty, 0);
+    } else {
+      JumpTableStart = it->second.StartValue;
+      JumpTableMask = it->second.MaskValue;
+      JumpTableSize = it->second.Size;
+    }
+
+    rewriteFunctionPointer(M, I, CalledValue, JumpTableStart, JumpTableMask,
+                           JumpTableSize);
+  }
+
+  return;
+}
+
+bool ForwardControlFlowIntegrity::runOnModule(Module &M) {
+  JumpInstrTableInfo *JITI = &getAnalysis<JumpInstrTableInfo>();
+  Type *Int64Ty = Type::getInt64Ty(M.getContext());
+  Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
+
+  // JumpInstrTableInfo stores information about the alignment of each entry.
+  // The alignment returned by JumpInstrTableInfo is alignment in bytes, not
+  // in the exponent.
+  ByteAlignment = JITI->entryByteAlignment();
+  LogByteAlignment = llvm::Log2_64(ByteAlignment);
+
+  // Set up tables for control-flow integrity based on information about the
+  // jump-instruction tables.
+  CFITables CFIT;
+  for (const auto &KV : JITI->getTables()) {
+    uint64_t Size = static_cast<uint64_t>(KV.second.size());
+    uint64_t TableSize = NextPowerOf2(Size);
+
+    int64_t MaskValue = ((TableSize << LogByteAlignment) - 1) & -ByteAlignment;
+    Constant *JumpTableMaskValue = ConstantInt::get(Int64Ty, MaskValue);
+    Constant *JumpTableSize = ConstantInt::get(Int64Ty, Size);
+
+    // The base of the table is defined to be the first jumptable function in
+    // the table.
+    Function *First = KV.second.begin()->second;
+    Constant *JumpTableStartValue = ConstantExpr::getBitCast(First, VoidPtrTy);
+    CFIT[KV.first].StartValue = JumpTableStartValue;
+    CFIT[KV.first].MaskValue = JumpTableMaskValue;
+    CFIT[KV.first].Size = JumpTableSize;
+  }
+
+  if (CFIT.empty())
+    return false;
+
+  getIndirectCalls(M);
+
+  if (!CFIEnforcing) {
+    addWarningFunction(M);
+  }
+
+  // Update the instructions with the check and the indirect jump through our
+  // table.
+  updateIndirectCalls(M, CFIT);
+
+  return true;
+}
+
+void ForwardControlFlowIntegrity::addWarningFunction(Module &M) {
+  PointerType *CharPtrTy = Type::getInt8PtrTy(M.getContext());
+
+  // Get the type of the Warning Function: void (i8*, i8*),
+  // where the first argument is the name of the function in which the violation
+  // occurs, and the second is the function pointer that violates CFI.
+  SmallVector<Type *, 2> WarningFunArgs;
+  WarningFunArgs.push_back(CharPtrTy);
+  WarningFunArgs.push_back(CharPtrTy);
+  FunctionType *WarningFunTy =
+      FunctionType::get(Type::getVoidTy(M.getContext()), WarningFunArgs, false);
+
+  if (!CFIFuncName.empty()) {
+    Constant *FailureFun = M.getOrInsertFunction(CFIFuncName, WarningFunTy);
+    if (!FailureFun)
+      report_fatal_error("Could not get or insert the function specified by"
+                         " -cfi-func-name");
+  } else {
+    // The default warning function swallows the warning and lets the call
+    // continue, since there's no generic way for it to print out this
+    // information.
+    Function *WarningFun = M.getFunction(cfi_failure_func_name);
+    if (!WarningFun) {
+      WarningFun =
+          Function::Create(WarningFunTy, GlobalValue::LinkOnceAnyLinkage,
+                           cfi_failure_func_name, &M);
+    }
+
+    BasicBlock *Entry =
+        BasicBlock::Create(M.getContext(), "entry", WarningFun, 0);
+    ReturnInst::Create(M.getContext(), Entry);
+  }
+}
+
+void ForwardControlFlowIntegrity::rewriteFunctionPointer(
+    Module &M, Instruction *I, Value *FunPtr, Constant *JumpTableStart,
+    Constant *JumpTableMask, Constant *JumpTableSize) {
+  IRBuilder<> TempBuilder(I);
+
+  Type *OrigFunType = FunPtr->getType();
+
+  BasicBlock *CurBB = cast<BasicBlock>(I->getParent());
+  Function *CurF = cast<Function>(CurBB->getParent());
+  Type *Int64Ty = Type::getInt64Ty(M.getContext());
+
+  Value *TI = TempBuilder.CreatePtrToInt(FunPtr, Int64Ty);
+  Value *TStartInt = TempBuilder.CreatePtrToInt(JumpTableStart, Int64Ty);
+
+  Value *NewFunPtr = nullptr;
+  Value *Check = nullptr;
+  switch (CFIType) {
+  case CFIntegrity::Sub: {
+    // This is the subtract, mask, and add version.
+    // Subtract from the base.
+    Value *Sub = TempBuilder.CreateSub(TI, TStartInt);
+
+    // Mask the difference to force this to be a table offset.
+    Value *And = TempBuilder.CreateAnd(Sub, JumpTableMask);
+
+    // Add it back to the base.
+    Value *Result = TempBuilder.CreateAdd(And, TStartInt);
+
+    // Convert it back into a function pointer that we can call.
+    NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType);
+    break;
+  }
+  case CFIntegrity::Ror: {
+    // This is the subtract and rotate version.
+    // Rotate right by the alignment value. The optimizer should recognize
+    // this sequence as a rotation.
+
+    // This cast is safe, since unsigned is always a subset of uint64_t.
+    uint64_t LogByteAlignment64 = static_cast<uint64_t>(LogByteAlignment);
+    Constant *RightShift = ConstantInt::get(Int64Ty, LogByteAlignment64);
+    Constant *LeftShift = ConstantInt::get(Int64Ty, 64 - LogByteAlignment64);
+
+    // Subtract from the base.
+    Value *Sub = TempBuilder.CreateSub(TI, TStartInt);
+
+    // Create the equivalent of a rotate-right instruction.
+    Value *Shr = TempBuilder.CreateLShr(Sub, RightShift);
+    Value *Shl = TempBuilder.CreateShl(Sub, LeftShift);
+    Value *Or = TempBuilder.CreateOr(Shr, Shl);
+
+    // Perform unsigned comparison to check for inclusion in the table.
+    Check = TempBuilder.CreateICmpULT(Or, JumpTableSize);
+    NewFunPtr = FunPtr;
+    break;
+  }
+  case CFIntegrity::Add: {
+    // This is the mask and add version.
+    // Mask the function pointer to turn it into an offset into the table.
+    Value *And = TempBuilder.CreateAnd(TI, JumpTableMask);
+
+    // Then or this offset to the base and get the pointer value.
+    Value *Result = TempBuilder.CreateAdd(And, TStartInt);
+
+    // Convert it back into a function pointer that we can call.
+    NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType);
+    break;
+  }
+  }
+
+  if (!CFIEnforcing) {
+    // If a check hasn't been added (in the rotation version), then check to see
+    // if it's the same as the original function. This check determines whether
+    // or not we call the CFI failure function.
+    if (!Check)
+      Check = TempBuilder.CreateICmpEQ(NewFunPtr, FunPtr);
+    BasicBlock *InvalidPtrBlock =
+        BasicBlock::Create(M.getContext(), "invalid.ptr", CurF, 0);
+    BasicBlock *ContinuationBB = CurBB->splitBasicBlock(I);
+
+    // Remove the unconditional branch that connects the two blocks.
+    TerminatorInst *TermInst = CurBB->getTerminator();
+    TermInst->eraseFromParent();
+
+    // Add a conditional branch that depends on the Check above.
+    BranchInst::Create(ContinuationBB, InvalidPtrBlock, Check, CurBB);
+
+    // Call the warning function for this pointer, then continue.
+    Instruction *BI = BranchInst::Create(ContinuationBB, InvalidPtrBlock);
+    insertWarning(M, InvalidPtrBlock, BI, FunPtr);
+  } else {
+    // Modify the instruction to call this value.
+    CallSite CS(I);
+    CS.setCalledFunction(NewFunPtr);
+  }
+}
+
+void ForwardControlFlowIntegrity::insertWarning(Module &M, BasicBlock *Block,
+                                                Instruction *I, Value *FunPtr) {
+  Function *ParentFun = cast<Function>(Block->getParent());
+
+  // Get the function to call right before the instruction.
+  Function *WarningFun = nullptr;
+  if (CFIFuncName.empty()) {
+    WarningFun = M.getFunction(cfi_failure_func_name);
+  } else {
+    WarningFun = M.getFunction(CFIFuncName);
+  }
+
+  assert(WarningFun && "Could not find the CFI failure function");
+
+  Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
+
+  IRBuilder<> WarningInserter(I);
+  // Create a mergeable GlobalVariable containing the name of the function.
+  Value *ParentNameGV =
+      WarningInserter.CreateGlobalString(ParentFun->getName());
+  Value *ParentNamePtr = WarningInserter.CreateBitCast(ParentNameGV, VoidPtrTy);
+  Value *FunVoidPtr = WarningInserter.CreateBitCast(FunPtr, VoidPtrTy);
+  WarningInserter.CreateCall2(WarningFun, ParentNamePtr, FunVoidPtr);
+}

Modified: llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/JumpInstrTables.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/JumpInstrTables.cpp (original)
+++ llvm/trunk/lib/CodeGen/JumpInstrTables.cpp Tue Nov 11 15:08:02 2014
@@ -163,7 +163,7 @@ void JumpInstrTables::getAnalysisUsage(A
 
 Function *JumpInstrTables::insertEntry(Module &M, Function *Target) {
   FunctionType *OrigFunTy = Target->getFunctionType();
-  FunctionType *FunTy = transformType(OrigFunTy);
+  FunctionType *FunTy = transformType(JTType, OrigFunTy);
 
   JumpMap::iterator it = Metadata.find(FunTy);
   if (Metadata.end() == it) {
@@ -191,11 +191,12 @@ Function *JumpInstrTables::insertEntry(M
 }
 
 bool JumpInstrTables::hasTable(FunctionType *FunTy) {
-  FunctionType *TransTy = transformType(FunTy);
+  FunctionType *TransTy = transformType(JTType, FunTy);
   return Metadata.end() != Metadata.find(TransTy);
 }
 
-FunctionType *JumpInstrTables::transformType(FunctionType *FunTy) {
+FunctionType *JumpInstrTables::transformType(JumpTable::JumpTableType JTT,
+                                             FunctionType *FunTy) {
   // Returning nullptr forces all types into the same table, since all types map
   // to the same type
   Type *VoidPtrTy = Type::getInt8PtrTy(FunTy->getContext());
@@ -211,7 +212,7 @@ FunctionType *JumpInstrTables::transform
   Type *Int32Ty = Type::getInt32Ty(FunTy->getContext());
   FunctionType *VoidFnTy = FunctionType::get(
       Type::getVoidTy(FunTy->getContext()), EmptyParams, false);
-  switch (JTType) {
+  switch (JTT) {
   case JumpTable::Single:
 
     return FunctionType::get(RetTy, EmptyParams, false);
@@ -253,10 +254,10 @@ FunctionType *JumpInstrTables::transform
 bool JumpInstrTables::runOnModule(Module &M) {
   JITI = &getAnalysis<JumpInstrTableInfo>();
 
-  // Get the set of jumptable-annotated functions.
+  // Get the set of jumptable-annotated functions that have their address taken.
   DenseMap<Function *, Function *> Functions;
   for (Function &F : M) {
-    if (F.hasFnAttribute(Attribute::JumpTable)) {
+    if (F.hasFnAttribute(Attribute::JumpTable) && F.hasAddressTaken()) {
       assert(F.hasUnnamedAddr() &&
              "Attribute 'jumptable' requires 'unnamed_addr'");
       Functions[&F] = nullptr;

Modified: llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp (original)
+++ llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp Tue Nov 11 15:08:02 2014
@@ -13,8 +13,10 @@
 
 #include "llvm/Target/TargetMachine.h"
 
+#include "llvm/Analysis/JumpInstrTableInfo.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/ForwardControlFlowIntegrity.h"
 #include "llvm/CodeGen/JumpInstrTables.h"
 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
@@ -143,8 +145,13 @@ bool LLVMTargetMachine::addPassesToEmitF
                                             AnalysisID StopAfter) {
   // Passes to handle jumptable function annotations. These can't be handled at
   // JIT time, so we don't add them directly to addPassesToGenerateCode.
-  PM.add(createJumpInstrTableInfoPass());
+  PM.add(createJumpInstrTableInfoPass(
+      getSubtargetImpl()->getInstrInfo()->getJumpInstrTableEntryBound()));
   PM.add(createJumpInstrTablesPass(Options.JTType));
+  if (Options.FCFI)
+    PM.add(createForwardControlFlowIntegrityPass(
+        Options.JTType, Options.CFIType, Options.CFIEnforcing,
+        Options.getCFIFuncName()));
 
   // Add common CodeGen passes.
   MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,

Modified: llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp Tue Nov 11 15:08:02 2014
@@ -51,3 +51,10 @@ bool TargetOptions::HonorSignDependentRo
 StringRef TargetOptions::getTrapFunctionName() const {
   return TrapFuncName;
 }
+
+/// getCFIFuncName - If this returns a non-empty string, then it is the name of
+/// the function that gets called on CFI violations in CFI non-enforcing mode
+/// (!TargetOptions::CFIEnforcing).
+StringRef TargetOptions::getCFIFuncName() const {
+  return CFIFuncName;
+}

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Tue Nov 11 15:08:02 2014
@@ -4489,29 +4489,6 @@ breakPartialRegDependency(MachineBasicBl
   MI->addRegisterKilled(DReg, TRI, true);
 }
 
-void ARMBaseInstrInfo::getUnconditionalBranch(
-    MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
-  if (Subtarget.isThumb())
-    Branch.setOpcode(ARM::tB);
-  else if (Subtarget.isThumb2())
-    Branch.setOpcode(ARM::t2B);
-  else
-    Branch.setOpcode(ARM::Bcc);
-
-  Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
-  Branch.addOperand(MCOperand::CreateImm(ARMCC::AL));
-  Branch.addOperand(MCOperand::CreateReg(0));
-}
-
-void ARMBaseInstrInfo::getTrap(MCInst &MI) const {
-  if (Subtarget.isThumb())
-    MI.setOpcode(ARM::tTRAP);
-  else if (Subtarget.useNaClTrap())
-    MI.setOpcode(ARM::TRAPNaCl);
-  else
-    MI.setOpcode(ARM::TRAP);
-}
-
 bool ARMBaseInstrInfo::hasNOP() const {
   return (Subtarget.getFeatureBits() & ARM::HasV6T2Ops) != 0;
 }

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Tue Nov 11 15:08:02 2014
@@ -289,12 +289,6 @@ public:
   void breakPartialRegDependency(MachineBasicBlock::iterator, unsigned,
                                  const TargetRegisterInfo *TRI) const override;
 
-  void
-  getUnconditionalBranch(MCInst &Branch,
-                         const MCSymbolRefExpr *BranchTarget) const override;
-
-  void getTrap(MCInst &MI) const override;
-
   /// Get the number of addresses by LDM or VLDM or zero for unknown.
   unsigned getNumLDMAddresses(const MachineInstr *MI) const;
 

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Nov 11 15:08:02 2014
@@ -5477,16 +5477,32 @@ void X86InstrInfo::getNoopForMachoTarget
   NopInst.setOpcode(X86::NOOP);
 }
 
+// This code must remain in sync with getJumpInstrTableEntryBound in this class!
+// In particular, getJumpInstrTableEntryBound must always return an upper bound
+// on the encoding lengths of the instructions generated by
+// getUnconditionalBranch and getTrap.
 void X86InstrInfo::getUnconditionalBranch(
     MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
   Branch.setOpcode(X86::JMP_4);
   Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
 }
 
+// This code must remain in sync with getJumpInstrTableEntryBound in this class!
+// In particular, getJumpInstrTableEntryBound must always return an upper bound
+// on the encoding lengths of the instructions generated by
+// getUnconditionalBranch and getTrap.
 void X86InstrInfo::getTrap(MCInst &MI) const {
   MI.setOpcode(X86::TRAP);
 }
 
+// See getTrap and getUnconditionalBranch for conditions on the value returned
+// by this function.
+unsigned X86InstrInfo::getJumpInstrTableEntryBound() const {
+  // 5 bytes suffice: JMP_4 Symbol at PLT is uses 1 byte (E9) for the JMP_4 and 4
+  // bytes for the symbol offset. And TRAP is ud2, which is two bytes (0F 0B).
+  return 5;
+}
+
 bool X86InstrInfo::isHighLatencyDef(int opc) const {
   switch (opc) {
   default: return false;

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Tue Nov 11 15:08:02 2014
@@ -413,6 +413,8 @@ public:
 
   void getTrap(MCInst &MI) const override;
 
+  unsigned getJumpInstrTableEntryBound() const override;
+
   bool isHighLatencyDef(int opc) const override;
 
   bool hasHighOperandLatency(const InstrItineraryData *ItinData,

Removed: llvm/trunk/test/CodeGen/ARM/jump_tables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/jump_tables.ll?rev=221707&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/jump_tables.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/jump_tables.ll (removed)
@@ -1,32 +0,0 @@
-; RUN: llc <%s -mtriple=arm-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=ARM %s
-; RUN: llc <%s -mtriple=thumb-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=THUMB %s
-
-define void @indirect_fun() unnamed_addr jumptable {
-  ret void
-}
-define void ()* @get_fun() {
-  ret void ()* @indirect_fun
-
-; ARM:         ldr     r0, [[LABEL:.*]]
-; ARM:         mov     pc, lr
-; ARM: [[LABEL]]:
-; ARM:         .long   __llvm_jump_instr_table_0_1
-
-; THUMB:         ldr     r0, [[LABEL:.*]]
-; THUMB:         bx      lr
-; THUMB: [[LABEL]]:
-; THUMB:         .long   __llvm_jump_instr_table_0_1
-}
-
-; ARM:         .globl  __llvm_jump_instr_table_0_1
-; ARM:         .align  3
-; ARM:         .type   __llvm_jump_instr_table_0_1,%function
-; ARM: __llvm_jump_instr_table_0_1:
-; ARM:         b     indirect_fun(PLT)
-
-; THUMB:         .globl  __llvm_jump_instr_table_0_1
-; THUMB:         .align  3
-; THUMB:         .thumb_func
-; THUMB:         .type   __llvm_jump_instr_table_0_1,%function
-; THUMB: __llvm_jump_instr_table_0_1:
-; THUMB:         b     indirect_fun(PLT)

Added: llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll?rev=221708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll (added)
+++ llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll Tue Nov 11 15:08:02 2014
@@ -0,0 +1,34 @@
+; RUN: llc -mtriple=i386-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86-64 %s
+
+define void @indirect_fun() unnamed_addr jumptable {
+  ret void
+}
+
+define i32 @m(void ()* %fun) {
+  call void ()* %fun()
+; CHECK: subl
+; X86-64: andq    $8,
+; X86-64: leaq    __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]]
+; X86-64-NOT: callq __llvm_cfi_pointer_warning
+; X86-64: callq   *[[REG]]
+; X86: andl    $8,
+; X86: leal    __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]]
+; X86-NOT: calll __llvm_cfi_pointer_warning
+; X86: calll   *[[REG]]
+  ret i32 0
+}
+
+define void ()* @get_fun() {
+  ret void ()* @indirect_fun
+}
+
+define i32 @main(i32 %argc, i8** %argv) {
+  %f = call void ()* ()* @get_fun()
+  %a = call i32 @m(void ()* %f)
+  ret i32 %a
+}
+
+; CHECK: .align 8
+; CHECK: __llvm_jump_instr_table_0_1:
+; CHECK: jmp indirect_fun at PLT

Added: llvm/trunk/test/CodeGen/X86/cfi_invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_invoke.ll?rev=221708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cfi_invoke.ll (added)
+++ llvm/trunk/test/CodeGen/X86/cfi_invoke.ll Tue Nov 11 15:08:02 2014
@@ -0,0 +1,35 @@
+; RUN: llc <%s -fcfi -cfi-type=sub | FileCheck %s
+; ModuleID = 'test.cc'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @__gxx_personality_v0(...)
+
+ at _ZTIPKc = external constant i8*
+ at _ZTIi = external constant i8*
+
+define void @f() unnamed_addr jumptable {
+  ret void
+}
+
+ at a = global void ()* @f
+
+; Make sure invoke gets targeted as well as regular calls
+define void @_Z3foov(void ()* %f) uwtable ssp {
+; CHECK-LABEL: _Z3foov:
+ entry:
+   invoke void %f()
+           to label %try.cont unwind label %lpad
+; CHECK: callq __llvm_cfi_pointer_warning
+; CHECK: callq *%rbx
+
+ lpad:
+   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+                                  catch i8* bitcast (i8** @_ZTIi to i8*)
+                                  filter [1 x i8*] [i8* bitcast (i8** @_ZTIPKc to i8*)]
+   ret void
+
+ try.cont:
+   ret void
+}
+

Added: llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll?rev=221708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll (added)
+++ llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll Tue Nov 11 15:08:02 2014
@@ -0,0 +1,27 @@
+; RUN: llc -fcfi -cfi-func-name=cfi_new_failure <%s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+define void @indirect_fun() unnamed_addr jumptable {
+  ret void
+}
+
+define i32 @m(void ()* %fun) {
+; CHECK-LABEL: @m
+  call void ()* %fun()
+; CHECK: callq cfi_new_failure
+  ret i32 0
+}
+
+define void ()* @get_fun() {
+  ret void ()* @indirect_fun
+}
+
+define i32 @main(i32 %argc, i8** %argv) {
+  %f = call void ()* ()* @get_fun()
+  %a = call i32 @m(void ()* %f)
+  ret i32 %a
+}
+
+; CHECK: .align 8
+; CHECK: __llvm_jump_instr_table_0_1:
+; CHECK: jmp indirect_fun at PLT

Added: llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll?rev=221708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll (added)
+++ llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll Tue Nov 11 15:08:02 2014
@@ -0,0 +1,43 @@
+; RUN: llc -fcfi -cfi-type=sub <%s | FileCheck --check-prefix=SUB %s
+; RUN: llc -fcfi -cfi-type=add <%s | FileCheck --check-prefix=ADD %s
+; RUN: llc -fcfi -cfi-type=ror <%s | FileCheck --check-prefix=ROR %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @indirect_fun() unnamed_addr jumptable {
+  ret void
+}
+
+define i32 @m(void ()* %fun) {
+  call void ()* %fun()
+; SUB: subl    
+; SUB: andq    $8
+; SUB-LABEL: leaq    __llvm_jump_instr_table_0_1
+; SUB-LABEL: callq   __llvm_cfi_pointer_warning
+
+; ROR: subq
+; ROR: rolq    $61
+; ROR: testq
+; ROR-LABEL: callq   __llvm_cfi_pointer_warning
+
+; ADD: andq    $8
+; ADD-LABEL: leaq    __llvm_jump_instr_table_0_1
+; ADD: cmpq
+; ADD-LABEL: callq   __llvm_cfi_pointer_warning
+ret i32 0
+}
+
+define void ()* @get_fun() {
+  ret void ()* @indirect_fun
+}
+
+define i32 @main(i32 %argc, i8** %argv) {
+  %f = call void ()* ()* @get_fun()
+  %a = call i32 @m(void ()* %f)
+  ret i32 %a
+}
+; SUB: .text
+; SUB: .align 8
+; SUB-LABEL: .type __llvm_jump_instr_table_0_1, at function
+; SUB-LABEL:__llvm_jump_instr_table_0_1:
+; SUB-LABEL: jmp indirect_fun at PLT

Modified: llvm/trunk/test/CodeGen/X86/jump_table_alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_alias.ll?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/jump_table_alias.ll (original)
+++ llvm/trunk/test/CodeGen/X86/jump_table_alias.ll Tue Nov 11 15:08:02 2014
@@ -25,7 +25,6 @@ define i32 @main(i32 %argc, i8** %argv)
 ; There should only be one table, even though there are two GlobalAliases,
 ; because they both alias the same value.
 
-; CHECK:         .globl  __llvm_jump_instr_table_0_1
 ; CHECK:         .align  8, 0x90
 ; CHECK:         .type   __llvm_jump_instr_table_0_1, at function
 ; CHECK: __llvm_jump_instr_table_0_1:

Added: llvm/trunk/test/CodeGen/X86/jump_table_align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_align.ll?rev=221708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/jump_table_align.ll (added)
+++ llvm/trunk/test/CodeGen/X86/jump_table_align.ll Tue Nov 11 15:08:02 2014
@@ -0,0 +1,29 @@
+; RUN: llc -filetype=obj <%s -jump-table-type=single -o %t1
+; RUN: llvm-objdump -triple=x86_64-unknown-linux-gnu -d %t1 | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+define i32 @f() unnamed_addr jumptable {
+  ret i32 0
+}
+
+define i32 @g(i8* %a) unnamed_addr jumptable {
+  ret i32 0
+}
+
+define void @h(void ()* %func) unnamed_addr jumptable {
+  ret void
+}
+
+define i32 @main() {
+  %g = alloca i32 (...)*, align 8
+  store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8
+  %1 = load i32 (...)** %g, align 8
+  %call = call i32 (...)* %1()
+  call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*))
+  %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)
+  ret i32 %a
+}
+
+; Make sure that the padding from getJumpInstrTableEntryBound is right.
+; CHECK: __llvm_jump_instr_table_0_1:
+; CHECK-NEXT: e9 00 00 00 00                                  jmp     0
+; CHECK-NEXT: 0f 1f 00                                        nopl    (%rax)

Modified: llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll (original)
+++ llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll Tue Nov 11 15:08:02 2014
@@ -15,12 +15,12 @@ define void @h(void ()* %func) unnamed_a
 define i32 @main() {
   %g = alloca i32 (...)*, align 8
   store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8
-; CHECK: movq    $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]], (%rsp)
-; CHECK: movl    $__llvm_jump_instr_table_0_[[ENTRY]], %ecx
+; CHECK: movq    $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]],
+; CHECK: movl    $__llvm_jump_instr_table_0_[[ENTRY]],
   %1 = load i32 (...)** %g, align 8
   %call = call i32 (...)* %1()
   call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*))
-; CHECK: movl    $__llvm_jump_instr_table_0_{{1|2|3}}, %edi
+; CHECK: movl    $__llvm_jump_instr_table_0_{{1|2|3}},
 ; CHECK: callq   h
 
   %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)
@@ -28,17 +28,14 @@ define i32 @main() {
   ret i32 %a
 }
 
-; CHECK:         .globl  __llvm_jump_instr_table_0_1
 ; CHECK:         .align  8, 0x90
 ; CHECK:         .type   __llvm_jump_instr_table_0_1, at function
 ; CHECK: __llvm_jump_instr_table_0_1:
 ; CHECK:         jmp     {{f|g|h}}@PLT
-; CHECK:         .globl  __llvm_jump_instr_table_0_2
 ; CHECK:         .align  8, 0x90
 ; CHECK:         .type   __llvm_jump_instr_table_0_2, at function
 ; CHECK: __llvm_jump_instr_table_0_2:
 ; CHECK:         jmp     {{f|g|h}}@PLT
-; CHECK:         .globl  __llvm_jump_instr_table_0_3
 ; CHECK:         .align  8, 0x90
 ; CHECK:         .type   __llvm_jump_instr_table_0_3, at function
 ; CHECK: __llvm_jump_instr_table_0_3:

Modified: llvm/trunk/test/CodeGen/X86/jump_tables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_tables.ll?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/jump_tables.ll (original)
+++ llvm/trunk/test/CodeGen/X86/jump_tables.ll Tue Nov 11 15:08:02 2014
@@ -7,6 +7,20 @@ target triple = "x86_64-unknown-linux-gn
 
 %struct.fun_struct = type { i32 (...)* }
 
+ at a = global [12 x i32 () *] [ i32 ()* bitcast (void ()* @indirect_fun to i32 ()*),
+			      i32 ()* bitcast (void ()* @indirect_fun_match to i32 ()*),
+			      i32 ()* bitcast (i32 ()* @indirect_fun_i32 to i32 ()*),
+			      i32 ()* bitcast (i32 (i32)* @indirect_fun_i32_1 to i32 ()*),
+			      i32 ()* bitcast (i32 (i32, i32)* @indirect_fun_i32_2 to i32 ()*),
+			      i32 ()* bitcast (i32* (i32*, i32)* @indirect_fun_i32S_2 to i32 ()*),
+			      i32 ()* bitcast (void (%struct.fun_struct)* @indirect_fun_struct to i32 ()*),
+			      i32 ()* bitcast (void (i32 (...)*, i32)* @indirect_fun_fun to i32 ()*),
+			      i32 ()* bitcast (i32 (i32 (...)*, i32)* @indirect_fun_fun_ret to i32 ()*),
+			      i32 ()* bitcast (void ([19 x i8])* @indirect_fun_array to i32 ()*),
+			      i32 ()* bitcast (void (<3 x i32>)* @indirect_fun_vec to i32 ()*),
+			      i32 ()* bitcast (void (<4 x float>)* @indirect_fun_vec_2 to i32 ()*)
+			    ]
+
 define void @indirect_fun() unnamed_addr jumptable {
   ret void
 }
@@ -74,62 +88,50 @@ define i32 @main(i32 %argc, i8** %argv)
   ret i32 %a
 }
 
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_1
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_1, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_1:
 ; SINGLE-DAG:         jmp     indirect_fun_array at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_2
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_2, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_2:
 ; SINGLE-DAG:         jmp     indirect_fun_i32_2 at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_3
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_3, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_3:
 ; SINGLE-DAG:         jmp     indirect_fun_vec_2 at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_4
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_4, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_4:
 ; SINGLE-DAG:         jmp     indirect_fun_i32S_2 at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_5
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_5, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_5:
 ; SINGLE-DAG:         jmp     indirect_fun_struct at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_6
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_6, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_6:
 ; SINGLE-DAG:         jmp     indirect_fun_i32_1 at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_7
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_7, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_7:
 ; SINGLE-DAG:         jmp     indirect_fun_i32 at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_8
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_8, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_8:
 ; SINGLE-DAG:         jmp     indirect_fun_fun at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_9
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_9, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_9:
 ; SINGLE-DAG:         jmp     indirect_fun_fun_ret at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_10
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_10, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_10:
 ; SINGLE-DAG:         jmp     indirect_fun at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_11
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_11, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_11:
 ; SINGLE-DAG:         jmp     indirect_fun_match at PLT
-; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_12
 ; SINGLE-DAG:         .align  8, 0x90
 ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_12, at function
 ; SINGLE-DAG: __llvm_jump_instr_table_0_12:
@@ -144,82 +146,69 @@ define i32 @main(i32 %argc, i8** %argv)
 ; SINGLE-DAG:         ud2
 
 
-; ARITY-DAG:         .globl  __llvm_jump_instr_table_2_1
 ; ARITY-DAG:         .align  8, 0x90
 ; ARITY-DAG:         .type   __llvm_jump_instr_table_2_1, at function
 ; ARITY-DAG: __llvm_jump_instr_table_2_1:
 ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT
 ; ARITY-DAG:         .align  8, 0x90
 ; ARITY-DAG:         ud2
-; ARITY-DAG:         .globl  __llvm_jump_instr_table_0_1
 ; ARITY-DAG:         .align  8, 0x90
 ; ARITY-DAG:         .type   __llvm_jump_instr_table_0_1, at function
 ; ARITY-DAG: __llvm_jump_instr_table_0_1:
 ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT
-; ARITY-DAG:         .globl  __llvm_jump_instr_table_1_1
 ; ARITY-DAG:         .align  8, 0x90
 ; ARITY-DAG:         .type   __llvm_jump_instr_table_1_1, at function
 ; ARITY-DAG: __llvm_jump_instr_table_1_1:
 ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT
 
-; SIMPL-DAG:         .globl  __llvm_jump_instr_table_2_1
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         .type   __llvm_jump_instr_table_2_1, at function
 ; SIMPL-DAG: __llvm_jump_instr_table_2_1:
 ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         ud2
-; SIMPL-DAG:         .globl  __llvm_jump_instr_table_0_1
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         .type   __llvm_jump_instr_table_0_1, at function
 ; SIMPL-DAG: __llvm_jump_instr_table_0_1:
 ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT
-; SIMPL-DAG:         .globl  __llvm_jump_instr_table_1_1
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         .type   __llvm_jump_instr_table_1_1, at function
 ; SIMPL-DAG: __llvm_jump_instr_table_1_1:
 ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT
-; SIMPL-DAG:         .globl  __llvm_jump_instr_table_3_1
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         .type   __llvm_jump_instr_table_3_1, at function
 ; SIMPL-DAG: __llvm_jump_instr_table_3_1:
 ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT
-; SIMPL-DAG:         .globl  __llvm_jump_instr_table_4_1
 ; SIMPL-DAG:         .align  8, 0x90
 ; SIMPL-DAG:         .type   __llvm_jump_instr_table_4_1, at function
 ; SIMPL-DAG: __llvm_jump_instr_table_4_1:
 ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT
 
 
-; FULL-DAG:        .globl  __llvm_jump_instr_table_10_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_10_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_10_1:
 ; FULL-DAG:        jmp     indirect_fun_i32_1 at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_9_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_9_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_9_1:
 ; FULL-DAG:        jmp     indirect_fun_i32_2 at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_7_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_7_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_7_1:
 ; FULL-DAG:        jmp     indirect_fun_i32S_2 at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_3_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_3_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_3_1:
 ; FULL-DAG:        jmp     indirect_fun_vec_2 at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_2_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_2_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_2_1:
@@ -228,42 +217,36 @@ define i32 @main(i32 %argc, i8** %argv)
 ; FULL-DAG:        ud2
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_8_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_8_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_8_1:
 ; FULL-DAG:        jmp     indirect_fun_i32 at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_1_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_1_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_1_1:
 ; FULL-DAG:        jmp     indirect_fun_array at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_0_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_0_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_0_1:
 ; FULL-DAG:        jmp     indirect_fun_vec at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_6_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_6_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_6_1:
 ; FULL-DAG:        jmp     indirect_fun_struct at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_5_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_5_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_5_1:
 ; FULL-DAG:        jmp     indirect_fun_fun at PLT
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        ud2
-; FULL-DAG:        .globl  __llvm_jump_instr_table_4_1
 ; FULL-DAG:        .align  8, 0x90
 ; FULL-DAG:        .type   __llvm_jump_instr_table_4_1, at function
 ; FULL-DAG:__llvm_jump_instr_table_4_1:

Modified: llvm/trunk/test/LTO/jump-table-type.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/jump-table-type.ll?rev=221708&r1=221707&r2=221708&view=diff
==============================================================================
--- llvm/trunk/test/LTO/jump-table-type.ll (original)
+++ llvm/trunk/test/LTO/jump-table-type.ll Tue Nov 11 15:08:02 2014
@@ -2,8 +2,8 @@
 ; RUN: llvm-lto -o %t2 %t1 -jump-table-type=arity
 ; RUN: llvm-nm %t2 | FileCheck %s
 
-; CHECK: T __llvm_jump_instr_table_0_1
-; CHECK: T __llvm_jump_instr_table_1_1
+; CHECK: t __llvm_jump_instr_table_0_1
+; CHECK: t __llvm_jump_instr_table_1_1
 
 target triple = "x86_64-unknown-linux-gnu"
 





More information about the llvm-commits mailing list