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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210280 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tom Roeder
2014-06-05 19:29:43 +00:00
parent 4db3ad47fc
commit 5d0f7af3dc
40 changed files with 1109 additions and 8 deletions

View File

@@ -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 InitTargetOptionsFromCodeGenFlags() {
Options.FunctionSections = FunctionSections;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
return Options;
}

View File

@@ -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,@function
/// .align 8,0x90
/// f:
/// jmp f_orig@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 */

View File

@@ -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