<div dir="ltr">That looks right to me; I think that must be the bit that only emits jumptable values if the address is taken in addition to there being a jumptable annotation.<div><br></div><div>Thanks for catching this.</div><div><br></div><div>Tom</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 12, 2014 at 6:23 AM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Should be fixed in r221783. Let me know if that looks like the correct fix.<br>
<div class="HOEnZb"><div class="h5"><br>
On 11 November 2014 20:36, Rafael Espíndola <<a href="mailto:rafael.espindola@gmail.com">rafael.espindola@gmail.com</a>> wrote:<br>
> This causes tools/gold/option.ll to fail.<br>
><br>
> Can you take a look? Looks like __llvm_jump_instr_table_* are no<br>
> longer produced for that test.<br>
><br>
><br>
> On 11 November 2014 16:08, Tom Roeder <<a href="mailto:tmroeder@google.com">tmroeder@google.com</a>> wrote:<br>
>> Author: tmroeder<br>
>> Date: Tue Nov 11 15:08:02 2014<br>
>> New Revision: 221708<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=221708&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=221708&view=rev</a><br>
>> Log:<br>
>> Add Forward Control-Flow Integrity.<br>
>><br>
>> This commit adds a new pass that can inject checks before indirect calls to<br>
>> make sure that these calls target known locations. It supports three types of<br>
>> checks and, at compile time, it can take the name of a custom function to call<br>
>> when an indirect call check fails. The default failure function ignores the<br>
>> error and continues.<br>
>><br>
>> This pass incidentally moves the function JumpInstrTables::transformType from<br>
>> private to public and makes it static (with a new argument that specifies the<br>
>> table type to use); this is so that the CFI code can transform function types<br>
>> at call sites to determine which jump-instruction table to use for the check at<br>
>> that site.<br>
>><br>
>> Also, this removes support for jumptables in ARM, pending further performance<br>
>> analysis and discussion.<br>
>><br>
>> Review: <a href="http://reviews.llvm.org/D4167" target="_blank">http://reviews.llvm.org/D4167</a><br>
>><br>
>><br>
>> Added:<br>
>>     llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h<br>
>>     llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp<br>
>>     llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll<br>
>>     llvm/trunk/test/CodeGen/X86/cfi_invoke.ll<br>
>>     llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll<br>
>>     llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll<br>
>>     llvm/trunk/test/CodeGen/X86/jump_table_align.ll<br>
>> Removed:<br>
>>     llvm/trunk/test/CodeGen/ARM/jump_tables.ll<br>
>> Modified:<br>
>>     llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h<br>
>>     llvm/trunk/include/llvm/CodeGen/CommandFlags.h<br>
>>     llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h<br>
>>     llvm/trunk/include/llvm/CodeGen/Passes.h<br>
>>     llvm/trunk/include/llvm/InitializePasses.h<br>
>>     llvm/trunk/include/llvm/Target/TargetInstrInfo.h<br>
>>     llvm/trunk/include/llvm/Target/TargetOptions.h<br>
>>     llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp<br>
>>     llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp<br>
>>     llvm/trunk/lib/CodeGen/CMakeLists.txt<br>
>>     llvm/trunk/lib/CodeGen/JumpInstrTables.cpp<br>
>>     llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp<br>
>>     llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp<br>
>>     llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp<br>
>>     llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>
>>     llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
>>     llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
>>     llvm/trunk/test/CodeGen/X86/jump_table_alias.ll<br>
>>     llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll<br>
>>     llvm/trunk/test/CodeGen/X86/jump_tables.ll<br>
>>     llvm/trunk/test/LTO/jump-table-type.ll<br>
>><br>
>> Modified: llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h (original)<br>
>> +++ llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h Tue Nov 11 15:08:02 2014<br>
>> @@ -37,7 +37,9 @@ class JumpInstrTableInfo : public Immuta<br>
>>  public:<br>
>>    static char ID;<br>
>><br>
>> -  JumpInstrTableInfo();<br>
>> +  /// The default byte alignment for jump tables is 16, which is large but<br>
>> +  /// usually safe.<br>
>> +  JumpInstrTableInfo(uint64_t ByteAlign = 16);<br>
>>    virtual ~JumpInstrTableInfo();<br>
>>    const char *getPassName() const override {<br>
>>      return "Jump-Instruction Table Info";<br>
>> @@ -52,9 +54,19 @@ public:<br>
>>    /// Gets the tables.<br>
>>    const JumpTables &getTables() const { return Tables; }<br>
>><br>
>> +  /// Gets the alignment in bytes of a jumptable entry.<br>
>> +  uint64_t entryByteAlignment() const { return ByteAlignment; }<br>
>>  private:<br>
>>    JumpTables Tables;<br>
>> +<br>
>> +  /// A power-of-two alignment of a jumptable entry.<br>
>> +  uint64_t ByteAlignment;<br>
>>  };<br>
>> +<br>
>> +/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This<br>
>> +/// bound specifies the maximum number of bytes needed to represent an<br>
>> +/// unconditional jump or a trap instruction in the back end currently in use.<br>
>> +ModulePass *createJumpInstrTableInfoPass(unsigned Bound);<br>
>>  }<br>
>><br>
>>  #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */<br>
>><br>
>> Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)<br>
>> +++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Tue Nov 11 15:08:02 2014<br>
>> @@ -222,6 +222,44 @@ JTableType("jump-table-type",<br>
>>                           "Create one table per unique function type."),<br>
>>                clEnumValEnd));<br>
>><br>
>> +cl::opt<bool><br>
>> +FCFI("fcfi",<br>
>> +     cl::desc("Apply forward-edge control-flow integrity"),<br>
>> +     cl::init(false));<br>
>> +<br>
>> +cl::opt<llvm::CFIntegrity><br>
>> +CFIType("cfi-type",<br>
>> +        cl::desc("Choose the type of Control-Flow Integrity check to add"),<br>
>> +        cl::init(CFIntegrity::Sub),<br>
>> +        cl::values(<br>
>> +            clEnumValN(CFIntegrity::Sub, "sub",<br>
>> +                       "Subtract the pointer from the table base, then mask."),<br>
>> +            clEnumValN(CFIntegrity::Ror, "ror",<br>
>> +                       "Use rotate to check the offset from a table base."),<br>
>> +            clEnumValN(CFIntegrity::Add, "add",<br>
>> +                       "Mask out the high bits and add to an aligned base."),<br>
>> +            clEnumValEnd));<br>
>> +<br>
>> +cl::opt<bool><br>
>> +CFIEnforcing("cfi-enforcing",<br>
>> +             cl::desc("Enforce CFI or pass the violation to a function."),<br>
>> +             cl::init(false));<br>
>> +<br>
>> +// Note that this option is linked to the cfi-enforcing option above: if<br>
>> +// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If<br>
>> +// cfi-enforcing is false and no cfi-func-name is set, then a default function<br>
>> +// will be generated that ignores all CFI violations. The expected signature for<br>
>> +// functions called with CFI violations is<br>
>> +//<br>
>> +// void (i8*, i8*)<br>
>> +//<br>
>> +// The first pointer is a C string containing the name of the function in which<br>
>> +// the violation occurs, and the second pointer is the pointer that violated<br>
>> +// CFI.<br>
>> +cl::opt<std::string><br>
>> +CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"),<br>
>> +            cl::init(""));<br>
>> +<br>
>>  // Common utility function tightly tied to the options listed here. Initializes<br>
>>  // a TargetOptions object with CodeGen flags and returns it.<br>
>>  static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {<br>
>> @@ -249,6 +287,10 @@ static inline TargetOptions InitTargetOp<br>
>><br>
>>    Options.MCOptions = InitMCTargetOptionsFromFlags();<br>
>>    Options.JTType = JTableType;<br>
>> +  Options.FCFI = FCFI;<br>
>> +  Options.CFIType = CFIType;<br>
>> +  Options.CFIEnforcing = CFIEnforcing;<br>
>> +  Options.CFIFuncName = CFIFuncName;<br>
>><br>
>>    Options.ThreadModel = TMModel;<br>
>><br>
>><br>
>> Added: llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h (added)<br>
>> +++ llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,123 @@<br>
>> +//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===//<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This pass instruments indirect calls with checks to ensure that these calls<br>
>> +// pass through the appropriate jump-instruction table generated by<br>
>> +// JumpInstrTables.<br>
>> +//<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H<br>
>> +#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H<br>
>> +<br>
>> +#include "llvm/ADT/DenseMap.h"<br>
>> +#include "llvm/ADT/SmallVector.h"<br>
>> +#include "llvm/Pass.h"<br>
>> +#include "llvm/Target/TargetOptions.h"<br>
>> +<br>
>> +#include <string><br>
>> +<br>
>> +namespace llvm {<br>
>> +<br>
>> +class AnalysisUsage;<br>
>> +class BasicBlock;<br>
>> +class Constant;<br>
>> +class Function;<br>
>> +class Instruction;<br>
>> +class Module;<br>
>> +class Value;<br>
>> +<br>
>> +/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to<br>
>> +/// prepend checks to indirect calls to make sure that these calls target valid<br>
>> +/// locations.<br>
>> +class ForwardControlFlowIntegrity : public ModulePass {<br>
>> +public:<br>
>> +  static char ID;<br>
>> +<br>
>> +  ForwardControlFlowIntegrity();<br>
>> +  ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT,<br>
>> +                              CFIntegrity CFIType,<br>
>> +                              bool CFIEnforcing, std::string CFIFuncName);<br>
>> +  virtual ~ForwardControlFlowIntegrity() override;<br>
>> +<br>
>> +  /// Runs the CFI pass on a given module. This works best if the module in<br>
>> +  /// question is the result of link-time optimization (see lib/LTO).<br>
>> +  bool runOnModule(Module &M) override;<br>
>> +  const char *getPassName() const override {<br>
>> +    return "Forward Control-Flow Integrity";<br>
>> +  }<br>
>> +  void getAnalysisUsage(AnalysisUsage &AU) const override;<br>
>> +<br>
>> +private:<br>
>> +  typedef SmallVector<Instruction *, 64> CallSet;<br>
>> +<br>
>> +  /// A structure that is used to keep track of constant table information.<br>
>> +  struct CFIConstants {<br>
>> +    Constant *StartValue;<br>
>> +    Constant *MaskValue;<br>
>> +    Constant *Size;<br>
>> +  };<br>
>> +<br>
>> +  /// A map from function type to the base of the table for this type and a mask<br>
>> +  /// for the table<br>
>> +  typedef DenseMap<FunctionType *, CFIConstants> CFITables;<br>
>> +<br>
>> +  CallSet IndirectCalls;<br>
>> +<br>
>> +  /// The type of jumptable implementation.<br>
>> +  JumpTable::JumpTableType JTType;<br>
>> +<br>
>> +  /// The type of CFI check to add before each indirect call.<br>
>> +  CFIntegrity CFIType;<br>
>> +<br>
>> +  /// A value that controls whether or not CFI violations cause a halt.<br>
>> +  bool CFIEnforcing;<br>
>> +<br>
>> +  /// The name of the function to call in case of a CFI violation when<br>
>> +  /// CFIEnforcing is false. There is a default function that ignores<br>
>> +  /// violations.<br>
>> +  std::string CFIFuncName;<br>
>> +<br>
>> +  /// The alignment of each entry in the table, from JumpInstrTableInfo. The<br>
>> +  /// JumpInstrTableInfo class always makes this a power of two.<br>
>> +  uint64_t ByteAlignment;<br>
>> +<br>
>> +  /// The base-2 logarithm of ByteAlignment, needed for some of the transforms<br>
>> +  /// (like CFIntegrity::Ror)<br>
>> +  unsigned LogByteAlignment;<br>
>> +<br>
>> +  /// Adds checks to each indirect call site to make sure that it is calling a<br>
>> +  /// function in our jump table.<br>
>> +  void updateIndirectCalls(Module &M, CFITables &CFIT);<br>
>> +<br>
>> +  /// Walks the instructions to find all the indirect calls.<br>
>> +  void getIndirectCalls(Module &M);<br>
>> +<br>
>> +  /// Adds a function that handles violations in non-enforcing mode<br>
>> +  /// (!CFIEnforcing). The default warning function simply returns, since the<br>
>> +  /// exact details of how to handle CFI violations depend on the application.<br>
>> +  void addWarningFunction(Module &M);<br>
>> +<br>
>> +  /// Rewrites a function pointer in a call/invoke instruction to force it into<br>
>> +  /// a table.<br>
>> +  void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr,<br>
>> +                              Constant *JumpTableStart, Constant *JumpTableMask,<br>
>> +                              Constant *JumpTableSize);<br>
>> +<br>
>> +  /// Inserts a check and a call to a warning function at a given instruction<br>
>> +  /// that must be an indirect call.<br>
>> +  void insertWarning(Module &M, BasicBlock *Block, Instruction *I,<br>
>> +                     Value *FunPtr);<br>
>> +};<br>
>> +<br>
>> +ModulePass *<br>
>> +createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT,<br>
>> +                                      CFIntegrity CFIType,<br>
>> +                                      bool CFIEnforcing, StringRef CFIFuncName);<br>
>> +}<br>
>> +<br>
>> +#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H<br>
>><br>
>> Modified: llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h (original)<br>
>> +++ llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h Tue Nov 11 15:08:02 2014<br>
>> @@ -39,13 +39,14 @@ class Module;<br>
>>  ///   jmp f_orig@PLT<br>
>>  /// \endverbatim<br>
>>  ///<br>
>> -/// Support for an architecture depends on two functions in TargetInstrInfo:<br>
>> -/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the<br>
>> -/// appropriate instructions for the jump statement (an unconditional branch)<br>
>> -/// and for padding to make the table have a size that is a power of two. This<br>
>> -/// padding uses a trap instruction to ensure that calls to this area halt the<br>
>> -/// program. The default implementations of these functions call<br>
>> -/// llvm_unreachable.<br>
>> +/// Support for an architecture depends on three functions in TargetInstrInfo:<br>
>> +/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter<br>
>> +/// uses these to generate the appropriate instructions for the jump statement<br>
>> +/// (an unconditional branch) and for padding to make the table have a size that<br>
>> +/// is a power of two. This padding uses a trap instruction to ensure that calls<br>
>> +/// to this area halt the program. The default implementations of these<br>
>> +/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound,<br>
>> +/// which returns 0 by default.<br>
>>  class JumpInstrTables : public ModulePass {<br>
>>  public:<br>
>>    static char ID;<br>
>> @@ -64,6 +65,14 @@ public:<br>
>>    /// Checks to see if there is already a table for the given FunctionType.<br>
>>    bool hasTable(FunctionType *FunTy);<br>
>><br>
>> +  /// Maps the function into a subset of function types, depending on the<br>
>> +  /// jump-instruction table style selected from JumpTableTypes in<br>
>> +  /// JumpInstrTables.cpp. The choice of mapping determines the number of<br>
>> +  /// jump-instruction tables generated by this pass. E.g., the simplest mapping<br>
>> +  /// converts every function type into void f(); so, all functions end up in a<br>
>> +  /// single table.<br>
>> +  static FunctionType *transformType(JumpTable::JumpTableType JTT,<br>
>> +                                     FunctionType *FunTy);<br>
>>  private:<br>
>>    /// The metadata used while a jump table is being built<br>
>>    struct TableMeta {<br>
>> @@ -76,14 +85,6 @@ private:<br>
>><br>
>>    typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;<br>
>><br>
>> -  /// Maps the function into a subset of function types, depending on the<br>
>> -  /// jump-instruction table style selected from JumpTableTypes in<br>
>> -  /// JumpInstrTables.cpp. The choice of mapping determines the number of<br>
>> -  /// jump-instruction tables generated by this pass. E.g., the simplest mapping<br>
>> -  /// converts every function type into void f(); so, all functions end up in a<br>
>> -  /// single table.<br>
>> -  FunctionType *transformType(FunctionType *FunTy);<br>
>> -<br>
>>    /// The current state of functions and jump entries in the table(s).<br>
>>    JumpMap Metadata;<br>
>><br>
>><br>
>> Modified: llvm/trunk/include/llvm/CodeGen/Passes.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/CodeGen/Passes.h (original)<br>
>> +++ llvm/trunk/include/llvm/CodeGen/Passes.h Tue Nov 11 15:08:02 2014<br>
>> @@ -602,6 +602,10 @@ namespace llvm {<br>
>><br>
>>    /// createJumpInstrTables - This pass creates jump-instruction tables.<br>
>>    ModulePass *createJumpInstrTablesPass();<br>
>> +<br>
>> +  /// createForwardControlFlowIntegrityPass - This pass adds control-flow<br>
>> +  /// integrity.<br>
>> +  ModulePass *createForwardControlFlowIntegrityPass();<br>
>>  } // End llvm namespace<br>
>><br>
>>  /// This initializer registers TargetMachine constructor, so the pass being<br>
>><br>
>> Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
>> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Nov 11 15:08:02 2014<br>
>> @@ -91,6 +91,7 @@ void initializeCFGOnlyViewerPass(PassReg<br>
>>  void initializeCFGPrinterPass(PassRegistry&);<br>
>>  void initializeCFGSimplifyPassPass(PassRegistry&);<br>
>>  void initializeCFLAliasAnalysisPass(PassRegistry&);<br>
>> +void initializeForwardControlFlowIntegrityPass(PassRegistry&);<br>
>>  void initializeFlattenCFGPassPass(PassRegistry&);<br>
>>  void initializeStructurizeCFGPass(PassRegistry&);<br>
>>  void initializeCFGViewerPass(PassRegistry&);<br>
>><br>
>> Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)<br>
>> +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Tue Nov 11 15:08:02 2014<br>
>> @@ -428,6 +428,26 @@ public:<br>
>>      llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");<br>
>>    }<br>
>><br>
>> +  /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold<br>
>> +  /// either the instruction returned by getUnconditionalBranch or the<br>
>> +  /// instruction returned by getTrap. This only makes sense because<br>
>> +  /// getUnconditionalBranch returns a single, specific instruction. This<br>
>> +  /// information is needed by the jumptable construction code, since it must<br>
>> +  /// decide how many bytes to use for a jumptable entry so it can generate the<br>
>> +  /// right mask.<br>
>> +  ///<br>
>> +  /// Note that if the jumptable instruction requires alignment, then that<br>
>> +  /// alignment should be factored into this required bound so that the<br>
>> +  /// resulting bound gives the right alignment for the instruction.<br>
>> +  virtual unsigned getJumpInstrTableEntryBound() const {<br>
>> +    // This method gets called by LLVMTargetMachine always, so it can't fail<br>
>> +    // just because there happens to be no implementation for this target.<br>
>> +    // Any code that tries to use a jumptable annotation without defining<br>
>> +    // getUnconditionalBranch on the appropriate Target will fail anyway, and<br>
>> +    // the value returned here won't matter in that case.<br>
>> +    return 0;<br>
>> +  }<br>
>> +<br>
>>    /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic<br>
>>    /// block at the specified instruction (i.e. instruction would be the start<br>
>>    /// of a new basic block).<br>
>><br>
>> Modified: llvm/trunk/include/llvm/Target/TargetOptions.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/include/llvm/Target/TargetOptions.h (original)<br>
>> +++ llvm/trunk/include/llvm/Target/TargetOptions.h Tue Nov 11 15:08:02 2014<br>
>> @@ -57,6 +57,14 @@ namespace llvm {<br>
>>      };<br>
>>    }<br>
>><br>
>> +  enum class CFIntegrity {<br>
>> +    Sub,             // Use subtraction-based checks.<br>
>> +    Ror,             // Use rotation-based checks.<br>
>> +    Add              // Use addition-based checks. This depends on having<br>
>> +                     // sufficient alignment in the code and is usually not<br>
>> +                     // feasible.<br>
>> +  };<br>
>> +<br>
>>    class TargetOptions {<br>
>>    public:<br>
>>      TargetOptions()<br>
>> @@ -70,10 +78,11 @@ namespace llvm {<br>
>>            EnableFastISel(false), PositionIndependentExecutable(false),<br>
>>            UseInitArray(false), DisableIntegratedAS(false),<br>
>>            CompressDebugSections(false), FunctionSections(false),<br>
>> -          DataSections(false), TrapUnreachable(false), TrapFuncName(""),<br>
>> +          DataSections(false), TrapUnreachable(false), TrapFuncName(),<br>
>>            FloatABIType(FloatABI::Default),<br>
>>            AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),<br>
>> -          ThreadModel(ThreadModel::POSIX) {}<br>
>> +          FCFI(false), ThreadModel(ThreadModel::POSIX),<br>
>> +          CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}<br>
>><br>
>>      /// PrintMachineCode - This flag is enabled when the -print-machineinstrs<br>
>>      /// option is specified on the command line, and should enable debugging<br>
>> @@ -228,10 +237,28 @@ namespace llvm {<br>
>>      /// create for functions that have the jumptable attribute.<br>
>>      JumpTable::JumpTableType JTType;<br>
>><br>
>> +    /// FCFI - This flags controls whether or not forward-edge control-flow<br>
>> +    /// integrity is applied.<br>
>> +    bool FCFI;<br>
>> +<br>
>>      /// ThreadModel - This flag specifies the type of threading model to assume<br>
>>      /// for things like atomics<br>
>>      ThreadModel::Model ThreadModel;<br>
>><br>
>> +    /// CFIType - This flag specifies the type of control-flow integrity check<br>
>> +    /// to add as a preamble to indirect calls.<br>
>> +    CFIntegrity CFIType;<br>
>> +<br>
>> +    /// CFIEnforcing - This flags controls whether or not CFI violations cause<br>
>> +    /// the program to halt.<br>
>> +    bool CFIEnforcing;<br>
>> +<br>
>> +    /// getCFIFuncName - If this returns a non-empty string, then this is the<br>
>> +    /// name of the function that will be called for each CFI violation in<br>
>> +    /// non-enforcing mode.<br>
>> +    std::string CFIFuncName;<br>
>> +    StringRef getCFIFuncName() const;<br>
>> +<br>
>>      /// Machine level options.<br>
>>      MCTargetOptions MCOptions;<br>
>>    };<br>
>><br>
>> Modified: llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -17,6 +17,7 @@<br>
>>  #include "llvm/Analysis/Passes.h"<br>
>>  #include "llvm/IR/Function.h"<br>
>>  #include "llvm/IR/Type.h"<br>
>> +#include "llvm/Support/MathExtras.h"<br>
>><br>
>>  using namespace llvm;<br>
>><br>
>> @@ -28,7 +29,21 @@ ImmutablePass *llvm::createJumpInstrTabl<br>
>>    return new JumpInstrTableInfo();<br>
>>  }<br>
>><br>
>> -JumpInstrTableInfo::JumpInstrTableInfo() : ImmutablePass(ID), Tables() {<br>
>> +ModulePass *llvm::createJumpInstrTableInfoPass(unsigned Bound) {<br>
>> +  // This cast is always safe, since Bound is always in a subset of uint64_t.<br>
>> +  uint64_t B = static_cast<uint64_t>(Bound);<br>
>> +  return new JumpInstrTableInfo(B);<br>
>> +}<br>
>> +<br>
>> +JumpInstrTableInfo::JumpInstrTableInfo(uint64_t ByteAlign)<br>
>> +    : ImmutablePass(ID), Tables(), ByteAlignment(ByteAlign) {<br>
>> +  if (!llvm::isPowerOf2_64(ByteAlign)) {<br>
>> +    // Note that we don't explicitly handle overflow here, since we handle the 0<br>
>> +    // case explicitly when a caller actually tries to create jumptable entries,<br>
>> +    // and this is the return value on overflow.<br>
>> +    ByteAlignment = llvm::NextPowerOf2(ByteAlign);<br>
>> +  }<br>
>> +<br>
>>    initializeJumpInstrTableInfoPass(*PassRegistry::getPassRegistry());<br>
>>  }<br>
>><br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -879,16 +879,17 @@ bool AsmPrinter::doFinalization(Module &<br>
>>      bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);<br>
>>      MCInst TrapInst;<br>
>>      TM.getSubtargetImpl()->getInstrInfo()->getTrap(TrapInst);<br>
>> +    unsigned LogAlignment = llvm::Log2_64(JITI->entryByteAlignment());<br>
>> +<br>
>> +    // Emit the right section for these functions.<br>
>> +    OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection());<br>
>>      for (const auto &KV : JITI->getTables()) {<br>
>>        uint64_t Count = 0;<br>
>>        for (const auto &FunPair : KV.second) {<br>
>>          // Emit the function labels to make this be a function entry point.<br>
>>          MCSymbol *FunSym =<br>
>>            OutContext.GetOrCreateSymbol(FunPair.second->getName());<br>
>> -        OutStreamer.EmitSymbolAttribute(FunSym, MCSA_Global);<br>
>> -        // FIXME: JumpTableInstrInfo should store information about the required<br>
>> -        // alignment of table entries and the size of the padding instruction.<br>
>> -        EmitAlignment(3);<br>
>> +        EmitAlignment(LogAlignment);<br>
>>          if (IsThumb)<br>
>>            OutStreamer.EmitThumbFunc(FunSym);<br>
>>          if (MAI->hasDotTypeDotSizeDirective())<br>
>> @@ -910,10 +911,9 @@ bool AsmPrinter::doFinalization(Module &<br>
>>        }<br>
>><br>
>>        // Emit enough padding instructions to fill up to the next power of two.<br>
>> -      // This assumes that the trap instruction takes 8 bytes or fewer.<br>
>>        uint64_t Remaining = NextPowerOf2(Count) - Count;<br>
>>        for (uint64_t C = 0; C < Remaining; ++C) {<br>
>> -        EmitAlignment(3);<br>
>> +        EmitAlignment(LogAlignment);<br>
>>          OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo());<br>
>>        }<br>
>><br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)<br>
>> +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Tue Nov 11 15:08:02 2014<br>
>> @@ -19,6 +19,7 @@ add_llvm_library(LLVMCodeGen<br>
>>    ExecutionDepsFix.cpp<br>
>>    ExpandISelPseudos.cpp<br>
>>    ExpandPostRAPseudos.cpp<br>
>> +  ForwardControlFlowIntegrity.cpp<br>
>>    GCMetadata.cpp<br>
>>    GCMetadataPrinter.cpp<br>
>>    GCStrategy.cpp<br>
>><br>
>> Added: llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp (added)<br>
>> +++ llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,375 @@<br>
>> +//===-- ForwardControlFlowIntegrity.cpp: Forward-Edge CFI -----------------===//<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +///<br>
>> +/// \file<br>
>> +/// \brief A pass that instruments code with fast checks for indirect calls and<br>
>> +/// hooks for a function to check violations.<br>
>> +///<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#define DEBUG_TYPE "cfi"<br>
>> +<br>
>> +#include "llvm/ADT/SmallVector.h"<br>
>> +#include "llvm/ADT/Statistic.h"<br>
>> +#include "llvm/Analysis/JumpInstrTableInfo.h"<br>
>> +#include "llvm/CodeGen/ForwardControlFlowIntegrity.h"<br>
>> +#include "llvm/CodeGen/JumpInstrTables.h"<br>
>> +#include "llvm/CodeGen/Passes.h"<br>
>> +#include "llvm/IR/Attributes.h"<br>
>> +#include "llvm/IR/CallSite.h"<br>
>> +#include "llvm/IR/Constants.h"<br>
>> +#include "llvm/IR/DerivedTypes.h"<br>
>> +#include "llvm/IR/Function.h"<br>
>> +#include "llvm/IR/GlobalValue.h"<br>
>> +#include "llvm/IR/Instructions.h"<br>
>> +#include "llvm/IR/InlineAsm.h"<br>
>> +#include "llvm/IR/IRBuilder.h"<br>
>> +#include "llvm/IR/LLVMContext.h"<br>
>> +#include "llvm/IR/Module.h"<br>
>> +#include "llvm/IR/Operator.h"<br>
>> +#include "llvm/IR/Type.h"<br>
>> +#include "llvm/IR/Verifier.h"<br>
>> +#include "llvm/Pass.h"<br>
>> +#include "llvm/Support/CommandLine.h"<br>
>> +#include "llvm/Support/Debug.h"<br>
>> +#include "llvm/Support/raw_ostream.h"<br>
>> +<br>
>> +using namespace llvm;<br>
>> +<br>
>> +STATISTIC(NumCFIIndirectCalls,<br>
>> +          "Number of indirect call sites rewritten by the CFI pass");<br>
>> +<br>
>> +char ForwardControlFlowIntegrity::ID = 0;<br>
>> +INITIALIZE_PASS_BEGIN(ForwardControlFlowIntegrity, "forward-cfi",<br>
>> +                      "Control-Flow Integrity", true, true)<br>
>> +INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo);<br>
>> +INITIALIZE_PASS_DEPENDENCY(JumpInstrTables);<br>
>> +INITIALIZE_PASS_END(ForwardControlFlowIntegrity, "forward-cfi",<br>
>> +                    "Control-Flow Integrity", true, true)<br>
>> +<br>
>> +ModulePass *llvm::createForwardControlFlowIntegrityPass() {<br>
>> +  return new ForwardControlFlowIntegrity();<br>
>> +}<br>
>> +<br>
>> +ModulePass *llvm::createForwardControlFlowIntegrityPass(<br>
>> +    JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing,<br>
>> +    StringRef CFIFuncName) {<br>
>> +  return new ForwardControlFlowIntegrity(JTT, CFIType, CFIEnforcing,<br>
>> +                                         CFIFuncName);<br>
>> +}<br>
>> +<br>
>> +// Checks to see if a given CallSite is making an indirect call, including<br>
>> +// cases where the indirect call is made through a bitcast.<br>
>> +static bool isIndirectCall(CallSite &CS) {<br>
>> +  if (CS.getCalledFunction())<br>
>> +    return false;<br>
>> +<br>
>> +  // Check the value to see if it is merely a bitcast of a function. In<br>
>> +  // this case, it will translate to a direct function call in the resulting<br>
>> +  // assembly, so we won't treat it as an indirect call here.<br>
>> +  const Value *V = CS.getCalledValue();<br>
>> +  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {<br>
>> +    return !(CE->isCast() && isa<Function>(CE->getOperand(0)));<br>
>> +  }<br>
>> +<br>
>> +  // Otherwise, since we know it's a call, it must be an indirect call<br>
>> +  return true;<br>
>> +}<br>
>> +<br>
>> +static const char cfi_failure_func_name[] = "__llvm_cfi_pointer_warning";<br>
>> +static const char cfi_func_name_prefix[] = "__llvm_cfi_function_";<br>
>> +<br>
>> +ForwardControlFlowIntegrity::ForwardControlFlowIntegrity()<br>
>> +    : ModulePass(ID), IndirectCalls(), JTType(JumpTable::Single),<br>
>> +      CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName("") {<br>
>> +  initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry());<br>
>> +}<br>
>> +<br>
>> +ForwardControlFlowIntegrity::ForwardControlFlowIntegrity(<br>
>> +    JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing,<br>
>> +    std::string CFIFuncName)<br>
>> +    : ModulePass(ID), IndirectCalls(), JTType(JTT), CFIType(CFIType),<br>
>> +      CFIEnforcing(CFIEnforcing), CFIFuncName(CFIFuncName) {<br>
>> +  initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry());<br>
>> +}<br>
>> +<br>
>> +ForwardControlFlowIntegrity::~ForwardControlFlowIntegrity() {}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::getAnalysisUsage(AnalysisUsage &AU) const {<br>
>> +  AU.addRequired<JumpInstrTableInfo>();<br>
>> +  AU.addRequired<JumpInstrTables>();<br>
>> +}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::getIndirectCalls(Module &M) {<br>
>> +  // To get the indirect calls, we iterate over all functions and iterate over<br>
>> +  // the list of basic blocks in each. We extract a total list of indirect calls<br>
>> +  // before modifying any of them, since our modifications will modify the list<br>
>> +  // of basic blocks.<br>
>> +  for (Function &F : M) {<br>
>> +    for (BasicBlock &BB : F) {<br>
>> +      for (Instruction &I : BB) {<br>
>> +        CallSite CS(&I);<br>
>> +        if (!(CS && isIndirectCall(CS)))<br>
>> +          continue;<br>
>> +<br>
>> +        Value *CalledValue = CS.getCalledValue();<br>
>> +<br>
>> +        // Don't rewrite this instruction if the indirect call is actually just<br>
>> +        // inline assembly, since our transformation will generate an invalid<br>
>> +        // module in that case.<br>
>> +        if (isa<InlineAsm>(CalledValue))<br>
>> +          continue;<br>
>> +<br>
>> +        IndirectCalls.push_back(&I);<br>
>> +      }<br>
>> +    }<br>
>> +  }<br>
>> +}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::updateIndirectCalls(Module &M,<br>
>> +                                                      CFITables &CFIT) {<br>
>> +  Type *Int64Ty = Type::getInt64Ty(M.getContext());<br>
>> +  for (Instruction *I : IndirectCalls) {<br>
>> +    CallSite CS(I);<br>
>> +    Value *CalledValue = CS.getCalledValue();<br>
>> +<br>
>> +    // Get the function type for this call and look it up in the tables.<br>
>> +    Type *VTy = CalledValue->getType();<br>
>> +    PointerType *PTy = dyn_cast<PointerType>(VTy);<br>
>> +    Type *EltTy = PTy->getElementType();<br>
>> +    FunctionType *FunTy = dyn_cast<FunctionType>(EltTy);<br>
>> +    FunctionType *TransformedTy = JumpInstrTables::transformType(JTType, FunTy);<br>
>> +    ++NumCFIIndirectCalls;<br>
>> +    Constant *JumpTableStart = nullptr;<br>
>> +    Constant *JumpTableMask = nullptr;<br>
>> +    Constant *JumpTableSize = nullptr;<br>
>> +<br>
>> +    // Some call sites have function types that don't correspond to any<br>
>> +    // address-taken function in the module. This happens when function pointers<br>
>> +    // are passed in from external code.<br>
>> +    auto it = CFIT.find(TransformedTy);<br>
>> +    if (it == CFIT.end()) {<br>
>> +      // In this case, make sure that the function pointer will change by<br>
>> +      // setting the mask and the start to be 0 so that the transformed<br>
>> +      // function is 0.<br>
>> +      JumpTableStart = ConstantInt::get(Int64Ty, 0);<br>
>> +      JumpTableMask = ConstantInt::get(Int64Ty, 0);<br>
>> +      JumpTableSize = ConstantInt::get(Int64Ty, 0);<br>
>> +    } else {<br>
>> +      JumpTableStart = it->second.StartValue;<br>
>> +      JumpTableMask = it->second.MaskValue;<br>
>> +      JumpTableSize = it->second.Size;<br>
>> +    }<br>
>> +<br>
>> +    rewriteFunctionPointer(M, I, CalledValue, JumpTableStart, JumpTableMask,<br>
>> +                           JumpTableSize);<br>
>> +  }<br>
>> +<br>
>> +  return;<br>
>> +}<br>
>> +<br>
>> +bool ForwardControlFlowIntegrity::runOnModule(Module &M) {<br>
>> +  JumpInstrTableInfo *JITI = &getAnalysis<JumpInstrTableInfo>();<br>
>> +  Type *Int64Ty = Type::getInt64Ty(M.getContext());<br>
>> +  Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());<br>
>> +<br>
>> +  // JumpInstrTableInfo stores information about the alignment of each entry.<br>
>> +  // The alignment returned by JumpInstrTableInfo is alignment in bytes, not<br>
>> +  // in the exponent.<br>
>> +  ByteAlignment = JITI->entryByteAlignment();<br>
>> +  LogByteAlignment = llvm::Log2_64(ByteAlignment);<br>
>> +<br>
>> +  // Set up tables for control-flow integrity based on information about the<br>
>> +  // jump-instruction tables.<br>
>> +  CFITables CFIT;<br>
>> +  for (const auto &KV : JITI->getTables()) {<br>
>> +    uint64_t Size = static_cast<uint64_t>(KV.second.size());<br>
>> +    uint64_t TableSize = NextPowerOf2(Size);<br>
>> +<br>
>> +    int64_t MaskValue = ((TableSize << LogByteAlignment) - 1) & -ByteAlignment;<br>
>> +    Constant *JumpTableMaskValue = ConstantInt::get(Int64Ty, MaskValue);<br>
>> +    Constant *JumpTableSize = ConstantInt::get(Int64Ty, Size);<br>
>> +<br>
>> +    // The base of the table is defined to be the first jumptable function in<br>
>> +    // the table.<br>
>> +    Function *First = KV.second.begin()->second;<br>
>> +    Constant *JumpTableStartValue = ConstantExpr::getBitCast(First, VoidPtrTy);<br>
>> +    CFIT[KV.first].StartValue = JumpTableStartValue;<br>
>> +    CFIT[KV.first].MaskValue = JumpTableMaskValue;<br>
>> +    CFIT[KV.first].Size = JumpTableSize;<br>
>> +  }<br>
>> +<br>
>> +  if (CFIT.empty())<br>
>> +    return false;<br>
>> +<br>
>> +  getIndirectCalls(M);<br>
>> +<br>
>> +  if (!CFIEnforcing) {<br>
>> +    addWarningFunction(M);<br>
>> +  }<br>
>> +<br>
>> +  // Update the instructions with the check and the indirect jump through our<br>
>> +  // table.<br>
>> +  updateIndirectCalls(M, CFIT);<br>
>> +<br>
>> +  return true;<br>
>> +}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::addWarningFunction(Module &M) {<br>
>> +  PointerType *CharPtrTy = Type::getInt8PtrTy(M.getContext());<br>
>> +<br>
>> +  // Get the type of the Warning Function: void (i8*, i8*),<br>
>> +  // where the first argument is the name of the function in which the violation<br>
>> +  // occurs, and the second is the function pointer that violates CFI.<br>
>> +  SmallVector<Type *, 2> WarningFunArgs;<br>
>> +  WarningFunArgs.push_back(CharPtrTy);<br>
>> +  WarningFunArgs.push_back(CharPtrTy);<br>
>> +  FunctionType *WarningFunTy =<br>
>> +      FunctionType::get(Type::getVoidTy(M.getContext()), WarningFunArgs, false);<br>
>> +<br>
>> +  if (!CFIFuncName.empty()) {<br>
>> +    Constant *FailureFun = M.getOrInsertFunction(CFIFuncName, WarningFunTy);<br>
>> +    if (!FailureFun)<br>
>> +      report_fatal_error("Could not get or insert the function specified by"<br>
>> +                         " -cfi-func-name");<br>
>> +  } else {<br>
>> +    // The default warning function swallows the warning and lets the call<br>
>> +    // continue, since there's no generic way for it to print out this<br>
>> +    // information.<br>
>> +    Function *WarningFun = M.getFunction(cfi_failure_func_name);<br>
>> +    if (!WarningFun) {<br>
>> +      WarningFun =<br>
>> +          Function::Create(WarningFunTy, GlobalValue::LinkOnceAnyLinkage,<br>
>> +                           cfi_failure_func_name, &M);<br>
>> +    }<br>
>> +<br>
>> +    BasicBlock *Entry =<br>
>> +        BasicBlock::Create(M.getContext(), "entry", WarningFun, 0);<br>
>> +    ReturnInst::Create(M.getContext(), Entry);<br>
>> +  }<br>
>> +}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::rewriteFunctionPointer(<br>
>> +    Module &M, Instruction *I, Value *FunPtr, Constant *JumpTableStart,<br>
>> +    Constant *JumpTableMask, Constant *JumpTableSize) {<br>
>> +  IRBuilder<> TempBuilder(I);<br>
>> +<br>
>> +  Type *OrigFunType = FunPtr->getType();<br>
>> +<br>
>> +  BasicBlock *CurBB = cast<BasicBlock>(I->getParent());<br>
>> +  Function *CurF = cast<Function>(CurBB->getParent());<br>
>> +  Type *Int64Ty = Type::getInt64Ty(M.getContext());<br>
>> +<br>
>> +  Value *TI = TempBuilder.CreatePtrToInt(FunPtr, Int64Ty);<br>
>> +  Value *TStartInt = TempBuilder.CreatePtrToInt(JumpTableStart, Int64Ty);<br>
>> +<br>
>> +  Value *NewFunPtr = nullptr;<br>
>> +  Value *Check = nullptr;<br>
>> +  switch (CFIType) {<br>
>> +  case CFIntegrity::Sub: {<br>
>> +    // This is the subtract, mask, and add version.<br>
>> +    // Subtract from the base.<br>
>> +    Value *Sub = TempBuilder.CreateSub(TI, TStartInt);<br>
>> +<br>
>> +    // Mask the difference to force this to be a table offset.<br>
>> +    Value *And = TempBuilder.CreateAnd(Sub, JumpTableMask);<br>
>> +<br>
>> +    // Add it back to the base.<br>
>> +    Value *Result = TempBuilder.CreateAdd(And, TStartInt);<br>
>> +<br>
>> +    // Convert it back into a function pointer that we can call.<br>
>> +    NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType);<br>
>> +    break;<br>
>> +  }<br>
>> +  case CFIntegrity::Ror: {<br>
>> +    // This is the subtract and rotate version.<br>
>> +    // Rotate right by the alignment value. The optimizer should recognize<br>
>> +    // this sequence as a rotation.<br>
>> +<br>
>> +    // This cast is safe, since unsigned is always a subset of uint64_t.<br>
>> +    uint64_t LogByteAlignment64 = static_cast<uint64_t>(LogByteAlignment);<br>
>> +    Constant *RightShift = ConstantInt::get(Int64Ty, LogByteAlignment64);<br>
>> +    Constant *LeftShift = ConstantInt::get(Int64Ty, 64 - LogByteAlignment64);<br>
>> +<br>
>> +    // Subtract from the base.<br>
>> +    Value *Sub = TempBuilder.CreateSub(TI, TStartInt);<br>
>> +<br>
>> +    // Create the equivalent of a rotate-right instruction.<br>
>> +    Value *Shr = TempBuilder.CreateLShr(Sub, RightShift);<br>
>> +    Value *Shl = TempBuilder.CreateShl(Sub, LeftShift);<br>
>> +    Value *Or = TempBuilder.CreateOr(Shr, Shl);<br>
>> +<br>
>> +    // Perform unsigned comparison to check for inclusion in the table.<br>
>> +    Check = TempBuilder.CreateICmpULT(Or, JumpTableSize);<br>
>> +    NewFunPtr = FunPtr;<br>
>> +    break;<br>
>> +  }<br>
>> +  case CFIntegrity::Add: {<br>
>> +    // This is the mask and add version.<br>
>> +    // Mask the function pointer to turn it into an offset into the table.<br>
>> +    Value *And = TempBuilder.CreateAnd(TI, JumpTableMask);<br>
>> +<br>
>> +    // Then or this offset to the base and get the pointer value.<br>
>> +    Value *Result = TempBuilder.CreateAdd(And, TStartInt);<br>
>> +<br>
>> +    // Convert it back into a function pointer that we can call.<br>
>> +    NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType);<br>
>> +    break;<br>
>> +  }<br>
>> +  }<br>
>> +<br>
>> +  if (!CFIEnforcing) {<br>
>> +    // If a check hasn't been added (in the rotation version), then check to see<br>
>> +    // if it's the same as the original function. This check determines whether<br>
>> +    // or not we call the CFI failure function.<br>
>> +    if (!Check)<br>
>> +      Check = TempBuilder.CreateICmpEQ(NewFunPtr, FunPtr);<br>
>> +    BasicBlock *InvalidPtrBlock =<br>
>> +        BasicBlock::Create(M.getContext(), "invalid.ptr", CurF, 0);<br>
>> +    BasicBlock *ContinuationBB = CurBB->splitBasicBlock(I);<br>
>> +<br>
>> +    // Remove the unconditional branch that connects the two blocks.<br>
>> +    TerminatorInst *TermInst = CurBB->getTerminator();<br>
>> +    TermInst->eraseFromParent();<br>
>> +<br>
>> +    // Add a conditional branch that depends on the Check above.<br>
>> +    BranchInst::Create(ContinuationBB, InvalidPtrBlock, Check, CurBB);<br>
>> +<br>
>> +    // Call the warning function for this pointer, then continue.<br>
>> +    Instruction *BI = BranchInst::Create(ContinuationBB, InvalidPtrBlock);<br>
>> +    insertWarning(M, InvalidPtrBlock, BI, FunPtr);<br>
>> +  } else {<br>
>> +    // Modify the instruction to call this value.<br>
>> +    CallSite CS(I);<br>
>> +    CS.setCalledFunction(NewFunPtr);<br>
>> +  }<br>
>> +}<br>
>> +<br>
>> +void ForwardControlFlowIntegrity::insertWarning(Module &M, BasicBlock *Block,<br>
>> +                                                Instruction *I, Value *FunPtr) {<br>
>> +  Function *ParentFun = cast<Function>(Block->getParent());<br>
>> +<br>
>> +  // Get the function to call right before the instruction.<br>
>> +  Function *WarningFun = nullptr;<br>
>> +  if (CFIFuncName.empty()) {<br>
>> +    WarningFun = M.getFunction(cfi_failure_func_name);<br>
>> +  } else {<br>
>> +    WarningFun = M.getFunction(CFIFuncName);<br>
>> +  }<br>
>> +<br>
>> +  assert(WarningFun && "Could not find the CFI failure function");<br>
>> +<br>
>> +  Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());<br>
>> +<br>
>> +  IRBuilder<> WarningInserter(I);<br>
>> +  // Create a mergeable GlobalVariable containing the name of the function.<br>
>> +  Value *ParentNameGV =<br>
>> +      WarningInserter.CreateGlobalString(ParentFun->getName());<br>
>> +  Value *ParentNamePtr = WarningInserter.CreateBitCast(ParentNameGV, VoidPtrTy);<br>
>> +  Value *FunVoidPtr = WarningInserter.CreateBitCast(FunPtr, VoidPtrTy);<br>
>> +  WarningInserter.CreateCall2(WarningFun, ParentNamePtr, FunVoidPtr);<br>
>> +}<br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/JumpInstrTables.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/JumpInstrTables.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/JumpInstrTables.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/JumpInstrTables.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/JumpInstrTables.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -163,7 +163,7 @@ void JumpInstrTables::getAnalysisUsage(A<br>
>><br>
>>  Function *JumpInstrTables::insertEntry(Module &M, Function *Target) {<br>
>>    FunctionType *OrigFunTy = Target->getFunctionType();<br>
>> -  FunctionType *FunTy = transformType(OrigFunTy);<br>
>> +  FunctionType *FunTy = transformType(JTType, OrigFunTy);<br>
>><br>
>>    JumpMap::iterator it = Metadata.find(FunTy);<br>
>>    if (Metadata.end() == it) {<br>
>> @@ -191,11 +191,12 @@ Function *JumpInstrTables::insertEntry(M<br>
>>  }<br>
>><br>
>>  bool JumpInstrTables::hasTable(FunctionType *FunTy) {<br>
>> -  FunctionType *TransTy = transformType(FunTy);<br>
>> +  FunctionType *TransTy = transformType(JTType, FunTy);<br>
>>    return Metadata.end() != Metadata.find(TransTy);<br>
>>  }<br>
>><br>
>> -FunctionType *JumpInstrTables::transformType(FunctionType *FunTy) {<br>
>> +FunctionType *JumpInstrTables::transformType(JumpTable::JumpTableType JTT,<br>
>> +                                             FunctionType *FunTy) {<br>
>>    // Returning nullptr forces all types into the same table, since all types map<br>
>>    // to the same type<br>
>>    Type *VoidPtrTy = Type::getInt8PtrTy(FunTy->getContext());<br>
>> @@ -211,7 +212,7 @@ FunctionType *JumpInstrTables::transform<br>
>>    Type *Int32Ty = Type::getInt32Ty(FunTy->getContext());<br>
>>    FunctionType *VoidFnTy = FunctionType::get(<br>
>>        Type::getVoidTy(FunTy->getContext()), EmptyParams, false);<br>
>> -  switch (JTType) {<br>
>> +  switch (JTT) {<br>
>>    case JumpTable::Single:<br>
>><br>
>>      return FunctionType::get(RetTy, EmptyParams, false);<br>
>> @@ -253,10 +254,10 @@ FunctionType *JumpInstrTables::transform<br>
>>  bool JumpInstrTables::runOnModule(Module &M) {<br>
>>    JITI = &getAnalysis<JumpInstrTableInfo>();<br>
>><br>
>> -  // Get the set of jumptable-annotated functions.<br>
>> +  // Get the set of jumptable-annotated functions that have their address taken.<br>
>>    DenseMap<Function *, Function *> Functions;<br>
>>    for (Function &F : M) {<br>
>> -    if (F.hasFnAttribute(Attribute::JumpTable)) {<br>
>> +    if (F.hasFnAttribute(Attribute::JumpTable) && F.hasAddressTaken()) {<br>
>>        assert(F.hasUnnamedAddr() &&<br>
>>               "Attribute 'jumptable' requires 'unnamed_addr'");<br>
>>        Functions[&F] = nullptr;<br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -13,8 +13,10 @@<br>
>><br>
>>  #include "llvm/Target/TargetMachine.h"<br>
>><br>
>> +#include "llvm/Analysis/JumpInstrTableInfo.h"<br>
>>  #include "llvm/Analysis/Passes.h"<br>
>>  #include "llvm/CodeGen/AsmPrinter.h"<br>
>> +#include "llvm/CodeGen/ForwardControlFlowIntegrity.h"<br>
>>  #include "llvm/CodeGen/JumpInstrTables.h"<br>
>>  #include "llvm/CodeGen/MachineFunctionAnalysis.h"<br>
>>  #include "llvm/CodeGen/MachineModuleInfo.h"<br>
>> @@ -143,8 +145,13 @@ bool LLVMTargetMachine::addPassesToEmitF<br>
>>                                              AnalysisID StopAfter) {<br>
>>    // Passes to handle jumptable function annotations. These can't be handled at<br>
>>    // JIT time, so we don't add them directly to addPassesToGenerateCode.<br>
>> -  PM.add(createJumpInstrTableInfoPass());<br>
>> +  PM.add(createJumpInstrTableInfoPass(<br>
>> +      getSubtargetImpl()->getInstrInfo()->getJumpInstrTableEntryBound()));<br>
>>    PM.add(createJumpInstrTablesPass(Options.JTType));<br>
>> +  if (Options.FCFI)<br>
>> +    PM.add(createForwardControlFlowIntegrityPass(<br>
>> +        Options.JTType, Options.CFIType, Options.CFIEnforcing,<br>
>> +        Options.getCFIFuncName()));<br>
>><br>
>>    // Add common CodeGen passes.<br>
>>    MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,<br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -51,3 +51,10 @@ bool TargetOptions::HonorSignDependentRo<br>
>>  StringRef TargetOptions::getTrapFunctionName() const {<br>
>>    return TrapFuncName;<br>
>>  }<br>
>> +<br>
>> +/// getCFIFuncName - If this returns a non-empty string, then it is the name of<br>
>> +/// the function that gets called on CFI violations in CFI non-enforcing mode<br>
>> +/// (!TargetOptions::CFIEnforcing).<br>
>> +StringRef TargetOptions::getCFIFuncName() const {<br>
>> +  return CFIFuncName;<br>
>> +}<br>
>><br>
>> Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -4489,29 +4489,6 @@ breakPartialRegDependency(MachineBasicBl<br>
>>    MI->addRegisterKilled(DReg, TRI, true);<br>
>>  }<br>
>><br>
>> -void ARMBaseInstrInfo::getUnconditionalBranch(<br>
>> -    MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {<br>
>> -  if (Subtarget.isThumb())<br>
>> -    Branch.setOpcode(ARM::tB);<br>
>> -  else if (Subtarget.isThumb2())<br>
>> -    Branch.setOpcode(ARM::t2B);<br>
>> -  else<br>
>> -    Branch.setOpcode(ARM::Bcc);<br>
>> -<br>
>> -  Branch.addOperand(MCOperand::CreateExpr(BranchTarget));<br>
>> -  Branch.addOperand(MCOperand::CreateImm(ARMCC::AL));<br>
>> -  Branch.addOperand(MCOperand::CreateReg(0));<br>
>> -}<br>
>> -<br>
>> -void ARMBaseInstrInfo::getTrap(MCInst &MI) const {<br>
>> -  if (Subtarget.isThumb())<br>
>> -    MI.setOpcode(ARM::tTRAP);<br>
>> -  else if (Subtarget.useNaClTrap())<br>
>> -    MI.setOpcode(ARM::TRAPNaCl);<br>
>> -  else<br>
>> -    MI.setOpcode(ARM::TRAP);<br>
>> -}<br>
>> -<br>
>>  bool ARMBaseInstrInfo::hasNOP() const {<br>
>>    return (Subtarget.getFeatureBits() & ARM::HasV6T2Ops) != 0;<br>
>>  }<br>
>><br>
>> Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)<br>
>> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Tue Nov 11 15:08:02 2014<br>
>> @@ -289,12 +289,6 @@ public:<br>
>>    void breakPartialRegDependency(MachineBasicBlock::iterator, unsigned,<br>
>>                                   const TargetRegisterInfo *TRI) const override;<br>
>><br>
>> -  void<br>
>> -  getUnconditionalBranch(MCInst &Branch,<br>
>> -                         const MCSymbolRefExpr *BranchTarget) const override;<br>
>> -<br>
>> -  void getTrap(MCInst &MI) const override;<br>
>> -<br>
>>    /// Get the number of addresses by LDM or VLDM or zero for unknown.<br>
>>    unsigned getNumLDMAddresses(const MachineInstr *MI) const;<br>
>><br>
>><br>
>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Nov 11 15:08:02 2014<br>
>> @@ -5477,16 +5477,32 @@ void X86InstrInfo::getNoopForMachoTarget<br>
>>    NopInst.setOpcode(X86::NOOP);<br>
>>  }<br>
>><br>
>> +// This code must remain in sync with getJumpInstrTableEntryBound in this class!<br>
>> +// In particular, getJumpInstrTableEntryBound must always return an upper bound<br>
>> +// on the encoding lengths of the instructions generated by<br>
>> +// getUnconditionalBranch and getTrap.<br>
>>  void X86InstrInfo::getUnconditionalBranch(<br>
>>      MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {<br>
>>    Branch.setOpcode(X86::JMP_4);<br>
>>    Branch.addOperand(MCOperand::CreateExpr(BranchTarget));<br>
>>  }<br>
>><br>
>> +// This code must remain in sync with getJumpInstrTableEntryBound in this class!<br>
>> +// In particular, getJumpInstrTableEntryBound must always return an upper bound<br>
>> +// on the encoding lengths of the instructions generated by<br>
>> +// getUnconditionalBranch and getTrap.<br>
>>  void X86InstrInfo::getTrap(MCInst &MI) const {<br>
>>    MI.setOpcode(X86::TRAP);<br>
>>  }<br>
>><br>
>> +// See getTrap and getUnconditionalBranch for conditions on the value returned<br>
>> +// by this function.<br>
>> +unsigned X86InstrInfo::getJumpInstrTableEntryBound() const {<br>
>> +  // 5 bytes suffice: JMP_4 Symbol@PLT is uses 1 byte (E9) for the JMP_4 and 4<br>
>> +  // bytes for the symbol offset. And TRAP is ud2, which is two bytes (0F 0B).<br>
>> +  return 5;<br>
>> +}<br>
>> +<br>
>>  bool X86InstrInfo::isHighLatencyDef(int opc) const {<br>
>>    switch (opc) {<br>
>>    default: return false;<br>
>><br>
>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)<br>
>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Tue Nov 11 15:08:02 2014<br>
>> @@ -413,6 +413,8 @@ public:<br>
>><br>
>>    void getTrap(MCInst &MI) const override;<br>
>><br>
>> +  unsigned getJumpInstrTableEntryBound() const override;<br>
>> +<br>
>>    bool isHighLatencyDef(int opc) const override;<br>
>><br>
>>    bool hasHighOperandLatency(const InstrItineraryData *ItinData,<br>
>><br>
>> Removed: llvm/trunk/test/CodeGen/ARM/jump_tables.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/jump_tables.ll?rev=221707&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/jump_tables.ll?rev=221707&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/ARM/jump_tables.ll (original)<br>
>> +++ llvm/trunk/test/CodeGen/ARM/jump_tables.ll (removed)<br>
>> @@ -1,32 +0,0 @@<br>
>> -; RUN: llc <%s -mtriple=arm-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=ARM %s<br>
>> -; RUN: llc <%s -mtriple=thumb-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=THUMB %s<br>
>> -<br>
>> -define void @indirect_fun() unnamed_addr jumptable {<br>
>> -  ret void<br>
>> -}<br>
>> -define void ()* @get_fun() {<br>
>> -  ret void ()* @indirect_fun<br>
>> -<br>
>> -; ARM:         ldr     r0, [[LABEL:.*]]<br>
>> -; ARM:         mov     pc, lr<br>
>> -; ARM: [[LABEL]]:<br>
>> -; ARM:         .long   __llvm_jump_instr_table_0_1<br>
>> -<br>
>> -; THUMB:         ldr     r0, [[LABEL:.*]]<br>
>> -; THUMB:         bx      lr<br>
>> -; THUMB: [[LABEL]]:<br>
>> -; THUMB:         .long   __llvm_jump_instr_table_0_1<br>
>> -}<br>
>> -<br>
>> -; ARM:         .globl  __llvm_jump_instr_table_0_1<br>
>> -; ARM:         .align  3<br>
>> -; ARM:         .type   __llvm_jump_instr_table_0_1,%function<br>
>> -; ARM: __llvm_jump_instr_table_0_1:<br>
>> -; ARM:         b     indirect_fun(PLT)<br>
>> -<br>
>> -; THUMB:         .globl  __llvm_jump_instr_table_0_1<br>
>> -; THUMB:         .align  3<br>
>> -; THUMB:         .thumb_func<br>
>> -; THUMB:         .type   __llvm_jump_instr_table_0_1,%function<br>
>> -; THUMB: __llvm_jump_instr_table_0_1:<br>
>> -; THUMB:         b     indirect_fun(PLT)<br>
>><br>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll (added)<br>
>> +++ llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,34 @@<br>
>> +; RUN: llc -mtriple=i386-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86 %s<br>
>> +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86-64 %s<br>
>> +<br>
>> +define void @indirect_fun() unnamed_addr jumptable {<br>
>> +  ret void<br>
>> +}<br>
>> +<br>
>> +define i32 @m(void ()* %fun) {<br>
>> +  call void ()* %fun()<br>
>> +; CHECK: subl<br>
>> +; X86-64: andq    $8,<br>
>> +; X86-64: leaq    __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]]<br>
>> +; X86-64-NOT: callq __llvm_cfi_pointer_warning<br>
>> +; X86-64: callq   *[[REG]]<br>
>> +; X86: andl    $8,<br>
>> +; X86: leal    __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]]<br>
>> +; X86-NOT: calll __llvm_cfi_pointer_warning<br>
>> +; X86: calll   *[[REG]]<br>
>> +  ret i32 0<br>
>> +}<br>
>> +<br>
>> +define void ()* @get_fun() {<br>
>> +  ret void ()* @indirect_fun<br>
>> +}<br>
>> +<br>
>> +define i32 @main(i32 %argc, i8** %argv) {<br>
>> +  %f = call void ()* ()* @get_fun()<br>
>> +  %a = call i32 @m(void ()* %f)<br>
>> +  ret i32 %a<br>
>> +}<br>
>> +<br>
>> +; CHECK: .align 8<br>
>> +; CHECK: __llvm_jump_instr_table_0_1:<br>
>> +; CHECK: jmp indirect_fun@PLT<br>
>><br>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_invoke.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_invoke.ll?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_invoke.ll?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/cfi_invoke.ll (added)<br>
>> +++ llvm/trunk/test/CodeGen/X86/cfi_invoke.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,35 @@<br>
>> +; RUN: llc <%s -fcfi -cfi-type=sub | FileCheck %s<br>
>> +; ModuleID = 'test.cc'<br>
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
>> +target triple = "x86_64-unknown-linux-gnu"<br>
>> +<br>
>> +declare i32 @__gxx_personality_v0(...)<br>
>> +<br>
>> +@_ZTIPKc = external constant i8*<br>
>> +@_ZTIi = external constant i8*<br>
>> +<br>
>> +define void @f() unnamed_addr jumptable {<br>
>> +  ret void<br>
>> +}<br>
>> +<br>
>> +@a = global void ()* @f<br>
>> +<br>
>> +; Make sure invoke gets targeted as well as regular calls<br>
>> +define void @_Z3foov(void ()* %f) uwtable ssp {<br>
>> +; CHECK-LABEL: _Z3foov:<br>
>> + entry:<br>
>> +   invoke void %f()<br>
>> +           to label %try.cont unwind label %lpad<br>
>> +; CHECK: callq __llvm_cfi_pointer_warning<br>
>> +; CHECK: callq *%rbx<br>
>> +<br>
>> + lpad:<br>
>> +   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)<br>
>> +                                  catch i8* bitcast (i8** @_ZTIi to i8*)<br>
>> +                                  filter [1 x i8*] [i8* bitcast (i8** @_ZTIPKc to i8*)]<br>
>> +   ret void<br>
>> +<br>
>> + try.cont:<br>
>> +   ret void<br>
>> +}<br>
>> +<br>
>><br>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll (added)<br>
>> +++ llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,27 @@<br>
>> +; RUN: llc -fcfi -cfi-func-name=cfi_new_failure <%s | FileCheck %s<br>
>> +<br>
>> +target triple = "x86_64-unknown-linux-gnu"<br>
>> +define void @indirect_fun() unnamed_addr jumptable {<br>
>> +  ret void<br>
>> +}<br>
>> +<br>
>> +define i32 @m(void ()* %fun) {<br>
>> +; CHECK-LABEL: @m<br>
>> +  call void ()* %fun()<br>
>> +; CHECK: callq cfi_new_failure<br>
>> +  ret i32 0<br>
>> +}<br>
>> +<br>
>> +define void ()* @get_fun() {<br>
>> +  ret void ()* @indirect_fun<br>
>> +}<br>
>> +<br>
>> +define i32 @main(i32 %argc, i8** %argv) {<br>
>> +  %f = call void ()* ()* @get_fun()<br>
>> +  %a = call i32 @m(void ()* %f)<br>
>> +  ret i32 %a<br>
>> +}<br>
>> +<br>
>> +; CHECK: .align 8<br>
>> +; CHECK: __llvm_jump_instr_table_0_1:<br>
>> +; CHECK: jmp indirect_fun@PLT<br>
>><br>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll (added)<br>
>> +++ llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,43 @@<br>
>> +; RUN: llc -fcfi -cfi-type=sub <%s | FileCheck --check-prefix=SUB %s<br>
>> +; RUN: llc -fcfi -cfi-type=add <%s | FileCheck --check-prefix=ADD %s<br>
>> +; RUN: llc -fcfi -cfi-type=ror <%s | FileCheck --check-prefix=ROR %s<br>
>> +<br>
>> +target triple = "x86_64-unknown-linux-gnu"<br>
>> +<br>
>> +define void @indirect_fun() unnamed_addr jumptable {<br>
>> +  ret void<br>
>> +}<br>
>> +<br>
>> +define i32 @m(void ()* %fun) {<br>
>> +  call void ()* %fun()<br>
>> +; SUB: subl<br>
>> +; SUB: andq    $8<br>
>> +; SUB-LABEL: leaq    __llvm_jump_instr_table_0_1<br>
>> +; SUB-LABEL: callq   __llvm_cfi_pointer_warning<br>
>> +<br>
>> +; ROR: subq<br>
>> +; ROR: rolq    $61<br>
>> +; ROR: testq<br>
>> +; ROR-LABEL: callq   __llvm_cfi_pointer_warning<br>
>> +<br>
>> +; ADD: andq    $8<br>
>> +; ADD-LABEL: leaq    __llvm_jump_instr_table_0_1<br>
>> +; ADD: cmpq<br>
>> +; ADD-LABEL: callq   __llvm_cfi_pointer_warning<br>
>> +ret i32 0<br>
>> +}<br>
>> +<br>
>> +define void ()* @get_fun() {<br>
>> +  ret void ()* @indirect_fun<br>
>> +}<br>
>> +<br>
>> +define i32 @main(i32 %argc, i8** %argv) {<br>
>> +  %f = call void ()* ()* @get_fun()<br>
>> +  %a = call i32 @m(void ()* %f)<br>
>> +  ret i32 %a<br>
>> +}<br>
>> +; SUB: .text<br>
>> +; SUB: .align 8<br>
>> +; SUB-LABEL: .type __llvm_jump_instr_table_0_1,@function<br>
>> +; SUB-LABEL:__llvm_jump_instr_table_0_1:<br>
>> +; SUB-LABEL: jmp indirect_fun@PLT<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_table_alias.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_alias.ll?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_alias.ll?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/jump_table_alias.ll (original)<br>
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_alias.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -25,7 +25,6 @@ define i32 @main(i32 %argc, i8** %argv)<br>
>>  ; There should only be one table, even though there are two GlobalAliases,<br>
>>  ; because they both alias the same value.<br>
>><br>
>> -; CHECK:         .globl  __llvm_jump_instr_table_0_1<br>
>>  ; CHECK:         .align  8, 0x90<br>
>>  ; CHECK:         .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; CHECK: __llvm_jump_instr_table_0_1:<br>
>><br>
>> Added: llvm/trunk/test/CodeGen/X86/jump_table_align.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_align.ll?rev=221708&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_align.ll?rev=221708&view=auto</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/jump_table_align.ll (added)<br>
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_align.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -0,0 +1,29 @@<br>
>> +; RUN: llc -filetype=obj <%s -jump-table-type=single -o %t1<br>
>> +; RUN: llvm-objdump -triple=x86_64-unknown-linux-gnu -d %t1 | FileCheck %s<br>
>> +target triple = "x86_64-unknown-linux-gnu"<br>
>> +define i32 @f() unnamed_addr jumptable {<br>
>> +  ret i32 0<br>
>> +}<br>
>> +<br>
>> +define i32 @g(i8* %a) unnamed_addr jumptable {<br>
>> +  ret i32 0<br>
>> +}<br>
>> +<br>
>> +define void @h(void ()* %func) unnamed_addr jumptable {<br>
>> +  ret void<br>
>> +}<br>
>> +<br>
>> +define i32 @main() {<br>
>> +  %g = alloca i32 (...)*, align 8<br>
>> +  store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8<br>
>> +  %1 = load i32 (...)** %g, align 8<br>
>> +  %call = call i32 (...)* %1()<br>
>> +  call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*))<br>
>> +  %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)<br>
>> +  ret i32 %a<br>
>> +}<br>
>> +<br>
>> +; Make sure that the padding from getJumpInstrTableEntryBound is right.<br>
>> +; CHECK: __llvm_jump_instr_table_0_1:<br>
>> +; CHECK-NEXT: e9 00 00 00 00                                  jmp     0<br>
>> +; CHECK-NEXT: 0f 1f 00                                        nopl    (%rax)<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll (original)<br>
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -15,12 +15,12 @@ define void @h(void ()* %func) unnamed_a<br>
>>  define i32 @main() {<br>
>>    %g = alloca i32 (...)*, align 8<br>
>>    store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8<br>
>> -; CHECK: movq    $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]], (%rsp)<br>
>> -; CHECK: movl    $__llvm_jump_instr_table_0_[[ENTRY]], %ecx<br>
>> +; CHECK: movq    $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]],<br>
>> +; CHECK: movl    $__llvm_jump_instr_table_0_[[ENTRY]],<br>
>>    %1 = load i32 (...)** %g, align 8<br>
>>    %call = call i32 (...)* %1()<br>
>>    call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*))<br>
>> -; CHECK: movl    $__llvm_jump_instr_table_0_{{1|2|3}}, %edi<br>
>> +; CHECK: movl    $__llvm_jump_instr_table_0_{{1|2|3}},<br>
>>  ; CHECK: callq   h<br>
>><br>
>>    %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)<br>
>> @@ -28,17 +28,14 @@ define i32 @main() {<br>
>>    ret i32 %a<br>
>>  }<br>
>><br>
>> -; CHECK:         .globl  __llvm_jump_instr_table_0_1<br>
>>  ; CHECK:         .align  8, 0x90<br>
>>  ; CHECK:         .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; CHECK: __llvm_jump_instr_table_0_1:<br>
>>  ; CHECK:         jmp     {{f|g|h}}@PLT<br>
>> -; CHECK:         .globl  __llvm_jump_instr_table_0_2<br>
>>  ; CHECK:         .align  8, 0x90<br>
>>  ; CHECK:         .type   __llvm_jump_instr_table_0_2,@function<br>
>>  ; CHECK: __llvm_jump_instr_table_0_2:<br>
>>  ; CHECK:         jmp     {{f|g|h}}@PLT<br>
>> -; CHECK:         .globl  __llvm_jump_instr_table_0_3<br>
>>  ; CHECK:         .align  8, 0x90<br>
>>  ; CHECK:         .type   __llvm_jump_instr_table_0_3,@function<br>
>>  ; CHECK: __llvm_jump_instr_table_0_3:<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_tables.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_tables.ll?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_tables.ll?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/CodeGen/X86/jump_tables.ll (original)<br>
>> +++ llvm/trunk/test/CodeGen/X86/jump_tables.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -7,6 +7,20 @@ target triple = "x86_64-unknown-linux-gn<br>
>><br>
>>  %struct.fun_struct = type { i32 (...)* }<br>
>><br>
>> +@a = global [12 x i32 () *] [ i32 ()* bitcast (void ()* @indirect_fun to i32 ()*),<br>
>> +                             i32 ()* bitcast (void ()* @indirect_fun_match to i32 ()*),<br>
>> +                             i32 ()* bitcast (i32 ()* @indirect_fun_i32 to i32 ()*),<br>
>> +                             i32 ()* bitcast (i32 (i32)* @indirect_fun_i32_1 to i32 ()*),<br>
>> +                             i32 ()* bitcast (i32 (i32, i32)* @indirect_fun_i32_2 to i32 ()*),<br>
>> +                             i32 ()* bitcast (i32* (i32*, i32)* @indirect_fun_i32S_2 to i32 ()*),<br>
>> +                             i32 ()* bitcast (void (%struct.fun_struct)* @indirect_fun_struct to i32 ()*),<br>
>> +                             i32 ()* bitcast (void (i32 (...)*, i32)* @indirect_fun_fun to i32 ()*),<br>
>> +                             i32 ()* bitcast (i32 (i32 (...)*, i32)* @indirect_fun_fun_ret to i32 ()*),<br>
>> +                             i32 ()* bitcast (void ([19 x i8])* @indirect_fun_array to i32 ()*),<br>
>> +                             i32 ()* bitcast (void (<3 x i32>)* @indirect_fun_vec to i32 ()*),<br>
>> +                             i32 ()* bitcast (void (<4 x float>)* @indirect_fun_vec_2 to i32 ()*)<br>
>> +                           ]<br>
>> +<br>
>>  define void @indirect_fun() unnamed_addr jumptable {<br>
>>    ret void<br>
>>  }<br>
>> @@ -74,62 +88,50 @@ define i32 @main(i32 %argc, i8** %argv)<br>
>>    ret i32 %a<br>
>>  }<br>
>><br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_1<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_1:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_array@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_2<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_2,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_2:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_i32_2@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_3<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_3,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_3:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_vec_2@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_4<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_4,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_4:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_i32S_2@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_5<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_5,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_5:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_struct@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_6<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_6,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_6:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_i32_1@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_7<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_7,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_7:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_i32@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_8<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_8,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_8:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_fun@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_9<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_9,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_9:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_fun_ret@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_10<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_10,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_10:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_11<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_11,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_11:<br>
>>  ; SINGLE-DAG:         jmp     indirect_fun_match@PLT<br>
>> -; SINGLE-DAG:         .globl  __llvm_jump_instr_table_0_12<br>
>>  ; SINGLE-DAG:         .align  8, 0x90<br>
>>  ; SINGLE-DAG:         .type   __llvm_jump_instr_table_0_12,@function<br>
>>  ; SINGLE-DAG: __llvm_jump_instr_table_0_12:<br>
>> @@ -144,82 +146,69 @@ define i32 @main(i32 %argc, i8** %argv)<br>
>>  ; SINGLE-DAG:         ud2<br>
>><br>
>><br>
>> -; ARITY-DAG:         .globl  __llvm_jump_instr_table_2_1<br>
>>  ; ARITY-DAG:         .align  8, 0x90<br>
>>  ; ARITY-DAG:         .type   __llvm_jump_instr_table_2_1,@function<br>
>>  ; ARITY-DAG: __llvm_jump_instr_table_2_1:<br>
>>  ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>>  ; ARITY-DAG:         .align  8, 0x90<br>
>>  ; ARITY-DAG:         ud2<br>
>> -; ARITY-DAG:         .globl  __llvm_jump_instr_table_0_1<br>
>>  ; ARITY-DAG:         .align  8, 0x90<br>
>>  ; ARITY-DAG:         .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; ARITY-DAG: __llvm_jump_instr_table_0_1:<br>
>>  ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>> -; ARITY-DAG:         .globl  __llvm_jump_instr_table_1_1<br>
>>  ; ARITY-DAG:         .align  8, 0x90<br>
>>  ; ARITY-DAG:         .type   __llvm_jump_instr_table_1_1,@function<br>
>>  ; ARITY-DAG: __llvm_jump_instr_table_1_1:<br>
>>  ; ARITY-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>><br>
>> -; SIMPL-DAG:         .globl  __llvm_jump_instr_table_2_1<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         .type   __llvm_jump_instr_table_2_1,@function<br>
>>  ; SIMPL-DAG: __llvm_jump_instr_table_2_1:<br>
>>  ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         ud2<br>
>> -; SIMPL-DAG:         .globl  __llvm_jump_instr_table_0_1<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; SIMPL-DAG: __llvm_jump_instr_table_0_1:<br>
>>  ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>> -; SIMPL-DAG:         .globl  __llvm_jump_instr_table_1_1<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         .type   __llvm_jump_instr_table_1_1,@function<br>
>>  ; SIMPL-DAG: __llvm_jump_instr_table_1_1:<br>
>>  ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>> -; SIMPL-DAG:         .globl  __llvm_jump_instr_table_3_1<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         .type   __llvm_jump_instr_table_3_1,@function<br>
>>  ; SIMPL-DAG: __llvm_jump_instr_table_3_1:<br>
>>  ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>> -; SIMPL-DAG:         .globl  __llvm_jump_instr_table_4_1<br>
>>  ; SIMPL-DAG:         .align  8, 0x90<br>
>>  ; SIMPL-DAG:         .type   __llvm_jump_instr_table_4_1,@function<br>
>>  ; SIMPL-DAG: __llvm_jump_instr_table_4_1:<br>
>>  ; SIMPL-DAG:         jmp     indirect_fun{{.*}}@PLT<br>
>><br>
>><br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_10_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_10_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_10_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_i32_1@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_9_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_9_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_9_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_i32_2@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_7_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_7_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_7_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_i32S_2@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_3_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_3_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_3_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_vec_2@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_2_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_2_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_2_1:<br>
>> @@ -228,42 +217,36 @@ define i32 @main(i32 %argc, i8** %argv)<br>
>>  ; FULL-DAG:        ud2<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_8_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_8_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_8_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_i32@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_1_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_1_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_1_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_array@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_0_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_0_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_0_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_vec@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_6_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_6_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_6_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_struct@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_5_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_5_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_5_1:<br>
>>  ; FULL-DAG:        jmp     indirect_fun_fun@PLT<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        ud2<br>
>> -; FULL-DAG:        .globl  __llvm_jump_instr_table_4_1<br>
>>  ; FULL-DAG:        .align  8, 0x90<br>
>>  ; FULL-DAG:        .type   __llvm_jump_instr_table_4_1,@function<br>
>>  ; FULL-DAG:__llvm_jump_instr_table_4_1:<br>
>><br>
>> Modified: llvm/trunk/test/LTO/jump-table-type.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/jump-table-type.ll?rev=221708&r1=221707&r2=221708&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/jump-table-type.ll?rev=221708&r1=221707&r2=221708&view=diff</a><br>
>> ==============================================================================<br>
>> --- llvm/trunk/test/LTO/jump-table-type.ll (original)<br>
>> +++ llvm/trunk/test/LTO/jump-table-type.ll Tue Nov 11 15:08:02 2014<br>
>> @@ -2,8 +2,8 @@<br>
>>  ; RUN: llvm-lto -o %t2 %t1 -jump-table-type=arity<br>
>>  ; RUN: llvm-nm %t2 | FileCheck %s<br>
>><br>
>> -; CHECK: T __llvm_jump_instr_table_0_1<br>
>> -; CHECK: T __llvm_jump_instr_table_1_1<br>
>> +; CHECK: t __llvm_jump_instr_table_0_1<br>
>> +; CHECK: t __llvm_jump_instr_table_1_1<br>
>><br>
>>  target triple = "x86_64-unknown-linux-gnu"<br>
>><br>
>><br>
>><br>
>> _______________________________________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>