[llvm] r210280 - Add a new attribute called 'jumptable' that creates jump-instruction tables for functions marked with this attribute.

Rafael EspĂ­ndola rafael.espindola at gmail.com
Thu Jun 5 12:58:19 PDT 2014


Since this is an IR->IR pass, can you add a testcase that runs just
the pass with opt?

On 5 June 2014 15:29, Tom Roeder <tmroeder at google.com> wrote:
> Author: tmroeder
> Date: Thu Jun  5 14:29:43 2014
> New Revision: 210280
>
> URL: http://llvm.org/viewvc/llvm-project?rev=210280&view=rev
> Log:
> Add a new attribute called 'jumptable' that creates jump-instruction tables for functions marked with this attribute.
> It includes a pass that rewrites all indirect calls to jumptable functions to pass through these tables.
>
> This also adds backend support for generating the jump-instruction tables on ARM and X86.
> Note that since the jumptable attribute creates a second function pointer for a
> function, any function marked with jumptable must also be marked with unnamed_addr.
>
> Added:
>     llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
>     llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
>     llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
>     llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
>     llvm/trunk/test/CodeGen/ARM/jump_tables.ll
>     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/Verifier/jumptable.ll
> Modified:
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm-c/Core.h
>     llvm/trunk/include/llvm/Analysis/Passes.h
>     llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
>     llvm/trunk/include/llvm/CodeGen/CommandFlags.h
>     llvm/trunk/include/llvm/CodeGen/Passes.h
>     llvm/trunk/include/llvm/IR/Attributes.h
>     llvm/trunk/include/llvm/InitializePasses.h
>     llvm/trunk/include/llvm/LinkAllPasses.h
>     llvm/trunk/include/llvm/Target/TargetInstrInfo.h
>     llvm/trunk/include/llvm/Target/TargetOptions.h
>     llvm/trunk/lib/Analysis/Analysis.cpp
>     llvm/trunk/lib/Analysis/CMakeLists.txt
>     llvm/trunk/lib/AsmParser/LLLexer.cpp
>     llvm/trunk/lib/AsmParser/LLParser.cpp
>     llvm/trunk/lib/AsmParser/LLToken.h
>     llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>     llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>     llvm/trunk/lib/CodeGen/CMakeLists.txt
>     llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
>     llvm/trunk/lib/IR/Attributes.cpp
>     llvm/trunk/lib/IR/Verifier.cpp
>     llvm/trunk/lib/LTO/LTOCodeGenerator.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/lib/Transforms/IPO/IPO.cpp
>     llvm/trunk/test/Bitcode/attributes.ll
>     llvm/trunk/test/CodeGen/Generic/stop-after.ll
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Thu Jun  5 14:29:43 2014
> @@ -1020,6 +1020,14 @@ example:
>      inlining this function is desirable (such as the "inline" keyword in
>      C/C++). It is just a hint; it imposes no requirements on the
>      inliner.
> +``jumptable``
> +    This attribute indicates that the function should be added to a
> +    jump-instruction table at code-generation time, and that all address-taken
> +    references to this function should be replaced with a reference to the
> +    appropriate jump-instruction-table function pointer. Note that this creates
> +    a new pointer for the original function, which means that code that depends
> +    on function-pointer identity can break. So, any function annotated with
> +    ``jumptable`` must also be ``unnamed_addr``.
>  ``minsize``
>      This attribute suggests that optimization passes and code generator
>      passes make choices that keep the code size of this function as small
>
> Modified: llvm/trunk/include/llvm-c/Core.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm-c/Core.h (original)
> +++ llvm/trunk/include/llvm-c/Core.h Thu Jun  5 14:29:43 2014
> @@ -166,7 +166,8 @@ typedef enum {
>      LLVMCold = 1ULL << 34,
>      LLVMOptimizeNone = 1ULL << 35,
>      LLVMInAllocaAttribute = 1ULL << 36,
> -    LLVMNonNullAttribute = 1ULL << 37
> +    LLVMNonNullAttribute = 1ULL << 37,
> +    LLVMJumpTableAttribute = 1ULL << 38,
>      */
>  } LLVMAttribute;
>
>
> Added: llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h (added)
> +++ llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,60 @@
> +//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===//
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +/// \brief Information about jump-instruction tables that have been created by
> +/// JumpInstrTables pass.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
> +#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
> +
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/Pass.h"
> +
> +#include <vector>
> +
> +namespace llvm {
> +class Function;
> +class FunctionType;
> +
> +/// This class stores information about jump-instruction tables created by the
> +/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a
> +/// map from a function type to a vector of pairs. The first element of each
> +/// pair is the function that has the jumptable annotation. The second element
> +/// is a function that was declared by JumpInstrTables and used to replace all
> +/// address-taking sites for the original function.
> +///
> +/// The information in this pass is used in AsmPrinter
> +/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly
> +/// for the jump-instruction tables.
> +class JumpInstrTableInfo : public ImmutablePass {
> +public:
> +  static char ID;
> +
> +  JumpInstrTableInfo();
> +  virtual ~JumpInstrTableInfo();
> +  const char *getPassName() const override {
> +    return "Jump-Instruction Table Info";
> +  }
> +
> +  typedef std::pair<Function *, Function *> JumpPair;
> +  typedef DenseMap<FunctionType *, std::vector<JumpPair> > JumpTables;
> +
> +  /// Inserts an entry in a table, adding the table if it doesn't exist.
> +  void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump);
> +
> +  /// Gets the tables.
> +  const JumpTables &getTables() const { return Tables; }
> +
> +private:
> +  JumpTables Tables;
> +};
> +}
> +
> +#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */
>
> Modified: llvm/trunk/include/llvm/Analysis/Passes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/Passes.h (original)
> +++ llvm/trunk/include/llvm/Analysis/Passes.h Thu Jun  5 14:29:43 2014
> @@ -142,6 +142,10 @@ namespace llvm {
>    // information and prints it with -analyze.
>    //
>    FunctionPass *createMemDepPrinter();
> +
> +  // createJumpInstrTableInfoPass - This creates a pass that stores information
> +  // about the jump tables created by JumpInstrTables
> +  ImmutablePass *createJumpInstrTableInfoPass();
>  }
>
>  #endif
>
> Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
> +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Thu Jun  5 14:29:43 2014
> @@ -372,7 +372,8 @@ namespace bitc {
>      ATTR_KIND_COLD = 36,
>      ATTR_KIND_OPTIMIZE_NONE = 37,
>      ATTR_KIND_IN_ALLOCA = 38,
> -    ATTR_KIND_NON_NULL = 39
> +    ATTR_KIND_NON_NULL = 39,
> +    ATTR_KIND_JUMP_TABLE = 40
>    };
>
>  } // End bitc namespace
>
> Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Thu Jun  5 14:29:43 2014
> @@ -202,6 +202,21 @@ FunctionSections("function-sections",
>                   cl::desc("Emit functions into separate sections"),
>                   cl::init(false));
>
> +cl::opt<llvm::JumpTable::JumpTableType>
> +JTableType("jump-table-type",
> +          cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
> +          cl::init(JumpTable::Single),
> +          cl::values(
> +              clEnumValN(JumpTable::Single, "single",
> +                         "Create a single table for all jumptable functions"),
> +              clEnumValN(JumpTable::Arity, "arity",
> +                         "Create one table per number of parameters."),
> +              clEnumValN(JumpTable::Simplified, "simplified",
> +                         "Create one table per simplified function type."),
> +              clEnumValN(JumpTable::Full, "full",
> +                         "Create one table per unique function type."),
> +              clEnumValEnd));
> +
>  // Common utility function tightly tied to the options listed here. Initializes
>  // a TargetOptions object with CodeGen flags and returns it.
>  static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
> @@ -228,6 +243,7 @@ static inline TargetOptions InitTargetOp
>    Options.FunctionSections = FunctionSections;
>
>    Options.MCOptions = InitMCTargetOptionsFromFlags();
> +  Options.JTType = JTableType;
>
>    return Options;
>  }
>
> Added: llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h (added)
> +++ llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,102 @@
> +//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===//
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +/// \brief An implementation of tables consisting of jump instructions
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H
> +#define LLVM_CODEGEN_JUMPINSTRTABLES_H
> +
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/Pass.h"
> +#include "llvm/Target/TargetOptions.h"
> +
> +namespace llvm {
> +class Constant;
> +class Function;
> +class FunctionType;
> +class JumpInstrTableInfo;
> +class Module;
> +
> +/// A class to manage a set of jump tables indexed on function type. It looks at
> +/// each function in the module to find all the functions that have the
> +/// jumptable attribute set. For each such function, it creates a new
> +/// jump-instruction-table function and stores the mapping in the ImmutablePass
> +/// JumpInstrTableInfo.
> +///
> +/// These special functions get lowered in AsmPrinter to assembly of the form:
> +///   .globl f
> +///   .type f, at function
> +///   .align 8,0x90
> +/// f:
> +///   jmp f_orig at PLT
> +///
> +/// 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.
> +class JumpInstrTables : public ModulePass {
> +public:
> +  static char ID;
> +
> +  JumpInstrTables();
> +  JumpInstrTables(JumpTable::JumpTableType JTT);
> +  virtual ~JumpInstrTables();
> +  bool runOnModule(Module &M) override;
> +  const char *getPassName() const override { return "Jump-Instruction Tables"; }
> +  void getAnalysisUsage(AnalysisUsage &AU) const override;
> +
> +  /// Creates a jump-instruction table function for the Target and adds it to
> +  /// the tables.
> +  Function *insertEntry(Module &M, Function *Target);
> +
> +  /// Checks to see if there is already a table for the given FunctionType.
> +  bool hasTable(FunctionType *FunTy);
> +
> +private:
> +  /// The metadata used while a jump table is being built
> +  struct TableMeta {
> +    /// The number of this table
> +    unsigned TableNum;
> +
> +    /// The current number of jump entries in the table.
> +    unsigned Count;
> +  };
> +
> +  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;
> +
> +  /// The ImmutablePass that stores information about the generated tables.
> +  JumpInstrTableInfo *JITI;
> +
> +  /// The total number of tables.
> +  unsigned TableCount;
> +
> +  /// The type of tables to build.
> +  JumpTable::JumpTableType JTType;
> +};
> +
> +/// Creates a JumpInstrTables pass for the given type of jump table.
> +ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT);
> +}
> +
> +#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */
>
> Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/Passes.h Thu Jun  5 14:29:43 2014
> @@ -588,6 +588,8 @@ namespace llvm {
>    /// the intrinsic for later emission to the StackMap.
>    extern char &StackMapLivenessID;
>
> +  /// createJumpInstrTables - This pass creates jump-instruction tables.
> +  ModulePass *createJumpInstrTablesPass();
>  } // End llvm namespace
>
>  #endif
>
> Modified: llvm/trunk/include/llvm/IR/Attributes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Attributes.h (original)
> +++ llvm/trunk/include/llvm/IR/Attributes.h Thu Jun  5 14:29:43 2014
> @@ -75,6 +75,7 @@ public:
>      Cold,                  ///< Marks function as being in a cold path.
>      InlineHint,            ///< Source said inlining was desirable
>      InReg,                 ///< Force argument to be passed in register
> +    JumpTable,             ///< Build jump-instruction tables and replace refs.
>      MinSize,               ///< Function must be optimized for size first
>      Naked,                 ///< Naked function
>      Nest,                  ///< Nested function static chain
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Thu Jun  5 14:29:43 2014
> @@ -146,6 +146,8 @@ void initializeInstCountPass(PassRegistr
>  void initializeInstNamerPass(PassRegistry&);
>  void initializeInternalizePassPass(PassRegistry&);
>  void initializeIntervalPartitionPass(PassRegistry&);
> +void initializeJumpInstrTableInfoPass(PassRegistry&);
> +void initializeJumpInstrTablesPass(PassRegistry&);
>  void initializeJumpThreadingPass(PassRegistry&);
>  void initializeLCSSAPass(PassRegistry&);
>  void initializeLICMPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Thu Jun  5 14:29:43 2014
> @@ -85,6 +85,8 @@ namespace {
>        (void) llvm::createIndVarSimplifyPass();
>        (void) llvm::createInstructionCombiningPass();
>        (void) llvm::createInternalizePass();
> +      (void) llvm::createJumpInstrTableInfoPass();
> +      (void) llvm::createJumpInstrTablesPass();
>        (void) llvm::createLCSSAPass();
>        (void) llvm::createLICMPass();
>        (void) llvm::createLazyValueInfoPass();
>
> Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Thu Jun  5 14:29:43 2014
> @@ -29,6 +29,7 @@ class MachineRegisterInfo;
>  class MDNode;
>  class MCInst;
>  class MCSchedModel;
> +class MCSymbolRefExpr;
>  class SDNode;
>  class ScheduleHazardRecognizer;
>  class SelectionDAG;
> @@ -321,6 +322,20 @@ public:
>    virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
>                                         MachineBasicBlock *NewDest) const;
>
> +  /// getUnconditionalBranch - Get an instruction that performs an unconditional
> +  /// branch to the given symbol.
> +  virtual void
> +  getUnconditionalBranch(MCInst &MI,
> +                         const MCSymbolRefExpr *BranchTarget) const {
> +    llvm_unreachable("Target didn't implement "
> +                     "TargetInstrInfo::getUnconditionalBranch!");
> +  }
> +
> +  /// getTrap - Get a machine trap instruction
> +  virtual void getTrap(MCInst &MI) const {
> +    llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
> +  }
> +
>    /// 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=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetOptions.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetOptions.h Thu Jun  5 14:29:43 2014
> @@ -39,6 +39,17 @@ namespace llvm {
>      };
>    }
>
> +  namespace JumpTable {
> +    enum JumpTableType {
> +      Single,          // Use a single table for all indirect jumptable calls.
> +      Arity,           // Use one table per number of function parameters.
> +      Simplified,      // Use one table per function type, with types projected
> +                       // into 4 types: pointer to non-function, struct,
> +                       // primitive, and function pointer.
> +      Full             // Use one table per unique function type
> +    };
> +  }
> +
>    class TargetOptions {
>    public:
>      TargetOptions()
> @@ -54,7 +65,7 @@ namespace llvm {
>            CompressDebugSections(false), FunctionSections(false),
>            DataSections(false), TrapUnreachable(false), TrapFuncName(""),
>            FloatABIType(FloatABI::Default),
> -          AllowFPOpFusion(FPOpFusion::Standard) {}
> +          AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {}
>
>      /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
>      /// option is specified on the command line, and should enable debugging
> @@ -205,6 +216,10 @@ namespace llvm {
>      /// the value of this option.
>      FPOpFusion::FPOpFusionMode AllowFPOpFusion;
>
> +    /// JTType - This flag specifies the type of jump-instruction table to
> +    /// create for functions that have the jumptable attribute.
> +    JumpTable::JumpTableType JTType;
> +
>      /// Machine level options.
>      MCTargetOptions MCOptions;
>    };
>
> Modified: llvm/trunk/lib/Analysis/Analysis.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/Analysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/Analysis.cpp Thu Jun  5 14:29:43 2014
> @@ -48,6 +48,7 @@ void llvm::initializeAnalysis(PassRegist
>    initializeIVUsersPass(Registry);
>    initializeInstCountPass(Registry);
>    initializeIntervalPartitionPass(Registry);
> +  initializeJumpInstrTableInfoPass(Registry);
>    initializeLazyValueInfoPass(Registry);
>    initializeLibCallAliasAnalysisPass(Registry);
>    initializeLintPass(Registry);
>
> Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Analysis/CMakeLists.txt Thu Jun  5 14:29:43 2014
> @@ -25,6 +25,7 @@ add_llvm_library(LLVMAnalysis
>    InstructionSimplify.cpp
>    Interval.cpp
>    IntervalPartition.cpp
> +  JumpInstrTableInfo.cpp
>    LazyCallGraph.cpp
>    LazyValueInfo.cpp
>    LibCallAliasAnalysis.cpp
>
> Added: llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp (added)
> +++ llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,40 @@
> +//===-- JumpInstrTableInfo.cpp: Info for Jump-Instruction Tables ----------===//
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +/// \brief Information about jump-instruction tables that have been created by
> +/// JumpInstrTables pass.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "jiti"
> +
> +#include "llvm/Analysis/JumpInstrTableInfo.h"
> +#include "llvm/Analysis/Passes.h"
> +#include "llvm/IR/Function.h"
> +#include "llvm/IR/Type.h"
> +
> +using namespace llvm;
> +
> +INITIALIZE_PASS(JumpInstrTableInfo, "jump-instr-table-info",
> +                "Jump-Instruction Table Info", true, true)
> +char JumpInstrTableInfo::ID = 0;
> +
> +ImmutablePass *llvm::createJumpInstrTableInfoPass() {
> +  return new JumpInstrTableInfo();
> +}
> +
> +JumpInstrTableInfo::JumpInstrTableInfo() : ImmutablePass(ID), Tables() {
> +  initializeJumpInstrTableInfoPass(*PassRegistry::getPassRegistry());
> +}
> +
> +JumpInstrTableInfo::~JumpInstrTableInfo() {}
> +
> +void JumpInstrTableInfo::insertEntry(FunctionType *TableFunTy, Function *Target,
> +                                     Function *Jump) {
> +  Tables[TableFunTy].push_back(JumpPair(Target, Jump));
> +}
>
> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Thu Jun  5 14:29:43 2014
> @@ -583,6 +583,7 @@ lltok::Kind LLLexer::LexIdentifier() {
>    KEYWORD(cold);
>    KEYWORD(inlinehint);
>    KEYWORD(inreg);
> +  KEYWORD(jumptable);
>    KEYWORD(minsize);
>    KEYWORD(naked);
>    KEYWORD(nest);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Thu Jun  5 14:29:43 2014
> @@ -947,6 +947,7 @@ bool LLParser::ParseFnAttributeValuePair
>      case lltok::kw_builtin:           B.addAttribute(Attribute::Builtin); break;
>      case lltok::kw_cold:              B.addAttribute(Attribute::Cold); break;
>      case lltok::kw_inlinehint:        B.addAttribute(Attribute::InlineHint); break;
> +    case lltok::kw_jumptable:         B.addAttribute(Attribute::JumpTable); break;
>      case lltok::kw_minsize:           B.addAttribute(Attribute::MinSize); break;
>      case lltok::kw_naked:             B.addAttribute(Attribute::Naked); break;
>      case lltok::kw_nobuiltin:         B.addAttribute(Attribute::NoBuiltin); break;
> @@ -1210,6 +1211,7 @@ bool LLParser::ParseOptionalParamAttrs(A
>      case lltok::kw_alwaysinline:
>      case lltok::kw_builtin:
>      case lltok::kw_inlinehint:
> +    case lltok::kw_jumptable:
>      case lltok::kw_minsize:
>      case lltok::kw_naked:
>      case lltok::kw_nobuiltin:
> @@ -1271,6 +1273,7 @@ bool LLParser::ParseOptionalReturnAttrs(
>      case lltok::kw_builtin:
>      case lltok::kw_cold:
>      case lltok::kw_inlinehint:
> +    case lltok::kw_jumptable:
>      case lltok::kw_minsize:
>      case lltok::kw_naked:
>      case lltok::kw_nobuiltin:
>
> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> +++ llvm/trunk/lib/AsmParser/LLToken.h Thu Jun  5 14:29:43 2014
> @@ -107,6 +107,7 @@ namespace lltok {
>      kw_cold,
>      kw_inlinehint,
>      kw_inreg,
> +    kw_jumptable,
>      kw_minsize,
>      kw_naked,
>      kw_nest,
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Jun  5 14:29:43 2014
> @@ -549,6 +549,8 @@ static Attribute::AttrKind GetAttrFromCo
>      return Attribute::InlineHint;
>    case bitc::ATTR_KIND_IN_REG:
>      return Attribute::InReg;
> +  case bitc::ATTR_KIND_JUMP_TABLE:
> +    return Attribute::JumpTable;
>    case bitc::ATTR_KIND_MIN_SIZE:
>      return Attribute::MinSize;
>    case bitc::ATTR_KIND_NAKED:
>
> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu Jun  5 14:29:43 2014
> @@ -177,6 +177,8 @@ static uint64_t getAttrKindEncoding(Attr
>      return bitc::ATTR_KIND_INLINE_HINT;
>    case Attribute::InReg:
>      return bitc::ATTR_KIND_IN_REG;
> +  case Attribute::JumpTable:
> +    return bitc::ATTR_KIND_JUMP_TABLE;
>    case Attribute::MinSize:
>      return bitc::ATTR_KIND_MIN_SIZE;
>    case Attribute::Naked:
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu Jun  5 14:29:43 2014
> @@ -18,6 +18,7 @@
>  #include "llvm/ADT/SmallString.h"
>  #include "llvm/ADT/Statistic.h"
>  #include "llvm/Analysis/ConstantFolding.h"
> +#include "llvm/Analysis/JumpInstrTableInfo.h"
>  #include "llvm/CodeGen/GCMetadataPrinter.h"
>  #include "llvm/CodeGen/MachineConstantPool.h"
>  #include "llvm/CodeGen/MachineFrameInfo.h"
> @@ -889,6 +890,54 @@ bool AsmPrinter::doFinalization(Module &
>      EmitVisibility(Name, V, false);
>    }
>
> +  // Get information about jump-instruction tables to print.
> +  JumpInstrTableInfo *JITI = getAnalysisIfAvailable<JumpInstrTableInfo>();
> +
> +  if (JITI && !JITI->getTables().empty()) {
> +    unsigned Arch = Triple(getTargetTriple()).getArch();
> +    bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);
> +    MCInst TrapInst;
> +    TM.getInstrInfo()->getTrap(TrapInst);
> +    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);
> +        if (IsThumb)
> +          OutStreamer.EmitThumbFunc(FunSym);
> +        if (MAI->hasDotTypeDotSizeDirective())
> +          OutStreamer.EmitSymbolAttribute(FunSym, MCSA_ELF_TypeFunction);
> +        OutStreamer.EmitLabel(FunSym);
> +
> +        // Emit the jump instruction to transfer control to the original
> +        // function.
> +        MCInst JumpToFun;
> +        MCSymbol *TargetSymbol =
> +          OutContext.GetOrCreateSymbol(FunPair.first->getName());
> +        const MCSymbolRefExpr *TargetSymRef =
> +          MCSymbolRefExpr::Create(TargetSymbol, MCSymbolRefExpr::VK_PLT,
> +                                  OutContext);
> +        TM.getInstrInfo()->getUnconditionalBranch(JumpToFun, TargetSymRef);
> +        OutStreamer.EmitInstruction(JumpToFun, getSubtargetInfo());
> +        ++Count;
> +      }
> +
> +      // 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);
> +        OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo());
> +      }
> +
> +    }
> +  }
> +
>    // Emit module flags.
>    SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
>    M.getModuleFlagsMetadata(ModuleFlags);
>
> Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Thu Jun  5 14:29:43 2014
> @@ -27,6 +27,7 @@ add_llvm_library(LLVMCodeGen
>    InterferenceCache.cpp
>    IntrinsicLowering.cpp
>    JITCodeEmitter.cpp
> +  JumpInstrTables.cpp
>    LLVMTargetMachine.cpp
>    LatencyPriorityQueue.cpp
>    LexicalScopes.cpp
>
> Added: llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/JumpInstrTables.cpp?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/JumpInstrTables.cpp (added)
> +++ llvm/trunk/lib/CodeGen/JumpInstrTables.cpp Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,301 @@
> +//===-- JumpInstrTables.cpp: Jump-Instruction Tables ----------------------===//
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +/// \brief An implementation of jump-instruction tables.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "jt"
> +
> +#include "llvm/CodeGen/JumpInstrTables.h"
> +
> +#include "llvm/ADT/Statistic.h"
> +#include "llvm/Analysis/JumpInstrTableInfo.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/LLVMContext.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/IR/Operator.h"
> +#include "llvm/IR/Type.h"
> +#include "llvm/IR/Verifier.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +#include <vector>
> +
> +using namespace llvm;
> +
> +char JumpInstrTables::ID = 0;
> +
> +INITIALIZE_PASS_BEGIN(JumpInstrTables, "jump-instr-tables",
> +                      "Jump-Instruction Tables", true, true)
> +INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo);
> +INITIALIZE_PASS_END(JumpInstrTables, "jump-instr-tables",
> +                    "Jump-Instruction Tables", true, true)
> +
> +STATISTIC(NumJumpTables, "Number of indirect call tables generated");
> +STATISTIC(NumFuncsInJumpTables, "Number of functions in the jump tables");
> +
> +ModulePass *llvm::createJumpInstrTablesPass() {
> +  // The default implementation uses a single table for all functions.
> +  return new JumpInstrTables(JumpTable::Single);
> +}
> +
> +ModulePass *llvm::createJumpInstrTablesPass(JumpTable::JumpTableType JTT) {
> +  return new JumpInstrTables(JTT);
> +}
> +
> +namespace {
> +static const char jump_func_prefix[] = "__llvm_jump_instr_table_";
> +static const char jump_section_prefix[] = ".jump.instr.table.text.";
> +
> +// Checks to see if a given CallSite is making an indirect call, including
> +// cases where the indirect call is made through a bitcast.
> +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;
> +}
> +
> +// Replaces Functions and GlobalAliases with a different Value.
> +bool replaceGlobalValueIndirectUse(GlobalValue *GV, Value *V, Use *U) {
> +  User *Us = U->getUser();
> +  if (!Us)
> +    return false;
> +  if (Instruction *I = dyn_cast<Instruction>(Us)) {
> +    CallSite CS(I);
> +
> +    // Don't do the replacement if this use is a direct call to this function.
> +    // If the use is not the called value, then replace it.
> +    if (CS && (isIndirectCall(CS) || CS.isCallee(U))) {
> +      return false;
> +    }
> +
> +    U->set(V);
> +  } else if (Constant *C = dyn_cast<Constant>(Us)) {
> +    // Don't replace calls to bitcasts of function symbols, since they get
> +    // translated to direct calls.
> +    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Us)) {
> +      if (CE->getOpcode() == Instruction::BitCast) {
> +        // This bitcast must have exactly one user.
> +        if (CE->user_begin() != CE->user_end()) {
> +          User *ParentUs = *CE->user_begin();
> +          if (CallInst *CI = dyn_cast<CallInst>(ParentUs)) {
> +            CallSite CS(CI);
> +            Use &CEU = *CE->use_begin();
> +            if (CS.isCallee(&CEU)) {
> +              return false;
> +            }
> +          }
> +        }
> +      }
> +    }
> +
> +    // GlobalAlias doesn't support replaceUsesOfWithOnConstant. And the verifier
> +    // requires alias to point to a defined function. So, GlobalAlias is handled
> +    // as a separate case in runOnModule.
> +    if (!isa<GlobalAlias>(C))
> +      C->replaceUsesOfWithOnConstant(GV, V, U);
> +  } else {
> +    assert(false && "The Use of a Function symbol is neither an instruction nor"
> +                    " a constant");
> +  }
> +
> +  return true;
> +}
> +
> +// Replaces all replaceable address-taken uses of GV with a pointer to a
> +// jump-instruction table entry.
> +void replaceValueWithFunction(GlobalValue *GV, Function *F) {
> +  // Go through all uses of this function and replace the uses of GV with the
> +  // jump-table version of the function. Get the uses as a vector before
> +  // replacing them, since replacing them changes the use list and invalidates
> +  // the iterator otherwise.
> +  for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E;) {
> +    Use &U = *I++;
> +
> +    // Replacement of constants replaces all instances in the constant. So, some
> +    // uses might have already been handled by the time we reach them here.
> +    if (U.get() == GV)
> +      replaceGlobalValueIndirectUse(GV, F, &U);
> +  }
> +
> +  return;
> +}
> +} // end anonymous namespace
> +
> +JumpInstrTables::JumpInstrTables()
> +    : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0),
> +      JTType(JumpTable::Single) {
> +  initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry());
> +}
> +
> +JumpInstrTables::JumpInstrTables(JumpTable::JumpTableType JTT)
> +    : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0), JTType(JTT) {
> +  initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry());
> +}
> +
> +JumpInstrTables::~JumpInstrTables() {}
> +
> +void JumpInstrTables::getAnalysisUsage(AnalysisUsage &AU) const {
> +  AU.addRequired<JumpInstrTableInfo>();
> +}
> +
> +Function *JumpInstrTables::insertEntry(Module &M, Function *Target) {
> +  FunctionType *OrigFunTy = Target->getFunctionType();
> +  FunctionType *FunTy = transformType(OrigFunTy);
> +
> +  JumpMap::iterator it = Metadata.find(FunTy);
> +  if (Metadata.end() == it) {
> +    struct TableMeta Meta;
> +    Meta.TableNum = TableCount;
> +    Meta.Count = 0;
> +    Metadata[FunTy] = Meta;
> +    it = Metadata.find(FunTy);
> +    ++NumJumpTables;
> +    ++TableCount;
> +  }
> +
> +  it->second.Count++;
> +
> +  std::string NewName(jump_func_prefix);
> +  NewName += (Twine(it->second.TableNum) + "_" + Twine(it->second.Count)).str();
> +  Function *JumpFun =
> +      Function::Create(OrigFunTy, GlobalValue::ExternalLinkage, NewName, &M);
> +  // The section for this table
> +  JumpFun->setSection((jump_section_prefix + Twine(it->second.TableNum)).str());
> +  JITI->insertEntry(FunTy, Target, JumpFun);
> +
> +  ++NumFuncsInJumpTables;
> +  return JumpFun;
> +}
> +
> +bool JumpInstrTables::hasTable(FunctionType *FunTy) {
> +  FunctionType *TransTy = transformType(FunTy);
> +  return Metadata.end() != Metadata.find(TransTy);
> +}
> +
> +FunctionType *JumpInstrTables::transformType(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());
> +
> +  // Ignore the return type.
> +  Type *RetTy = VoidPtrTy;
> +  bool IsVarArg = FunTy->isVarArg();
> +  std::vector<Type *> ParamTys(FunTy->getNumParams());
> +  FunctionType::param_iterator PI, PE;
> +  int i = 0;
> +
> +  std::vector<Type *> EmptyParams;
> +  Type *Int32Ty = Type::getInt32Ty(FunTy->getContext());
> +  FunctionType *VoidFnTy = FunctionType::get(
> +      Type::getVoidTy(FunTy->getContext()), EmptyParams, false);
> +  switch (JTType) {
> +  case JumpTable::Single:
> +
> +    return FunctionType::get(RetTy, EmptyParams, false);
> +  case JumpTable::Arity:
> +    // Transform all types to void* so that all functions with the same arity
> +    // end up in the same table.
> +    for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE;
> +         PI++, i++) {
> +      ParamTys[i] = VoidPtrTy;
> +    }
> +
> +    return FunctionType::get(RetTy, ParamTys, IsVarArg);
> +  case JumpTable::Simplified:
> +    // Project all parameters types to one of 3 types: composite, integer, and
> +    // function, matching the three subclasses of Type.
> +    for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE;
> +         ++PI, ++i) {
> +      assert((isa<IntegerType>(*PI) || isa<FunctionType>(*PI) ||
> +              isa<CompositeType>(*PI)) &&
> +             "This type is not an Integer or a Composite or a Function");
> +      if (isa<CompositeType>(*PI)) {
> +        ParamTys[i] = VoidPtrTy;
> +      } else if (isa<FunctionType>(*PI)) {
> +        ParamTys[i] = VoidFnTy;
> +      } else if (isa<IntegerType>(*PI)) {
> +        ParamTys[i] = Int32Ty;
> +      }
> +    }
> +
> +    return FunctionType::get(RetTy, ParamTys, IsVarArg);
> +  case JumpTable::Full:
> +    // Don't transform this type at all.
> +    return FunTy;
> +  }
> +
> +  return nullptr;
> +}
> +
> +bool JumpInstrTables::runOnModule(Module &M) {
> +  // Make sure the module is well-formed, especially with respect to jumptable.
> +  if (verifyModule(M))
> +    return false;
> +
> +  JITI = &getAnalysis<JumpInstrTableInfo>();
> +
> +  // Get the set of jumptable-annotated functions.
> +  DenseMap<Function *, Function *> Functions;
> +  for (Function &F : M) {
> +    if (F.hasFnAttribute(Attribute::JumpTable)) {
> +      assert(F.hasUnnamedAddr() &&
> +             "Attribute 'jumptable' requires 'unnamed_addr'");
> +      Functions[&F] = NULL;
> +    }
> +  }
> +
> +  // Create the jump-table functions.
> +  for (auto &KV : Functions) {
> +    Function *F = KV.first;
> +    KV.second = insertEntry(M, F);
> +  }
> +
> +  // GlobalAlias is a special case, because the target of an alias statement
> +  // must be a defined function. So, instead of replacing a given function in
> +  // the alias, we replace all uses of aliases that target jumptable functions.
> +  // Note that there's no need to create these functions, since only aliases
> +  // that target known jumptable functions are replaced, and there's no way to
> +  // put the jumptable annotation on a global alias.
> +  DenseMap<GlobalAlias *, Function *> Aliases;
> +  for (GlobalAlias &GA : M.aliases()) {
> +    Constant *Aliasee = GA.getAliasee();
> +    if (Function *F = dyn_cast<Function>(Aliasee)) {
> +      auto it = Functions.find(F);
> +      if (it != Functions.end()) {
> +        Aliases[&GA] = it->second;
> +      }
> +    }
> +  }
> +
> +  // Replace each address taken function with its jump-instruction table entry.
> +  for (auto &KV : Functions)
> +    replaceValueWithFunction(KV.first, KV.second);
> +
> +  for (auto &KV : Aliases)
> +    replaceValueWithFunction(KV.first, KV.second);
> +
> +  return !Functions.empty();
> +}
>
> Modified: llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp (original)
> +++ llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp Thu Jun  5 14:29:43 2014
> @@ -12,11 +12,15 @@
>  //===----------------------------------------------------------------------===//
>
>  #include "llvm/Target/TargetMachine.h"
> +
> +#include "llvm/Analysis/Passes.h"
>  #include "llvm/CodeGen/AsmPrinter.h"
> +#include "llvm/CodeGen/JumpInstrTables.h"
>  #include "llvm/CodeGen/MachineFunctionAnalysis.h"
>  #include "llvm/CodeGen/MachineModuleInfo.h"
>  #include "llvm/CodeGen/Passes.h"
>  #include "llvm/IR/IRPrintingPasses.h"
> +#include "llvm/IR/Verifier.h"
>  #include "llvm/MC/MCAsmInfo.h"
>  #include "llvm/MC/MCContext.h"
>  #include "llvm/MC/MCInstrInfo.h"
> @@ -82,6 +86,7 @@ static MCContext *addPassesToGenerateCod
>                                            bool DisableVerify,
>                                            AnalysisID StartAfter,
>                                            AnalysisID StopAfter) {
> +
>    // Add internal analysis passes from the target machine.
>    TM->addAnalysisPasses(PM);
>
> @@ -136,6 +141,11 @@ bool LLVMTargetMachine::addPassesToEmitF
>                                              bool DisableVerify,
>                                              AnalysisID StartAfter,
>                                              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(createJumpInstrTablesPass(Options.JTType));
> +
>    // Add common CodeGen passes.
>    MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
>                                                 StartAfter, StopAfter);
>
> Modified: llvm/trunk/lib/IR/Attributes.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Attributes.cpp (original)
> +++ llvm/trunk/lib/IR/Attributes.cpp Thu Jun  5 14:29:43 2014
> @@ -173,6 +173,8 @@ std::string Attribute::getAsString(bool
>      return "inlinehint";
>    if (hasAttribute(Attribute::InReg))
>      return "inreg";
> +  if (hasAttribute(Attribute::JumpTable))
> +    return "jumptable";
>    if (hasAttribute(Attribute::MinSize))
>      return "minsize";
>    if (hasAttribute(Attribute::Naked))
> @@ -395,6 +397,7 @@ uint64_t AttributeImpl::getAttrMask(Attr
>    case Attribute::OptimizeNone:    return 1ULL << 42;
>    case Attribute::InAlloca:        return 1ULL << 43;
>    case Attribute::NonNull:         return 1ULL << 44;
> +  case Attribute::JumpTable:       return 1ULL << 45;
>    }
>    llvm_unreachable("Unsupported attribute type");
>  }
>
> Modified: llvm/trunk/lib/IR/Verifier.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Verifier.cpp (original)
> +++ llvm/trunk/lib/IR/Verifier.cpp Thu Jun  5 14:29:43 2014
> @@ -735,7 +735,8 @@ void Verifier::VerifyAttributeTypes(Attr
>          I->getKindAsEnum() == Attribute::Builtin ||
>          I->getKindAsEnum() == Attribute::NoBuiltin ||
>          I->getKindAsEnum() == Attribute::Cold ||
> -        I->getKindAsEnum() == Attribute::OptimizeNone) {
> +        I->getKindAsEnum() == Attribute::OptimizeNone ||
> +        I->getKindAsEnum() == Attribute::JumpTable) {
>        if (!isFunction) {
>          CheckFailed("Attribute '" + I->getAsString() +
>                      "' only applies to functions!", V);
> @@ -909,6 +910,14 @@ void Verifier::VerifyFunctionAttrs(Funct
>                                  Attribute::MinSize),
>              "Attributes 'minsize and optnone' are incompatible!", V);
>    }
> +
> +  if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
> +                         Attribute::JumpTable)) {
> +    const GlobalValue *GV = cast<GlobalValue>(V);
> +    Assert1(GV->hasUnnamedAddr(),
> +            "Attribute 'jumptable' requires 'unnamed_addr'", V);
> +
> +  }
>  }
>
>  void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) {
>
> Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
> +++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Thu Jun  5 14:29:43 2014
> @@ -96,6 +96,7 @@ void LTOCodeGenerator::initializeLTOPass
>    initializeConstantMergePass(R);
>    initializeDAHPass(R);
>    initializeInstCombinerPass(R);
> +  initializeJumpInstrTablesPass(R);
>    initializeSimpleInlinerPass(R);
>    initializePruneEHPass(R);
>    initializeGlobalDCEPass(R);
>
> Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Thu Jun  5 14:29:43 2014
> @@ -32,6 +32,7 @@
>  #include "llvm/IR/Function.h"
>  #include "llvm/IR/GlobalValue.h"
>  #include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCExpr.h"
>  #include "llvm/Support/BranchProbability.h"
>  #include "llvm/Support/CommandLine.h"
>  #include "llvm/Support/Debug.h"
> @@ -4358,6 +4359,29 @@ 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=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)
> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Thu Jun  5 14:29:43 2014
> @@ -229,6 +229,13 @@ public:
>                                        const TargetRegisterInfo*) const override;
>    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=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Thu Jun  5 14:29:43 2014
> @@ -28,6 +28,7 @@
>  #include "llvm/IR/DerivedTypes.h"
>  #include "llvm/IR/LLVMContext.h"
>  #include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCExpr.h"
>  #include "llvm/MC/MCInst.h"
>  #include "llvm/Support/CommandLine.h"
>  #include "llvm/Support/Debug.h"
> @@ -5299,6 +5300,16 @@ void X86InstrInfo::getNoopForMachoTarget
>    NopInst.setOpcode(X86::NOOP);
>  }
>
> +void X86InstrInfo::getUnconditionalBranch(
> +    MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
> +  Branch.setOpcode(X86::JMP_4);
> +  Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
> +}
> +
> +void X86InstrInfo::getTrap(MCInst &MI) const {
> +  MI.setOpcode(X86::TRAP);
> +}
> +
>  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=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Thu Jun  5 14:29:43 2014
> @@ -396,6 +396,12 @@ public:
>                                        const SmallVectorImpl<MachineOperand> &MOs,
>                                        unsigned Size, unsigned Alignment) const;
>
> +  void
> +  getUnconditionalBranch(MCInst &Branch,
> +                         const MCSymbolRefExpr *BranchTarget) const override;
> +
> +  void getTrap(MCInst &MI) const override;
> +
>    bool isHighLatencyDef(int opc) const override;
>
>    bool hasHighOperandLatency(const InstrItineraryData *ItinData,
>
> Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Thu Jun  5 14:29:43 2014
> @@ -30,6 +30,7 @@ void llvm::initializeIPO(PassRegistry &R
>    initializeGlobalDCEPass(Registry);
>    initializeGlobalOptPass(Registry);
>    initializeIPCPPass(Registry);
> +  initializeJumpInstrTablesPass(Registry);
>    initializeAlwaysInlinerPass(Registry);
>    initializeSimpleInlinerPass(Registry);
>    initializeInternalizePassPass(Registry);
>
> Modified: llvm/trunk/test/Bitcode/attributes.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/test/Bitcode/attributes.ll (original)
> +++ llvm/trunk/test/Bitcode/attributes.ll Thu Jun  5 14:29:43 2014
> @@ -203,7 +203,7 @@ define void @f34()
>  ; CHECK: define void @f34()
>  {
>          call void @nobuiltin() nobuiltin
> -; CHECK: call void @nobuiltin() #24
> +; CHECK: call void @nobuiltin() #25
>          ret void;
>  }
>
> @@ -223,6 +223,12 @@ define nonnull i8* @f37(i8* nonnull %a)
>          ret i8* %a
>  }
>
> +define void @f38() unnamed_addr jumptable {
> +; CHECK: define void @f38() unnamed_addr #24
> +    call void bitcast (void (i8*)* @f36 to void ()*)()
> +    unreachable
> +}
> +
>  ; CHECK: attributes #0 = { noreturn }
>  ; CHECK: attributes #1 = { nounwind }
>  ; CHECK: attributes #2 = { readnone }
> @@ -247,5 +253,5 @@ define nonnull i8* @f37(i8* nonnull %a)
>  ; CHECK: attributes #21 = { sspstrong }
>  ; CHECK: attributes #22 = { minsize }
>  ; CHECK: attributes #23 = { noinline optnone }
> -; CHECK: attributes #24 = { nobuiltin }
> -
> +; CHECK: attributes #24 = { jumptable }
> +; CHECK: attributes #25 = { nobuiltin }
>
> Added: llvm/trunk/test/CodeGen/ARM/jump_tables.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/jump_tables.ll?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/jump_tables.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/jump_tables.ll Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,32 @@
> +; RUN: llc <%s -march=arm -jump-table-type=single | FileCheck --check-prefix=ARM %s
> +; RUN: llc <%s -march=thumb -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)
>
> Modified: llvm/trunk/test/CodeGen/Generic/stop-after.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/stop-after.ll?rev=210280&r1=210279&r2=210280&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/Generic/stop-after.ll (original)
> +++ llvm/trunk/test/CodeGen/Generic/stop-after.ll Thu Jun  5 14:29:43 2014
> @@ -5,6 +5,6 @@
>  ; STOP: Loop Strength Reduction
>  ; STOP-NEXT: Machine Function Analysis
>
> -; START: -machine-branch-prob -gc-lowering
> +; START: -machine-branch-prob -jump-instr-tables -gc-lowering
>  ; START: FunctionPass Manager
>  ; START-NEXT: Lower Garbage Collection Instructions
>
> Added: 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=210280&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/jump_table_alias.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/jump_table_alias.ll Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,33 @@
> +; RUN: llc <%s -jump-table-type=single | FileCheck %s
> +target triple = "x86_64-unknown-linux-gnu"
> +define i32 @f() unnamed_addr jumptable {
> +entry:
> +  ret i32 0
> +}
> +
> + at i = alias internal i32 ()* @f
> + at j = alias i32 ()* @f
> +
> +define i32 @main(i32 %argc, i8** %argv) {
> +  %temp = alloca i32 ()*, align 8
> +  store i32 ()* @i, i32()** %temp, align 8
> +; CHECK: movq    $__llvm_jump_instr_table_0_1
> +  %1 = load i32 ()** %temp, align 8
> +; CHECK: movl    $__llvm_jump_instr_table_0_1
> +  %2 = call i32 ()* %1()
> +  %3 = call i32 ()* @i()
> +; CHECK: callq   i
> +  %4 = call i32 ()* @j()
> +; CHECK: callq   j
> +  ret i32 %3
> +}
> +
> +; 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:
> +; CHECK:         jmp     f at PLT
> +
>
> Added: 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=210280&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,46 @@
> +; RUN: llc <%s -jump-table-type=single | 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
> +; CHECK: movq    $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]], (%rsp)
> +; CHECK: movl    $__llvm_jump_instr_table_0_[[ENTRY]], %ecx
> +  %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: callq   h
> +
> +  %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)
> +; CHECK: callq g
> +  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:
> +; CHECK:         jmp     {{f|g|h}}@PLT
> +
>
> Added: llvm/trunk/test/CodeGen/X86/jump_tables.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_tables.ll?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/jump_tables.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/jump_tables.ll Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,272 @@
> +; RUN: llc <%s -jump-table-type=single | FileCheck --check-prefix=SINGLE %s
> +; RUN: llc <%s -jump-table-type=arity | FileCheck --check-prefix=ARITY %s
> +; RUN: llc <%s -jump-table-type=simplified | FileCheck --check-prefix=SIMPL %s
> +; RUN: llc <%s -jump-table-type=full | FileCheck --check-prefix=FULL %s
> +
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +%struct.fun_struct = type { i32 (...)* }
> +
> +define void @indirect_fun() unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define void @indirect_fun_match() unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define i32 @indirect_fun_i32() unnamed_addr jumptable {
> +  ret i32 0
> +}
> +
> +define i32 @indirect_fun_i32_1(i32 %a) unnamed_addr jumptable {
> +  ret i32 %a
> +}
> +
> +define i32 @indirect_fun_i32_2(i32 %a, i32 %b) unnamed_addr jumptable {
> +  ret i32 %a
> +}
> +
> +define i32* @indirect_fun_i32S_2(i32* %a, i32 %b) unnamed_addr jumptable {
> +  ret i32* %a
> +}
> +
> +define void @indirect_fun_struct(%struct.fun_struct %fs) unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define void @indirect_fun_fun(i32 (...)* %fun, i32 %a) unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define i32 @indirect_fun_fun_ret(i32 (...)* %fun, i32 %a) unnamed_addr jumptable {
> +  ret i32 %a
> +}
> +
> +define void @indirect_fun_array([19 x i8] %a) unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define void @indirect_fun_vec(<3 x i32> %a) unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define void @indirect_fun_vec_2(<4 x float> %a) unnamed_addr jumptable {
> +  ret void
> +}
> +
> +define i32 @m(void ()* %fun) {
> +  call void ()* %fun()
> +  ret i32 0
> +}
> +
> +define void ()* @get_fun() {
> +  ret void ()* @indirect_fun
> +; SINGLE: movl    $__llvm_jump_instr_table_0_
> +; ARITY: movl    $__llvm_jump_instr_table_
> +; SIMPL: movl    $__llvm_jump_instr_table_
> +; FULL: movl    $__llvm_jump_instr_table_
> +}
> +
> +define i32 @main(i32 %argc, i8** %argv) {
> +  %f = call void ()* ()* @get_fun()
> +  %a = call i32 @m(void ()* %f)
> +  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:
> +; SINGLE-DAG:         jmp     indirect_fun_vec at PLT
> +; SINGLE-DAG:         .align  8, 0x90
> +; SINGLE-DAG:         ud2
> +; SINGLE-DAG:         .align  8, 0x90
> +; SINGLE-DAG:         ud2
> +; SINGLE-DAG:         .align  8, 0x90
> +; SINGLE-DAG:         ud2
> +; SINGLE-DAG:         .align  8, 0x90
> +; 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:
> +; FULL-DAG:        jmp     indirect_fun at PLT
> +; FULL-DAG:        .align  8, 0x90
> +; 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:
> +; FULL-DAG:        jmp     indirect_fun_fun_ret at PLT
> +; FULL-DAG:        .align  8, 0x90
> +; FULL-DAG:        ud2
>
> Added: llvm/trunk/test/Verifier/jumptable.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/jumptable.ll?rev=210280&view=auto
> ==============================================================================
> --- llvm/trunk/test/Verifier/jumptable.ll (added)
> +++ llvm/trunk/test/Verifier/jumptable.ll Thu Jun  5 14:29:43 2014
> @@ -0,0 +1,9 @@
> +; RUN: not llc <%s 2>&1 | FileCheck %s
> +
> +define i32 @f() jumptable {
> +  ret i32 0
> +}
> +
> +; CHECK: Attribute 'jumptable' requires 'unnamed_addr'
> +; CHECK: i32 ()* @f
> +; CHECK: LLVM ERROR: Broken function found, compilation aborted!
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list