| //===-- 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/IR/LegacyPassManagers.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: |
| /// \verbatim |
| /// .globl f |
| /// .type f,@function |
| /// .align 8,0x90 |
| /// f: |
| /// jmp f_orig@PLT |
| /// \endverbatim |
| /// |
| /// Support for an architecture depends on three functions in TargetInstrInfo: |
| /// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter |
| /// uses these to generate the appropriate instructions for the jump statement |
| /// (an unconditional branch) and for padding to make the table have a size that |
| /// is a power of two. This padding uses a trap instruction to ensure that calls |
| /// to this area halt the program. The default implementations of these |
| /// functions call llvm_unreachable, except for getJumpInstrTableEntryBound, |
| /// which returns 0 by default. |
| class JumpInstrTables : public ModulePass { |
| public: |
| static char ID; |
| |
| 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; |
| |
| // @LOCALMOD-BEGIN |
| // If there is not a ModulePassManager in the pass manager stack, do not |
| // schedule this pass. pnacl-llc uses only a FunctionPassManager but for |
| // some reason it will happily schedule any module passes that are handed to |
| // it and call them with bogus arguments. We could move this mod up into |
| // ModulePass::assignPassManager except that the JIT also uses a FPM and |
| // schedules a DebugInfoVerifier (which we do not use). That is still |
| // probably wrong but DebugInfoVerifier seems to accidentally work anyway for |
| // that case. |
| // All of this should be fixed upstream, except that the pass manager is being |
| // completely rewritten. So for now this is a noninvasive solution. |
| void assignPassManager(PMStack &PMS, PassManagerType PreferredType) override { |
| |
| if (std::none_of(PMS.begin(), PMS.end(), [](PMDataManager *PM) { |
| return PM->getPassManagerType() == PMT_ModulePassManager;})) { |
| return; |
| } |
| ModulePass::assignPassManager(PMS, PreferredType); |
| } |
| // @LOCALMOD-END |
| |
| /// 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); |
| |
| /// Maps the function into a subset of function types, depending on the |
| /// jump-instruction table style selected from JumpTableTypes in |
| /// JumpInstrTables.cpp. The choice of mapping determines the number of |
| /// jump-instruction tables generated by this pass. E.g., the simplest mapping |
| /// converts every function type into void f(); so, all functions end up in a |
| /// single table. |
| static FunctionType *transformType(JumpTable::JumpTableType JTT, |
| FunctionType *FunTy); |
| private: |
| /// The metadata used while a jump table is being built |
| struct TableMeta { |
| /// The number of this table |
| unsigned TableNum; |
| |
| /// The current number of jump entries in the table. |
| unsigned Count; |
| }; |
| |
| typedef DenseMap<FunctionType *, struct TableMeta> JumpMap; |
| |
| /// 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 */ |