diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /include | |
parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) | |
download | src-67c32a98315f785a9ec9d531c1f571a0196c7463.tar.gz src-67c32a98315f785a9ec9d531c1f571a0196c7463.zip |
Notes
Diffstat (limited to 'include')
426 files changed, 19812 insertions, 11209 deletions
diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h index 7af209bdfdce..f3b388bc4fb4 100644 --- a/include/llvm-c/BitReader.h +++ b/include/llvm-c/BitReader.h @@ -16,8 +16,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_BITCODEREADER_H -#define LLVM_C_BITCODEREADER_H +#ifndef LLVM_C_BITREADER_H +#define LLVM_C_BITREADER_H #include "llvm-c/Core.h" diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h index f605e2453f1c..f25ad3a445f5 100644 --- a/include/llvm-c/BitWriter.h +++ b/include/llvm-c/BitWriter.h @@ -16,8 +16,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_BITCODEWRITER_H -#define LLVM_C_BITCODEWRITER_H +#ifndef LLVM_C_BITWRITER_H +#define LLVM_C_BITWRITER_H #include "llvm-c/Core.h" @@ -45,6 +45,9 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, descriptor. Returns 0 on success. Closes the Handle. */ int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); +/** Writes a module to a new memory buffer and returns it. */ +LLVMMemoryBufferRef LLVMWriteBitcodeToMemoryBuffer(LLVMModuleRef M); + /** * @} */ diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index fdff77bc5e51..8873fdb67730 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -560,6 +560,10 @@ LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); */ LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, LLVMContextRef C); +/** + * Return an exact copy of the specified module. + */ +LLVMModuleRef LLVMCloneModule(LLVMModuleRef M); /** * Destroy a module instance. @@ -1153,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Argument) \ macro(BasicBlock) \ macro(InlineAsm) \ - macro(MDNode) \ - macro(MDString) \ macro(User) \ macro(Constant) \ macro(BlockAddress) \ @@ -1303,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); LLVMValueRef LLVMIsA##name(LLVMValueRef Val); LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); + /** * @} */ @@ -1378,6 +1383,13 @@ LLVMValueRef LLVMGetUsedValue(LLVMUseRef U); LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index); /** + * Obtain the use of an operand at a specific index in a llvm::User value. + * + * @see llvm::User::getOperandUse() + */ +LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index); + +/** * Set an operand at a specific index in a llvm::User value. * * @see llvm::User::setOperand() @@ -1538,6 +1550,14 @@ unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal); long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal); /** + * Obtain the double value for an floating point constant value. + * losesInfo indicates if some precision was lost in the conversion. + * + * @see llvm::ConstantFP::getDoubleValue + */ +double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *losesInfo); + +/** * @} */ @@ -1570,6 +1590,20 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length, LLVMBool DontNullTerminate); /** + * Returns true if the specified constant is an array of i8. + * + * @see ConstantDataSequential::getAsString() + */ +LLVMBool LLVMIsConstantString(LLVMValueRef c); + +/** + * Get the given constant data sequential as a string. + * + * @see ConstantDataSequential::getAsString() + */ +const char *LLVMGetAsString(LLVMValueRef c, size_t* out); + +/** * Create an anonymous ConstantStruct with the specified values. * * @see llvm::ConstantStruct::getAnon() @@ -1607,6 +1641,13 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy, unsigned Count); /** + * Get an element at specified index as a constant. + * + * @see ConstantDataSequential::getElementAsConstant() + */ +LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx); + +/** * Create a ConstantVector from values. * * @see llvm::ConstantVector::get() @@ -2377,6 +2418,26 @@ LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst); LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst); /** + * Obtain the float predicate of an instruction. + * + * This is only valid for instructions that correspond to llvm::FCmpInst + * or llvm::ConstantExpr whose opcode is llvm::Instruction::FCmp. + * + * @see llvm::FCmpInst::getPredicate() + */ +LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst); + +/** + * Create a copy of 'this' instruction that is identical in all ways + * except the following: + * * The instruction has no parent + * * The instruction has no name + * + * @see llvm::Instruction::clone() + */ +LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst); + +/** * @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations * * Functions in this group apply to instructions that refer to call @@ -2437,6 +2498,63 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); */ /** + * @defgroup LLVMCCoreValueInstructionTerminator Terminators + * + * Functions in this group only apply to instructions that map to + * llvm::TerminatorInst instances. + * + * @{ + */ + +/** + * Return the number of successors that this terminator has. + * + * @see llvm::TerminatorInst::getNumSuccessors + */ +unsigned LLVMGetNumSuccessors(LLVMValueRef Term); + +/** + * Return the specified successor. + * + * @see llvm::TerminatorInst::getSuccessor + */ +LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i); + +/** + * Update the specified successor to point at the provided block. + * + * @see llvm::TerminatorInst::setSuccessor + */ +void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block); + +/** + * Return if a branch is conditional. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::isConditional + */ +LLVMBool LLVMIsConditional(LLVMValueRef Branch); + +/** + * Return the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::getCondition + */ +LLVMValueRef LLVMGetCondition(LLVMValueRef Branch); + +/** + * Set the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::setCondition + */ +void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond); + +/** * Obtain the default destination basic block of a switch instruction. * * This only works on llvm::SwitchInst instructions. @@ -2446,6 +2564,10 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr); /** + * @} + */ + +/** * @defgroup LLVMCCoreValueInstructionPHINode PHI Nodes * * Functions in this group only apply to instructions that map to diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 8f31150ad91d..d6cbe31cbb4e 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -174,8 +174,8 @@ extern "C" { * by passing a block of information in the DisInfo parameter and specifying the * TagType and callback functions as described above. These can all be passed * as NULL. If successful, this returns a disassembler context. If not, it - * returns NULL. This function is equivalent to calling LLVMCreateDisasmCPU() - * with an empty CPU name. + * returns NULL. This function is equivalent to calling + * LLVMCreateDisasmCPUFeatures() with an empty CPU name and feature set. */ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, @@ -186,7 +186,8 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, * disassembly is supported by passing a block of information in the DisInfo * parameter and specifying the TagType and callback functions as described * above. These can all be passed * as NULL. If successful, this returns a - * disassembler context. If not, it returns NULL. + * disassembler context. If not, it returns NULL. This function is equivalent + * to calling LLVMCreateDisasmCPUFeatures() with an empty feature set. */ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, void *DisInfo, int TagType, @@ -194,6 +195,19 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, LLVMSymbolLookupCallback SymbolLookUp); /** + * Create a disassembler for the TripleName, a specific CPU and specific feature + * string. Symbolic disassembly is supported by passing a block of information + * in the DisInfo parameter and specifying the TagType and callback functions as + * described above. These can all be passed * as NULL. If successful, this + * returns a disassembler context. If not, it returns NULL. + */ +LLVMDisasmContextRef +LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU, + const char *Features, void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** * Set the disassembler's options. Returns 1 if it can set the Options and 0 * otherwise. */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 7cdf0d78d5b6..eb3ecabfa8a8 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -34,7 +34,6 @@ extern "C" { * @{ */ -void LLVMLinkInJIT(void); void LLVMLinkInMCJIT(void); void LLVMLinkInInterpreter(void); @@ -171,6 +170,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/include/llvm-c/Initialization.h b/include/llvm-c/Initialization.h index ada473818da6..44194f8ea311 100644 --- a/include/llvm-c/Initialization.h +++ b/include/llvm-c/Initialization.h @@ -13,8 +13,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_INITIALIZEPASSES_H -#define LLVM_C_INITIALIZEPASSES_H +#ifndef LLVM_C_INITIALIZATION_H +#define LLVM_C_INITIALIZATION_H #include "llvm-c/Core.h" diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h index 9f337cfba477..cedde5ea8e3a 100644 --- a/include/llvm-c/Linker.h +++ b/include/llvm-c/Linker.h @@ -20,20 +20,13 @@ extern "C" { #endif - -typedef enum { - LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */ - LLVMLinkerPreserveSource = 1 /* Preserve the source module. */ -} LLVMLinkerMode; - - /* Links the source module into the destination module, taking ownership * of the source module away from the caller. Optionally returns a * human-readable description of any errors that occurred in linking. * OutMessage must be disposed with LLVMDisposeMessage. The return value * is true if an error occurred, false otherwise. */ LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - LLVMLinkerMode Mode, char **OutMessage); + unsigned Unused, char **OutMessage); #ifdef __cplusplus } diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h index 4e6ff220b100..a9216d0364ad 100644 --- a/include/llvm-c/Support.h +++ b/include/llvm-c/Support.h @@ -47,6 +47,17 @@ typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; */ LLVMBool LLVMLoadLibraryPermanently(const char* Filename); +/** + * This function parses the given arguments using the LLVM command line parser. + * Note that the only stable thing about this function is its signature; you + * cannot rely on any particular set of command line arguments being interpreted + * the same way across LLVM versions. + * + * @see llvm::cl::ParseCommandLineOptions() + */ +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview); + #ifdef __cplusplus } #endif diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 0ca72cec0cd2..7ad1ad1d0564 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -35,6 +35,9 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); +/** See llvm::createAlignmentFromAssumptionsPass function. */ +void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM); + /** See llvm::createCFGSimplificationPass function. */ void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); @@ -86,6 +89,9 @@ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); /** See llvm::createPartiallyInlineLibCallsPass function. */ void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); +/** See llvm::createLowerSwitchPass function. */ +void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); + /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); @@ -132,6 +138,9 @@ void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); +/** See llvm::createScopedNoAliasAAPass function */ +void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); + /** See llvm::createBasicAliasAnalysisPass function */ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index c525710ae1a1..3f30d6d535d2 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 10 +#define LTO_API_VERSION 11 /** * \since prior to LTO_API_VERSION=3 @@ -178,6 +178,35 @@ lto_module_create_from_memory_with_path(const void* mem, size_t length, const char *path); /** + * \brief Loads an object file in its own context. + * + * Loads an object file in its own LLVMContext. This function call is + * thread-safe. However, modules created this way should not be merged into an + * lto_code_gen_t using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_local_context(const void *mem, size_t length, + const char *path); + +/** + * \brief Loads an object file in the codegen context. + * + * Loads an object file into the same context as \c cg. The module is safe to + * add using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_codegen_context(const void *mem, size_t length, + const char *path, lto_code_gen_t cg); + +/** * Loads an object file from disk. The seek point of fd is not preserved. * Returns NULL on error (check lto_get_error_message() for details). * @@ -324,12 +353,27 @@ extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t, * Instantiates a code generator. * Returns NULL on error (check lto_get_error_message() for details). * + * All modules added using \a lto_codegen_add_module() must have been created + * in the same context as the codegen. + * * \since prior to LTO_API_VERSION=3 */ extern lto_code_gen_t lto_codegen_create(void); /** + * \brief Instantiate a code generator in its own context. + * + * Instantiates a code generator in its own context. Modules added via \a + * lto_codegen_add_module() must have all been created in the same context, + * using \a lto_module_create_in_codegen_context(). + * + * \since LTO_API_VERSION=11 + */ +extern lto_code_gen_t +lto_codegen_create_in_local_context(void); + +/** * Frees all code generator and all memory it internally allocated. * Upon return the lto_code_gen_t is no longer valid. * @@ -342,6 +386,10 @@ lto_codegen_dispose(lto_code_gen_t); * Add an object module to the set of modules for which code will be generated. * Returns true on error (check lto_get_error_message() for details). * + * \c cg and \c mod must both be in the same context. See \a + * lto_codegen_create_in_local_context() and \a + * lto_module_create_in_codegen_context(). + * * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 50f1463d7eaa..26aae773624c 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -304,6 +304,38 @@ public: /// IEEE-754R 5.3.1: nextUp/nextDown. opStatus next(bool nextDown); + /// \brief Operator+ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator+(const APFloat &RHS) const { + APFloat Result = *this; + Result.add(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator- overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator-(const APFloat &RHS) const { + APFloat Result = *this; + Result.subtract(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator* overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator*(const APFloat &RHS) const { + APFloat Result = *this; + Result.multiply(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator/ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator/(const APFloat &RHS) const { + APFloat Result = *this; + Result.divide(RHS, rmNearestTiesToEven); + return Result; + } + /// @} /// \name Sign operations. @@ -313,6 +345,13 @@ public: void clearSign(); void copySign(const APFloat &); + /// \brief A static helper to produce a copy of an APFloat value with its sign + /// copied from some other APFloat. + static APFloat copySign(APFloat Value, const APFloat &Sign) { + Value.copySign(Sign); + return std::move(Value); + } + /// @} /// \name Conversions @@ -452,6 +491,36 @@ public: /// return true. bool getExactInverse(APFloat *inv) const; + /// \brief Enumeration of \c ilogb error results. + enum IlogbErrorKinds { + IEK_Zero = INT_MIN+1, + IEK_NaN = INT_MIN, + IEK_Inf = INT_MAX + }; + + /// \brief Returns the exponent of the internal representation of the APFloat. + /// + /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). + /// For special APFloat values, this returns special error codes: + /// + /// NaN -> \c IEK_NaN + /// 0 -> \c IEK_Zero + /// Inf -> \c IEK_Inf + /// + friend int ilogb(const APFloat &Arg) { + if (Arg.isNaN()) + return IEK_NaN; + if (Arg.isZero()) + return IEK_Zero; + if (Arg.isInfinity()) + return IEK_Inf; + + return Arg.exponent; + } + + /// \brief Returns: X * 2^Exp for integral exponents. + friend APFloat scalbn(APFloat X, int Exp); + private: /// \name Simple Queries @@ -573,11 +642,41 @@ private: unsigned int sign : 1; }; -/// See friend declaration above. +/// See friend declarations above. /// -/// This additional declaration is required in order to compile LLVM with IBM +/// These additional declarations are required in order to compile LLVM with IBM /// xlC compiler. hash_code hash_value(const APFloat &Arg); +APFloat scalbn(APFloat X, int Exp); + +/// \brief Returns the absolute value of the argument. +inline APFloat abs(APFloat X) { + X.clearSign(); + return X; +} + +/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat minnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat maxnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + } // namespace llvm #endif // LLVM_ADT_APFLOAT_H diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index aa3c3f67ec10..025397d9ce45 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -91,6 +91,8 @@ class APInt { APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t)) }; + friend struct DenseMapAPIntKeyInfo; + /// \brief Fast internal constructor /// /// This constructor is used only internally for speed of construction of @@ -277,7 +279,6 @@ public: /// Simply makes *this a copy of that. /// @brief Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; else @@ -656,13 +657,24 @@ public: /// @brief Move assignment operator. APInt &operator=(APInt &&that) { - if (!isSingleWord()) + if (!isSingleWord()) { + // The MSVC STL shipped in 2013 requires that self move assignment be a + // no-op. Otherwise algorithms like stable_sort will produce answers + // where half of the output is left in a moved-from state. + if (this == &that) + return *this; delete[] pVal; + } - BitWidth = that.BitWidth; - VAL = that.VAL; + // Use memcpy so that type based alias analysis sees both VAL and pVal + // as modified. + memcpy(&VAL, &that.VAL, sizeof(uint64_t)); + // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that' + // first. + unsigned ThatBitWidth = that.BitWidth; that.BitWidth = 0; + BitWidth = ThatBitWidth; return *this; } @@ -936,7 +948,8 @@ public: APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; APInt smul_ov(const APInt &RHS, bool &Overflow) const; APInt umul_ov(const APInt &RHS, bool &Overflow) const; - APInt sshl_ov(unsigned Amt, bool &Overflow) const; + APInt sshl_ov(const APInt &Amt, bool &Overflow) const; + APInt ushl_ov(const APInt &Amt, bool &Overflow) const; /// \brief Array-indexing support. /// diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index ee34e9b53088..a6693f7992cd 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -269,19 +269,15 @@ public: else if (I2.getBitWidth() > I1.getBitWidth()) return isSameValue(I1.extend(I2.getBitWidth()), I2); - // We have a signedness mismatch. Turn the signed value into an unsigned - // value. - if (I1.isSigned()) { - if (I1.isNegative()) - return false; + assert(I1.isSigned() != I2.isSigned()); - return APSInt(I1, true) == I2; - } - - if (I2.isNegative()) + // We have a signedness mismatch. Check for negative values and do an + // unsigned compare if signs match. + if ((I1.isSigned() && I1.isNegative()) || + (!I1.isSigned() && I2.isNegative())) return false; - return I1 == APSInt(I2, true); + return I1.eq(I2); } /// Profile - Used to insert APSInt objects, or objects that contain APSInt diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 0fff505d8d01..8c14a423c8f5 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -11,6 +11,7 @@ #define LLVM_ADT_ARRAYREF_H #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include <vector> @@ -43,6 +44,19 @@ namespace llvm { /// The number of elements. size_type Length; + /// \brief A dummy "optional" type that is only created by implicit + /// conversion from a reference to T. + /// + /// This type must *only* be used in a function argument or as a copy of + /// a function argument, as otherwise it will hold a pointer to a temporary + /// past that temporaries' lifetime. + struct TRefOrNothing { + const T *TPtr; + + TRefOrNothing() : TPtr(nullptr) {} + TRefOrNothing(const T &TRef) : TPtr(&TRef) {} + }; + public: /// @name Constructors /// @{ @@ -90,6 +104,14 @@ namespace llvm { Length(Vec.size()) {} #endif + /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to + /// ensure that only ArrayRefs of pointers can be converted. + template <typename U> + ArrayRef(const ArrayRef<U *> &A, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type* = 0) + : Data(A.data()), Length(A.size()) {} + /// @} /// @name Simple Operations /// @{ @@ -131,7 +153,13 @@ namespace llvm { bool equals(ArrayRef RHS) const { if (Length != RHS.Length) return false; - return std::equal(begin(), end(), RHS.begin()); + // Don't use std::equal(), since it asserts in MSVC on nullptr iterators. + for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R) + // Match std::equal() in using == (instead of !=) to minimize API + // requirements of ArrayRef'ed types. + if (!(*L == *R)) + return false; + return true; } /// slice(n) - Chop off the first N elements of the array. @@ -176,6 +204,47 @@ namespace llvm { } /// @} + /// @{ + /// @name Convenience methods + + /// @brief Predicate for testing that the array equals the exact sequence of + /// arguments. + /// + /// Will return false if the size is not equal to the exact number of + /// arguments given or if the array elements don't equal the argument + /// elements in order. Currently supports up to 16 arguments, but can + /// easily be extended. + bool equals(TRefOrNothing Arg0 = TRefOrNothing(), + TRefOrNothing Arg1 = TRefOrNothing(), + TRefOrNothing Arg2 = TRefOrNothing(), + TRefOrNothing Arg3 = TRefOrNothing(), + TRefOrNothing Arg4 = TRefOrNothing(), + TRefOrNothing Arg5 = TRefOrNothing(), + TRefOrNothing Arg6 = TRefOrNothing(), + TRefOrNothing Arg7 = TRefOrNothing(), + TRefOrNothing Arg8 = TRefOrNothing(), + TRefOrNothing Arg9 = TRefOrNothing(), + TRefOrNothing Arg10 = TRefOrNothing(), + TRefOrNothing Arg11 = TRefOrNothing(), + TRefOrNothing Arg12 = TRefOrNothing(), + TRefOrNothing Arg13 = TRefOrNothing(), + TRefOrNothing Arg14 = TRefOrNothing(), + TRefOrNothing Arg15 = TRefOrNothing()) { + TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, + Arg6, Arg7, Arg8, Arg9, Arg10, Arg11, + Arg12, Arg13, Arg14, Arg15}; + if (size() > array_lengthof(Args)) + return false; + + for (unsigned i = 0, e = size(); i != e; ++i) + if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr) + return false; + + // Either the size is exactly as many args, or the next arg must be null. + return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr; + } + + /// @} }; /// MutableArrayRef - Represent a mutable reference to an array (0 or more diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 34e2284311b3..a40f694485bf 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -239,6 +239,7 @@ public: } BitVector &set(unsigned Idx) { + assert(Bits && "Bits never allocated"); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -450,6 +451,7 @@ public: // Grow the bitvector to have enough elements. Capacity = RHSWords; + assert(Capacity > 0 && "negative capacity?"); BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); @@ -545,6 +547,7 @@ private: void grow(unsigned NewSize) { Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + assert(Capacity > 0 && "realloc-ing zero space"); Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 85f37b9051b1..050f8ac150dd 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -31,26 +31,35 @@ namespace llvm { -template<typename KeyT, typename ValueT, - typename KeyInfoT = DenseMapInfo<KeyT>, - bool IsConst = false> +namespace detail { +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template <typename KeyT, typename ValueT> +struct DenseMapPair : public std::pair<KeyT, ValueT> { + KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } + const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } + ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } + const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; } +}; +} + +template < + typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, + typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false> class DenseMapIterator; -template<typename DerivedT, - typename KeyT, typename ValueT, typename KeyInfoT> +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> class DenseMapBase { -protected: - typedef std::pair<KeyT, ValueT> BucketT; - public: typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; - typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; - typedef DenseMapIterator<KeyT, ValueT, - KeyInfoT, true> const_iterator; + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator; + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true> + const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); @@ -88,12 +97,12 @@ public: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey)) { - if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { - P->second.~ValueT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); decrementNumEntries(); } - P->first = EmptyKey; + P->getFirst() = EmptyKey; } } assert(getNumEntries() == 0 && "Node count imbalance!"); @@ -144,7 +153,7 @@ public: ValueT lookup(const KeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return TheBucket->second; + return TheBucket->getSecond(); return ValueT(); } @@ -191,16 +200,16 @@ public: if (!LookupBucketFor(Val, TheBucket)) return false; // not in map. - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); return true; } void erase(iterator I) { BucketT *TheBucket = &*I; - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); } @@ -250,10 +259,10 @@ protected: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); } #ifndef NDEBUG @@ -269,7 +278,7 @@ protected: "# initial buckets must be a power of two!"); const KeyT EmptyKey = getEmptyKey(); for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) - new (&B->first) KeyT(EmptyKey); + new (&B->getFirst()) KeyT(EmptyKey); } void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { @@ -279,21 +288,21 @@ protected: const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { // Insert the key/value into the new table. BucketT *DestBucket; - bool FoundVal = LookupBucketFor(B->first, DestBucket); + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); - DestBucket->first = std::move(B->first); - new (&DestBucket->second) ValueT(std::move(B->second)); + DestBucket->getFirst() = std::move(B->getFirst()); + new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); incrementNumEntries(); // Free the value. - B->second.~ValueT(); + B->getSecond().~ValueT(); } - B->first.~KeyT(); + B->getFirst().~KeyT(); } #ifndef NDEBUG @@ -304,7 +313,9 @@ protected: } template <typename OtherBaseT> - void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) { + void copyFrom( + const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) { + assert(&other != this); assert(getNumBuckets() == other.getNumBuckets()); setNumEntries(other.getNumEntries()); @@ -315,10 +326,12 @@ protected: getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { - new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); - if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && - !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) - new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); + new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); } } @@ -395,8 +408,8 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(Value); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(Value); return TheBucket; } @@ -404,16 +417,16 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = std::move(Key); - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = std::move(Key); + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } @@ -445,7 +458,7 @@ private: // If we are writing over a tombstone, remember this. const KeyT EmptyKey = getEmptyKey(); - if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) decrementNumTombstones(); return TheBucket; @@ -479,14 +492,14 @@ private: while (1) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. - if (KeyInfoT::isEqual(Val, ThisBucket->first)) { + if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) { FoundBucket = ThisBucket; return true; } // If we found an empty bucket, the key doesn't exist in the set. // Insert it and return the default value. - if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; @@ -495,7 +508,8 @@ private: // If this is a tombstone, remember it. If Val ends up not in the map, we // prefer to return it than something that would require more probing. - if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) FoundTombstone = ThisBucket; // Remember the first tombstone found. // Otherwise, it's a hash collision or a tombstone, continue quadratic @@ -524,16 +538,15 @@ public: } }; -template<typename KeyT, typename ValueT, - typename KeyInfoT = DenseMapInfo<KeyT> > -class DenseMap - : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>, - KeyT, ValueT, KeyInfoT> { +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = detail::DenseMapPair<KeyT, ValueT>> +class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, + KeyT, ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>; + typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT; + friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; BucketT *Buckets; unsigned NumEntries; @@ -574,7 +587,8 @@ public: } DenseMap& operator=(const DenseMap& other) { - copyFrom(other); + if (&other != this) + copyFrom(other); return *this; } @@ -675,17 +689,17 @@ private: } }; -template<typename KeyT, typename ValueT, - unsigned InlineBuckets = 4, - typename KeyInfoT = DenseMapInfo<KeyT> > +template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = detail::DenseMapPair<KeyT, ValueT>> class SmallDenseMap - : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>, - KeyT, ValueT, KeyInfoT> { + : public DenseMapBase< + SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, + ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>; + typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT; + friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; unsigned Small : 1; unsigned NumEntries : 31; @@ -742,23 +756,23 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *LHSB = &getInlineBuckets()[i], *RHSB = &RHS.getInlineBuckets()[i]; - bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && - !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); - bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && - !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); if (hasLHSValue && hasRHSValue) { // Swap together if we can... std::swap(*LHSB, *RHSB); continue; } // Swap separately and handle any assymetry. - std::swap(LHSB->first, RHSB->first); + std::swap(LHSB->getFirst(), RHSB->getFirst()); if (hasLHSValue) { - new (&RHSB->second) ValueT(std::move(LHSB->second)); - LHSB->second.~ValueT(); + new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); } else if (hasRHSValue) { - new (&LHSB->second) ValueT(std::move(RHSB->second)); - RHSB->second.~ValueT(); + new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); } } return; @@ -783,12 +797,12 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *NewB = &LargeSide.getInlineBuckets()[i], *OldB = &SmallSide.getInlineBuckets()[i]; - new (&NewB->first) KeyT(std::move(OldB->first)); - OldB->first.~KeyT(); - if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && - !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { - new (&NewB->second) ValueT(std::move(OldB->second)); - OldB->second.~ValueT(); + new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); } } @@ -799,7 +813,8 @@ public: } SmallDenseMap& operator=(const SmallDenseMap& other) { - copyFrom(other); + if (&other != this) + copyFrom(other); return *this; } @@ -849,16 +864,16 @@ public: const KeyT EmptyKey = this->getEmptyKey(); const KeyT TombstoneKey = this->getTombstoneKey(); for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && "Too many inline buckets!"); - new (&TmpEnd->first) KeyT(std::move(P->first)); - new (&TmpEnd->second) ValueT(std::move(P->second)); + new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); ++TmpEnd; - P->second.~ValueT(); + P->getSecond().~ValueT(); } - P->first.~KeyT(); + P->getFirst().~KeyT(); } // Now make this map use the large rep, and move all the entries back @@ -969,13 +984,12 @@ private: } }; -template<typename KeyT, typename ValueT, - typename KeyInfoT, bool IsConst> +template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket, + bool IsConst> class DenseMapIterator { - typedef std::pair<KeyT, ValueT> Bucket; - typedef DenseMapIterator<KeyT, ValueT, - KeyInfoT, true> ConstIterator; - friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>; + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator; + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; + public: typedef ptrdiff_t difference_type; typedef typename std::conditional<IsConst, const Bucket, Bucket>::type @@ -996,9 +1010,9 @@ public: // If IsConst is true this is a converting constructor from iterator to // const_iterator and the default copy constructor is used. // Otherwise this is a copy constructor for iterator. - DenseMapIterator(const DenseMapIterator<KeyT, ValueT, - KeyInfoT, false>& I) - : Ptr(I.Ptr), End(I.End) {} + DenseMapIterator( + const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I) + : Ptr(I.Ptr), End(I.End) {} reference operator*() const { return *Ptr; @@ -1028,9 +1042,8 @@ private: const KeyT Empty = KeyInfoT::getEmptyKey(); const KeyT Tombstone = KeyInfoT::getTombstoneKey(); - while (Ptr != End && - (KeyInfoT::isEqual(Ptr->first, Empty) || - KeyInfoT::isEqual(Ptr->first, Tombstone))) + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) ++Ptr; } }; diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 37a81b0c7ee2..d34024005dfe 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -18,18 +18,34 @@ namespace llvm { +namespace detail { +struct DenseSetEmpty {}; + +// Use the empty base class trick so we can create a DenseMap where the buckets +// contain only a single item. +template <typename KeyT> class DenseSetPair : public DenseSetEmpty { + KeyT key; + +public: + KeyT &getFirst() { return key; } + const KeyT &getFirst() const { return key; } + DenseSetEmpty &getSecond() { return *this; } + const DenseSetEmpty &getSecond() const { return *this; } +}; +} + /// DenseSet - This implements a dense probed hash-table based set. -/// -/// FIXME: This is currently implemented directly in terms of DenseMap, this -/// should be optimized later if there is a need. template<typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT> > class DenseSet { - typedef DenseMap<ValueT, char, ValueInfoT> MapTy; + typedef DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT, + detail::DenseSetPair<ValueT>> MapTy; + static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), + "DenseMap buckets unexpectedly large!"); MapTy TheMap; public: typedef ValueT key_type; typedef ValueT value_type; - typedef unsigned size_type;
+ typedef unsigned size_type; explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} @@ -45,7 +61,7 @@ public: TheMap.clear(); } - /// Return 1 if the specified key is in the set, 0 otherwise.
+ /// Return 1 if the specified key is in the set, 0 otherwise. size_type count(const ValueT &V) const { return TheMap.count(V); } @@ -72,8 +88,8 @@ public: Iterator(const typename MapTy::iterator &i) : I(i) {} - ValueT& operator*() { return I->first; } - ValueT* operator->() { return &I->first; } + ValueT &operator*() { return I->getFirst(); } + ValueT *operator->() { return &I->getFirst(); } Iterator& operator++() { ++I; return *this; } bool operator==(const Iterator& X) const { return I == X.I; } @@ -92,8 +108,8 @@ public: ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} - const ValueT& operator*() { return I->first; } - const ValueT* operator->() { return &I->first; } + const ValueT &operator*() { return I->getFirst(); } + const ValueT *operator->() { return &I->getFirst(); } ConstIterator& operator++() { ++I; return *this; } bool operator==(const ConstIterator& X) const { return I == X.I; } @@ -110,11 +126,27 @@ public: const_iterator end() const { return ConstIterator(TheMap.end()); } iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); } + + /// Alternative version of find() which allows a different, and possibly less + /// expensive, key type. + /// The DenseMapInfo is responsible for supplying methods + /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type + /// used. + template <class LookupKeyT> + iterator find_as(const LookupKeyT &Val) { + return Iterator(TheMap.find_as(Val)); + } + template <class LookupKeyT> + const_iterator find_as(const LookupKeyT &Val) const { + return ConstIterator(TheMap.find_as(Val)); + } + void erase(Iterator I) { return TheMap.erase(I.I); } void erase(ConstIterator CI) { return TheMap.erase(CI.I); } std::pair<iterator, bool> insert(const ValueT &V) { - return TheMap.insert(std::make_pair(V, 0)); + detail::DenseSetEmpty Empty; + return TheMap.insert(std::make_pair(V, Empty)); } // Range insertion of values. diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index dfba43f3ac85..6cd9e68aea56 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -33,10 +33,10 @@ #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H #define LLVM_ADT_DEPTHFIRSTITERATOR_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include <set> #include <vector> @@ -231,6 +231,13 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) { return df_ext_iterator<T, SetTy>::end(G, S); } +template <class T, class SetTy> +iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G, + SetTy &S) { + return iterator_range<df_ext_iterator<T, SetTy>>(df_ext_begin(G, S), + df_ext_end(G, S)); +} + // Provide global definitions of inverse depth first iterators... template <class T, @@ -276,6 +283,13 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) { return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S); } +template <class T, class SetTy> +iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G, + SetTy &S) { + return iterator_range<idf_ext_iterator<T, SetTy>>(idf_ext_begin(G, S), + idf_ext_end(G, S)); +} + } // End llvm namespace #endif diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index f9df3781257e..c859c98d06b2 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -197,6 +197,9 @@ public: private: void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } + + template <typename X> + friend class IntrusiveRefCntPtr; }; template<class T, class U> diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 4e1fc1527270..1331b15b2d29 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -18,6 +18,7 @@ #define LLVM_ADT_MAPVECTOR_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include <vector> namespace llvm { @@ -37,26 +38,20 @@ class MapVector { public: typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; + typedef typename VectorType::reverse_iterator reverse_iterator; + typedef typename VectorType::const_reverse_iterator const_reverse_iterator; - size_type size() const { - return Vector.size(); - } - - iterator begin() { - return Vector.begin(); - } + size_type size() const { return Vector.size(); } - const_iterator begin() const { - return Vector.begin(); - } - - iterator end() { - return Vector.end(); - } + iterator begin() { return Vector.begin(); } + const_iterator begin() const { return Vector.begin(); } + iterator end() { return Vector.end(); } + const_iterator end() const { return Vector.end(); } - const_iterator end() const { - return Vector.end(); - } + reverse_iterator rbegin() { return Vector.rbegin(); } + const_reverse_iterator rbegin() const { return Vector.rbegin(); } + reverse_iterator rend() { return Vector.rend(); } + const_reverse_iterator rend() const { return Vector.rend(); } bool empty() const { return Vector.empty(); @@ -147,6 +142,17 @@ public: return Next; } + /// \brief Remove all elements with the key value Key. + /// + /// Returns the number of elements removed. + size_type erase(const KeyT &Key) { + auto Iterator = find(Key); + if (Iterator == end()) + return 0; + erase(Iterator); + return 1; + } + /// \brief Remove the elements that match the predicate. /// /// Erase all elements that match \c Pred in a single pass. Takes linear @@ -176,6 +182,14 @@ void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) { Vector.erase(O, Vector.end()); } +/// \brief A MapVector that performs no allocations if smaller than a certain +/// size. +template <typename KeyT, typename ValueT, unsigned N> +struct SmallMapVector + : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>, + SmallVector<std::pair<KeyT, ValueT>, N>> { +}; + } // end namespace llvm #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index ae8344da76a6..591872e6591a 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -20,6 +20,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include <cassert> +#include <new> #include <utility> namespace llvm { @@ -29,6 +30,8 @@ class Optional { AlignedCharArrayUnion<T> storage; bool hasVal; public: + typedef T value_type; + Optional(NoneType) : hasVal(false) {} explicit Optional() : hasVal(false) {} Optional(const T &y) : hasVal(true) { @@ -67,6 +70,61 @@ public: return *this; } +#if LLVM_HAS_VARIADIC_TEMPLATES + + /// Create a new object by constructing it in place with the given arguments. + template<typename ...ArgTypes> + void emplace(ArgTypes &&...Args) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<ArgTypes>(Args)...); + } + +#else + + /// Create a new object by default-constructing it in place. + void emplace() { + reset(); + hasVal = true; + new (storage.buffer) T(); + } + + /// Create a new object by constructing it in place with the given arguments. + template<typename T1> + void emplace(T1 &&A1) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<T1>(A1)); + } + + /// Create a new object by constructing it in place with the given arguments. + template<typename T1, typename T2> + void emplace(T1 &&A1, T2 &&A2) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2)); + } + + /// Create a new object by constructing it in place with the given arguments. + template<typename T1, typename T2, typename T3> + void emplace(T1 &&A1, T2 &&A2, T3 &&A3) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2), + std::forward<T3>(A3)); + } + + /// Create a new object by constructing it in place with the given arguments. + template<typename T1, typename T2, typename T3, typename T4> + void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2), + std::forward<T3>(A3), std::forward<T4>(A4)); + } + +#endif // LLVM_HAS_VARIADIC_TEMPLATES + static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -117,9 +175,19 @@ public: const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + template <typename U> + LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + return hasValue() ? getValue() : std::forward<U>(value); + } + #if LLVM_HAS_RVALUE_REFERENCE_THIS T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } + + template <typename U> + T getValueOr(U &&value) && { + return hasValue() ? std::move(getValue()) : std::forward<U>(value); + } #endif }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index dd8cc74b714e..dfadc3b85db6 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -57,7 +57,7 @@ public: // Return true if edge destination should be visited. template<typename NodeType> bool insertEdge(NodeType *From, NodeType *To) { - return Visited.insert(To); + return Visited.insert(To).second; } // Called after all children of BB have been visited. @@ -76,8 +76,9 @@ public: // Return true if edge destination should be visited, called with From = 0 for // the root node. // Graph edges can be pruned by specializing this function. - template<class NodeType> - bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); } + template <class NodeType> bool insertEdge(NodeType *From, NodeType *To) { + return Visited.insert(To).second; + } // Called after all children of BB have been visited. template<class NodeType> diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 1cef3933b5d6..4e56e4d74470 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -77,8 +77,11 @@ class function_ref<Ret(Params...)> { } public: - template<typename Callable> - function_ref(Callable &&callable) + template <typename Callable> + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn<typename std::remove_reference<Callable>::type>), callable(reinterpret_cast<intptr_t>(&callable)) {} Ret operator()(Params ...params) const { @@ -100,7 +103,10 @@ class function_ref<Ret()> { public: template<typename Callable> - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn<typename std::remove_reference<Callable>::type>), callable(reinterpret_cast<intptr_t>(&callable)) {} Ret operator()() const { return callback(callable); } @@ -119,7 +125,10 @@ class function_ref<Ret(Param1)> { public: template<typename Callable> - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn<typename std::remove_reference<Callable>::type>), callable(reinterpret_cast<intptr_t>(&callable)) {} Ret operator()(Param1 param1) { @@ -141,7 +150,10 @@ class function_ref<Ret(Param1, Param2)> { public: template<typename Callable> - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn<typename std::remove_reference<Callable>::type>), callable(reinterpret_cast<intptr_t>(&callable)) {} Ret operator()(Param1 param1, Param2 param2) { @@ -167,7 +179,10 @@ class function_ref<Ret(Param1, Param2, Param3)> { public: template<typename Callable> - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn<typename std::remove_reference<Callable>::type>), callable(reinterpret_cast<intptr_t>(&callable)) {} Ret operator()(Param1 param1, Param2 param2, Param3 param3) { @@ -530,6 +545,12 @@ make_unique(size_t n) { #endif +struct FreeDeleter { + void operator()(void* v) { + ::free(v); + } +}; + template<typename First, typename Second> struct pair_hash { size_t operator()(const std::pair<First, Second> &P) const { diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 02a6ea345834..2f60ecc92043 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -148,7 +148,7 @@ public: /// ScopeTy - This is a helpful typedef that allows clients to get easy access /// to the name of the scope for this hash table. typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy; - typedef unsigned size_type;
+ typedef unsigned size_type; private: typedef ScopedHashTableVal<K, V> ValTy; DenseMap<K, ValTy*, KInfo> TopLevelMap; @@ -171,7 +171,7 @@ public: AllocatorTy &getAllocator() { return Allocator; } const AllocatorTy &getAllocator() const { return Allocator; } - /// Return 1 if the specified key is in the table, 0 otherwise.
+ /// Return 1 if the specified key is in the table, 0 otherwise. size_type count(const K &Key) const { return TopLevelMap.count(Key); } diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 1e7d237045aa..a7fd408c854a 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -100,7 +100,7 @@ public: /// \brief Insert a new element into the SetVector. /// \returns true iff the element was inserted into the SetVector. bool insert(const value_type &X) { - bool result = set_.insert(X); + bool result = set_.insert(X).second; if (result) vector_.push_back(X); return result; @@ -110,7 +110,7 @@ public: template<typename It> void insert(It Start, It End) { for (; Start != End; ++Start) - if (set_.insert(*Start)) + if (set_.insert(*Start).second) vector_.push_back(*Start); } diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 0922017ea61a..1e2f365b1040 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -54,7 +54,7 @@ class SmallBitVector { }; public: - typedef unsigned size_type;
+ typedef unsigned size_type; // Encapsulation of a single bit. class reference { SmallBitVector &TheVector; @@ -292,8 +292,12 @@ public: } SmallBitVector &set(unsigned Idx) { - if (isSmall()) + if (isSmall()) { + assert(Idx <= static_cast<unsigned>( + std::numeric_limits<uintptr_t>::digits) && + "undefined behavior"); setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + } else getPointer()->set(Idx); return *this; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 74f3fd43cec4..cb1c5e1fa96a 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -22,6 +22,7 @@ #include <cstddef> #include <cstring> #include <iterator> +#include <utility> namespace llvm { @@ -100,7 +101,7 @@ protected: /// insert_imp - This returns true if the pointer was new to the set, false if /// it was already in the set. This is hidden from the client so that the /// derived class can check that the right type of pointer is passed in. - bool insert_imp(const void * Ptr); + std::pair<const void *const *, bool> insert_imp(const void *Ptr); /// erase_imp - If the set contains the specified pointer, remove it and /// return true, otherwise return false. This is hidden from the client so @@ -240,6 +241,8 @@ struct RoundUpToPowerOfTwo { template <typename PtrType> class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits<PtrType> PtrTraits; + + SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION; protected: // Constructors that forward to the base. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) @@ -251,10 +254,16 @@ protected: : SmallPtrSetImplBase(SmallStorage, SmallSize) {} public: - /// insert - This returns true if the pointer was new to the set, false if it - /// was already in the set. - bool insert(PtrType Ptr) { - return insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + typedef SmallPtrSetIterator<PtrType> iterator; + typedef SmallPtrSetIterator<PtrType> const_iterator; + + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. The bool component of the returned pair is true if and only if the + /// insertion takes place, and the iterator component of the pair points to + /// the element equal to Ptr. + std::pair<iterator, bool> insert(PtrType Ptr) { + auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); } /// erase - If the set contains the specified pointer, remove it and return @@ -274,8 +283,6 @@ public: insert(*I); } - typedef SmallPtrSetIterator<PtrType> iterator; - typedef SmallPtrSetIterator<PtrType> const_iterator; inline iterator begin() const { return iterator(CurArray, CurArray+CurArraySize); } diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index bb1971eb7c5d..bc6493554c8b 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_SMALLSET_H #define LLVM_ADT_SMALLSET_H +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include <set> @@ -60,16 +61,21 @@ public: /// insert - Insert an element into the set if it isn't already there. /// Returns true if the element is inserted (it was not in the set before). - bool insert(const T &V) { + /// The first value of the returned pair is unused and provided for + /// partial compatibility with the standard library self-associative container + /// concept. + // FIXME: Add iterators that abstract over the small and large form, and then + // return those here. + std::pair<NoneType, bool> insert(const T &V) { if (!isSmall()) - return Set.insert(V).second; + return std::make_pair(None, Set.insert(V).second); VIterator I = vfind(V); if (I != Vector.end()) // Don't reinsert if it already exists. - return false; + return std::make_pair(None, false); if (Vector.size() < N) { Vector.push_back(V); - return true; + return std::make_pair(None, true); } // Otherwise, grow from vector to set. @@ -78,7 +84,7 @@ public: Vector.pop_back(); } Set.insert(V); - return true; + return std::make_pair(None, true); } template <typename IterT> diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 82538e9bd108..44a352119b09 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -29,8 +29,7 @@ namespace llvm { -/// SmallVectorBase - This is all the non-templated stuff common to all -/// SmallVectors. +/// This is all the non-templated stuff common to all SmallVectors. class SmallVectorBase { protected: void *BeginX, *EndX, *CapacityX; @@ -39,12 +38,12 @@ protected: SmallVectorBase(void *FirstEl, size_t Size) : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} - /// grow_pod - This is an implementation of the grow() method which only works + /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); public: - /// size_in_bytes - This returns size()*sizeof(T). + /// This returns size()*sizeof(T). size_t size_in_bytes() const { return size_t((char*)EndX - (char*)BeginX); } @@ -59,10 +58,9 @@ public: template <typename T, unsigned N> struct SmallVectorStorage; -/// SmallVectorTemplateCommon - This is the part of SmallVectorTemplateBase -/// which does not depend on whether the type T is a POD. The extra dummy -/// template argument is used by ArrayRef to avoid unnecessarily requiring T -/// to be complete. +/// This is the part of SmallVectorTemplateBase which does not depend on whether +/// the type T is a POD. The extra dummy template argument is used by ArrayRef +/// to avoid unnecessarily requiring T to be complete. template <typename T, typename = void> class SmallVectorTemplateCommon : public SmallVectorBase { private: @@ -82,13 +80,13 @@ protected: SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); } - /// isSmall - Return true if this is a smallvector which has not had dynamic + /// Return true if this is a smallvector which has not had dynamic /// memory allocated for it. bool isSmall() const { return BeginX == static_cast<const void*>(&FirstEl); } - /// resetToSmall - Put this vector in a state of being small. + /// Put this vector in a state of being small. void resetToSmall() { BeginX = EndX = CapacityX = &FirstEl; } @@ -128,21 +126,20 @@ public: size_type size() const { return end()-begin(); } size_type max_size() const { return size_type(-1) / sizeof(T); } - /// capacity - Return the total number of elements in the currently allocated - /// buffer. + /// Return the total number of elements in the currently allocated buffer. size_t capacity() const { return capacity_ptr() - begin(); } - /// data - Return a pointer to the vector's buffer, even if empty(). + /// Return a pointer to the vector's buffer, even if empty(). pointer data() { return pointer(begin()); } - /// data - Return a pointer to the vector's buffer, even if empty(). + /// Return a pointer to the vector's buffer, even if empty(). const_pointer data() const { return const_pointer(begin()); } - reference operator[](unsigned idx) { - assert(begin() + idx < end()); + reference operator[](size_type idx) { + assert(idx < size()); return begin()[idx]; } - const_reference operator[](unsigned idx) const { - assert(begin() + idx < end()); + const_reference operator[](size_type idx) const { + assert(idx < size()); return begin()[idx]; } @@ -179,7 +176,7 @@ protected: } } - /// move - Use move-assignment to move the range [I, E) onto the + /// Use move-assignment to move the range [I, E) onto the /// objects starting with "Dest". This is just <memory>'s /// std::move, but not all stdlibs actually provide that. template<typename It1, typename It2> @@ -189,7 +186,7 @@ protected: return Dest; } - /// move_backward - Use move-assignment to move the range + /// Use move-assignment to move the range /// [I, E) onto the objects ending at "Dest", moving objects /// in reverse order. This is just <algorithm>'s /// std::move_backward, but not all stdlibs actually provide that. @@ -200,25 +197,24 @@ protected: return Dest; } - /// uninitialized_move - Move the range [I, E) into the uninitialized - /// memory starting with "Dest", constructing elements as needed. + /// Move the range [I, E) into the uninitialized memory starting with "Dest", + /// constructing elements as needed. template<typename It1, typename It2> static void uninitialized_move(It1 I, It1 E, It2 Dest) { for (; I != E; ++I, ++Dest) ::new ((void*) &*Dest) T(::std::move(*I)); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized - /// memory starting with "Dest", constructing elements as needed. + /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", + /// constructing elements as needed. template<typename It1, typename It2> static void uninitialized_copy(It1 I, It1 E, It2 Dest) { std::uninitialized_copy(I, E, Dest); } - /// grow - Grow the allocated memory (without initializing new - /// elements), doubling the size of the allocated memory. - /// Guarantees space for at least one more element, or MinSize more - /// elements if specified. + /// Grow the allocated memory (without initializing new elements), doubling + /// the size of the allocated memory. Guarantees space for at least one more + /// element, or MinSize more elements if specified. void grow(size_t MinSize = 0); public: @@ -240,6 +236,51 @@ public: this->setEnd(this->end()-1); this->end()->~T(); } + +#if LLVM_HAS_VARIADIC_TEMPLATES + template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); + this->setEnd(this->end() + 1); + } +#else +private: + template <typename Constructor> void emplace_back_impl(Constructor construct) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + construct((void *)this->end()); + this->setEnd(this->end() + 1); + } + +public: + void emplace_back() { + emplace_back_impl([](void *Mem) { ::new (Mem) T(); }); + } + template <typename T1> void emplace_back(T1 &&A1) { + emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward<T1>(A1)); }); + } + template <typename T1, typename T2> void emplace_back(T1 &&A1, T2 &&A2) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2)); + }); + } + template <typename T1, typename T2, typename T3> + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) { + T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3)); + emplace_back_impl([&](void *Mem) { + ::new (Mem) + T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3)); + }); + } + template <typename T1, typename T2, typename T3, typename T4> + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2), + std::forward<T3>(A3), std::forward<T4>(A4)); + }); + } +#endif // LLVM_HAS_VARIADIC_TEMPLATES }; // Define this out-of-line to dissuade the C++ compiler from inlining it. @@ -279,22 +320,21 @@ protected: // No need to do a destroy loop for POD's. static void destroy_range(T *, T *) {} - /// move - Use move-assignment to move the range [I, E) onto the + /// Use move-assignment to move the range [I, E) onto the /// objects starting with "Dest". For PODs, this is just memcpy. template<typename It1, typename It2> static It2 move(It1 I, It1 E, It2 Dest) { return ::std::copy(I, E, Dest); } - /// move_backward - Use move-assignment to move the range - /// [I, E) onto the objects ending at "Dest", moving objects - /// in reverse order. + /// Use move-assignment to move the range [I, E) onto the objects ending at + /// "Dest", moving objects in reverse order. template<typename It1, typename It2> static It2 move_backward(It1 I, It1 E, It2 Dest) { return ::std::copy_backward(I, E, Dest); } - /// uninitialized_move - Move the range [I, E) onto the uninitialized memory + /// Move the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename It1, typename It2> static void uninitialized_move(It1 I, It1 E, It2 Dest) { @@ -302,7 +342,7 @@ protected: uninitialized_copy(I, E, Dest); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename It1, typename It2> static void uninitialized_copy(It1 I, It1 E, It2 Dest) { @@ -310,7 +350,7 @@ protected: std::uninitialized_copy(I, E, Dest); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename T1, typename T2> static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { @@ -320,7 +360,7 @@ protected: memcpy(Dest, I, (E-I)*sizeof(T)); } - /// grow - double the size of the allocated memory, guaranteeing space for at + /// Double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. void grow(size_t MinSize = 0) { this->grow_pod(MinSize*sizeof(T), sizeof(T)); @@ -339,9 +379,8 @@ public: }; -/// SmallVectorImpl - This class consists of common code factored out of the -/// SmallVector class to reduce code duplication based on the SmallVector 'N' -/// template parameter. +/// This class consists of common code factored out of the SmallVector class to +/// reduce code duplication based on the SmallVector 'N' template parameter. template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; @@ -373,7 +412,7 @@ public: this->EndX = this->BeginX; } - void resize(unsigned N) { + void resize(size_type N) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -386,7 +425,7 @@ public: } } - void resize(unsigned N, const T &NV) { + void resize(size_type N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -398,7 +437,7 @@ public: } } - void reserve(unsigned N) { + void reserve(size_type N) { if (this->capacity() < N) this->grow(N); } @@ -411,8 +450,7 @@ public: void swap(SmallVectorImpl &RHS); - /// append - Add the specified range to the end of the SmallVector. - /// + /// Add the specified range to the end of the SmallVector. template<typename in_iter> void append(in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); @@ -427,8 +465,7 @@ public: this->setEnd(this->end() + NumInputs); } - /// append - Add the specified range to the end of the SmallVector. - /// + /// Add the specified range to the end of the SmallVector. void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) @@ -439,7 +476,7 @@ public: this->setEnd(this->end() + NumInputs); } - void assign(unsigned NumElts, const T &Elt) { + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) this->grow(NumElts); @@ -545,7 +582,7 @@ public: assert(I <= this->end() && "Inserting past the end of the vector."); // Ensure there is enough space. - reserve(static_cast<unsigned>(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -599,7 +636,7 @@ public: size_t NumToInsert = std::distance(From, To); // Ensure there is enough space. - reserve(static_cast<unsigned>(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -666,7 +703,7 @@ public: /// of the buffer when they know that more elements are available, and only /// update the size later. This avoids the cost of value initializing elements /// which will only be overwritten. - void set_size(unsigned N) { + void set_size(size_type N) { assert(N <= this->capacity()); this->setEnd(this->begin() + N); } @@ -692,7 +729,7 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { // Swap the shared elements. size_t NumShared = this->size(); if (NumShared > RHS.size()) NumShared = RHS.size(); - for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i) + for (size_type i = 0; i != NumShared; ++i) std::swap((*this)[i], RHS[i]); // Copy over the extra elts. @@ -833,7 +870,7 @@ struct SmallVectorStorage { template <typename T> struct SmallVectorStorage<T, 1> {}; template <typename T> struct SmallVectorStorage<T, 0> {}; -/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements /// in-place, which allows it to avoid heap allocation when the actual number of /// elements is below that threshold. This allows normal "small" cases to be @@ -843,13 +880,13 @@ template <typename T> struct SmallVectorStorage<T, 0> {}; /// template <typename T, unsigned N> class SmallVector : public SmallVectorImpl<T> { - /// Storage - Inline space for elements which aren't stored in the base class. + /// Inline space for elements which aren't stored in the base class. SmallVectorStorage<T, N> Storage; public: SmallVector() : SmallVectorImpl<T>(N) { } - explicit SmallVector(unsigned Size, const T &Value = T()) + explicit SmallVector(size_t Size, const T &Value = T()) : SmallVectorImpl<T>(N) { this->assign(Size, Value); } diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 36754d682355..d5bde2963fbd 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -45,7 +45,7 @@ struct SparseBitVectorElement : public ilist_node<SparseBitVectorElement<ElementSize> > { public: typedef unsigned long BitWord; - typedef unsigned size_type;
+ typedef unsigned size_type; enum { BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index dc1273eb7ff6..f858536b6ed8 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -185,7 +185,7 @@ public: typedef const ValueT &const_reference; typedef ValueT *pointer; typedef const ValueT *const_pointer; - typedef unsigned size_type;
+ typedef unsigned size_type; SparseMultiSet() : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {} diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 632d52ad9d82..9a13440000ac 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -124,7 +124,7 @@ class SparseSet { typedef typename KeyFunctorT::argument_type KeyT; typedef SmallVector<ValueT, 8> DenseT; - typedef unsigned size_type;
+ typedef unsigned size_type; DenseT Dense; SparseT *Sparse; unsigned Universe; diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index c40e5e2b3d87..3437607a0bd0 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -117,8 +117,9 @@ public: explicit StringMapEntry(unsigned strLen) : StringMapEntryBase(strLen), second() {} - StringMapEntry(unsigned strLen, ValueTy V) - : StringMapEntryBase(strLen), second(std::move(V)) {} + template <class InitTy> + StringMapEntry(unsigned strLen, InitTy &&V) + : StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {} StringRef getKey() const { return StringRef(getKeyData(), getKeyLength()); @@ -138,10 +139,9 @@ public: /// Create - Create a StringMapEntry for the specified key and default /// construct the value. - template<typename AllocatorTy, typename InitType> - static StringMapEntry *Create(StringRef Key, - AllocatorTy &Allocator, - InitType InitVal) { + template <typename AllocatorTy, typename InitType> + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, + InitType &&InitVal) { unsigned KeyLength = Key.size(); // Allocate a new item with space for the string at the end and a null @@ -154,7 +154,7 @@ public: static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); // Default construct the value. - new (NewItem) StringMapEntry(KeyLength, std::move(InitVal)); + new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal)); // Copy the string information. char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); @@ -170,28 +170,15 @@ public: /// Create - Create a StringMapEntry with normal malloc/free. template<typename InitType> - static StringMapEntry *Create(StringRef Key, InitType InitVal) { + static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { MallocAllocator A; - return Create(Key, A, std::move(InitVal)); + return Create(Key, A, std::forward<InitType>(InitVal)); } static StringMapEntry *Create(StringRef Key) { return Create(Key, ValueTy()); } - /// GetStringMapEntryFromValue - Given a value that is known to be embedded - /// into a StringMapEntry, return the StringMapEntry itself. - static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { - StringMapEntry *EPtr = 0; - char *Ptr = reinterpret_cast<char*>(&V) - - (reinterpret_cast<char*>(&EPtr->second) - - reinterpret_cast<char*>(EPtr)); - return *reinterpret_cast<StringMapEntry*>(Ptr); - } - static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { - return GetStringMapEntryFromValue(const_cast<ValueTy&>(V)); - } - /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded /// into a StringMapEntry, return the StringMapEntry itself. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { @@ -296,7 +283,7 @@ public: } ValueTy &operator[](StringRef Key) { - return GetOrCreateValue(Key).getValue(); + return insert(std::make_pair(Key, ValueTy())).first->second; } /// count - Return 1 if the element is in the map, 0 otherwise. @@ -363,18 +350,6 @@ public: NumTombstones = 0; } - /// GetOrCreateValue - Look up the specified key in the table. If a value - /// exists, return it. Otherwise, default construct a value, insert it, and - /// return. - template <typename InitTy> - MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) { - return *insert(std::make_pair(Key, std::move(Val))).first; - } - - MapEntryTy &GetOrCreateValue(StringRef Key) { - return GetOrCreateValue(Key, ValueTy()); - } - /// remove - Remove the specified key/value pair from the map, but do not /// erase it. This aborts if the key is not in the map. void remove(MapEntryTy *KeyValue) { diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 1f413e80553f..6111c42da9dc 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -51,12 +51,6 @@ namespace llvm { /// The length of the string. size_t Length; - // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min() - // Changing the arg of min to be an integer, instead of a reference to an - // integer works around this bug. - static size_t min(size_t a, size_t b) { return a < b ? a : b; } - static size_t max(size_t a, size_t b) { return a > b ? a : b; } - // Workaround memcmp issue with null pointers (undefined behavior) // by providing a specialized version static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { @@ -97,6 +91,13 @@ namespace llvm { iterator end() const { return Data + Length; } + const unsigned char *bytes_begin() const { + return reinterpret_cast<const unsigned char *>(begin()); + } + const unsigned char *bytes_end() const { + return reinterpret_cast<const unsigned char *>(end()); + } + /// @} /// @name String Operations /// @{ @@ -124,7 +125,7 @@ namespace llvm { } // copy - Allocate copy in Allocator and return StringRef to it. - template <typename Allocator> StringRef copy(Allocator &A) { + template <typename Allocator> StringRef copy(Allocator &A) const { char *S = A.template Allocate<char>(Length); std::copy(begin(), end(), S); return StringRef(S, Length); @@ -146,7 +147,7 @@ namespace llvm { /// is lexicographically less than, equal to, or greater than the \p RHS. int compare(StringRef RHS) const { // Check the prefix for a mismatch. - if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length))) + if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) return Res < 0 ? -1 : 1; // Otherwise the prefixes match, so we only need to check the lengths. @@ -237,7 +238,7 @@ namespace llvm { /// \returns The index of the first occurrence of \p C, or npos if not /// found. size_t find(char C, size_t From = 0) const { - for (size_t i = min(From, Length), e = Length; i != e; ++i) + for (size_t i = std::min(From, Length), e = Length; i != e; ++i) if (Data[i] == C) return i; return npos; @@ -254,7 +255,7 @@ namespace llvm { /// \returns The index of the last occurrence of \p C, or npos if not /// found. size_t rfind(char C, size_t From = npos) const { - From = min(From, Length); + From = std::min(From, Length); size_t i = From; while (i != 0) { --i; @@ -353,8 +354,11 @@ namespace llvm { typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type getAsInteger(unsigned Radix, T &Result) const { unsigned long long ULLVal; + // The additional cast to unsigned long long is required to avoid the + // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type + // 'unsigned __int64' when instantiating getAsInteger with T = bool. if (getAsUnsignedInteger(*this, Radix, ULLVal) || - static_cast<T>(ULLVal) != ULLVal) + static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal) return true; Result = ULLVal; return false; @@ -396,8 +400,8 @@ namespace llvm { /// exceeds the number of characters remaining in the string, the string /// suffix (starting with \p Start) will be returned. StringRef substr(size_t Start, size_t N = npos) const { - Start = min(Start, Length); - return StringRef(Data + Start, min(N, Length - Start)); + Start = std::min(Start, Length); + return StringRef(Data + Start, std::min(N, Length - Start)); } /// Return a StringRef equal to 'this' but with the first \p N elements @@ -425,8 +429,8 @@ namespace llvm { /// number of characters remaining in the string, the string suffix /// (starting with \p Start) will be returned. StringRef slice(size_t Start, size_t End) const { - Start = min(Start, Length); - End = min(max(Start, End), Length); + Start = std::min(Start, Length); + End = std::min(std::max(Start, End), Length); return StringRef(Data + Start, End - Start); } diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h index 7bea577f34d3..3e0cc200b6dd 100644 --- a/include/llvm/ADT/StringSet.h +++ b/include/llvm/ADT/StringSet.h @@ -24,20 +24,9 @@ namespace llvm { typedef llvm::StringMap<char, AllocatorTy> base; public: - /// insert - Insert the specified key into the set. If the key already - /// exists in the set, return false and ignore the request, otherwise insert - /// it and return true. - bool insert(StringRef Key) { - // Get or create the map entry for the key; if it doesn't exist the value - // type will be default constructed which we use to detect insert. - // - // We use '+' as the sentinel value in the map. + std::pair<typename base::iterator, bool> insert(StringRef Key) { assert(!Key.empty()); - StringMapEntry<char> &Entry = this->GetOrCreateValue(Key); - if (Entry.getValue() == '+') - return false; - Entry.setValue('+'); - return true; + return base::insert(std::make_pair(Key, '\0')); } }; } diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index 5669b2a81a40..15137f5ebf8c 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -96,10 +96,17 @@ public: return *this; } + /// Constructor from a single element. + explicit TinyPtrVector(EltTy Elt) : Val(Elt) {} + + /// Constructor from an ArrayRef. + explicit TinyPtrVector(ArrayRef<EltTy> Elts) + : Val(new VecTy(Elts.begin(), Elts.end())) {} + // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { if (Val.isNull()) - return ArrayRef<EltTy>(); + return None; if (Val.template is<EltTy>()) return *Val.getAddrOfPtr1(); return *Val.template get<VecTy*>(); diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index b96f11435520..8a685995256b 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -48,8 +48,6 @@ public: arm, // ARM (little endian): arm, armv.*, xscale armeb, // ARM (big endian): armeb - arm64, // ARM64 (little endian): arm64 - arm64_be, // ARM64 (big endian): arm64_be aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be hexagon, // Hexagon: hexagon @@ -62,6 +60,7 @@ public: ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 systemz, // SystemZ: s390x @@ -74,7 +73,11 @@ public: nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) - amdil, // amdil: amd IL + le64, // le64: generic little-endian 64-bit CPU (PNaCl / Emscripten) + amdil, // AMDIL + amdil64, // AMDIL with 64-bit pointers + hsail, // AMD HSAIL + hsail64, // AMD HSAIL with 64-bit pointers spir, // SPIR: standard portable IR for OpenCL 32-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version kalimba // Kalimba: generic kalimba @@ -92,7 +95,11 @@ public: ARMSubArch_v6t2, ARMSubArch_v5, ARMSubArch_v5te, - ARMSubArch_v4t + ARMSubArch_v4t, + + KalimbaSubArch_v3, + KalimbaSubArch_v4, + KalimbaSubArch_v5 }; enum VendorType { UnknownVendor, @@ -112,8 +119,6 @@ public: enum OSType { UnknownOS, - AuroraUX, - Cygwin, Darwin, DragonFly, FreeBSD, @@ -122,7 +127,6 @@ public: Linux, Lv2, // PS3 MacOSX, - MinGW32, // i*86-pc-mingw32, *-w64-mingw32 NetBSD, OpenBSD, Solaris, @@ -135,7 +139,8 @@ public: Bitrig, AIX, CUDA, // NVIDIA CUDA - NVCL // NVIDIA OpenCL + NVCL, // NVIDIA OpenCL + AMDHSA // AMD HSA Runtime }; enum EnvironmentType { UnknownEnvironment, @@ -361,10 +366,28 @@ public: return isMacOSX() || isiOS(); } + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + bool isOSFreeBSD() const { return getOS() == Triple::FreeBSD; } + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSBitrig() const { + return getOS() == Triple::Bitrig; + } + bool isWindowsMSVCEnvironment() const { return getOS() == Triple::Win32 && (getEnvironment() == Triple::UnknownEnvironment || @@ -380,13 +403,11 @@ public: } bool isWindowsCygwinEnvironment() const { - return getOS() == Triple::Cygwin || - (getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus); + return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus; } bool isWindowsGNUEnvironment() const { - return getOS() == Triple::MinGW32 || - (getOS() == Triple::Win32 && getEnvironment() == Triple::GNU); + return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU; } /// \brief Tests for either Cygwin or MinGW OS @@ -396,7 +417,8 @@ public: /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. bool isOSMSVCRT() const { - return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment(); + return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() || + isWindowsItaniumEnvironment(); } /// \brief Tests whether the OS is Windows. @@ -475,10 +497,6 @@ public: /// environment components with a single string. void setOSAndEnvironmentName(StringRef Str); - /// getArchNameForAssembler - Get an architecture name that is understood by - /// the target assembler. - const char *getArchNameForAssembler(); - /// @} /// @name Helpers to build variants of a particular triple. /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 4be3ee6f82db..05d2fea117cf 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -80,7 +80,7 @@ namespace llvm { /// StringRef) codegen as desired. class Twine { /// NodeKind - Represent the type of an argument. - enum NodeKind { + enum NodeKind : unsigned char { /// An empty string; the result of concatenating anything with it is also /// empty. NullKind, @@ -153,12 +153,10 @@ namespace llvm { /// RHS - The suffix in the concatenation, which may be uninitialized for /// Null or Empty kinds. Child RHS; - // enums stored as unsigned chars to save on space while some compilers - // don't support specifying the backing type for an enum /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char LHSKind; - /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char RHSKind; + NodeKind LHSKind; + /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). + NodeKind RHSKind; private: /// Construct a nullary twine; the kind must be NullKind or EmptyKind. @@ -238,10 +236,10 @@ namespace llvm { } /// getLHSKind - Get the NodeKind of the left-hand side. - NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + NodeKind getLHSKind() const { return LHSKind; } /// getRHSKind - Get the NodeKind of the right-hand side. - NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + NodeKind getRHSKind() const { return RHSKind; } /// printOneChild - Print one child from a twine. void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h index 0497aa70887c..403130c623eb 100644 --- a/include/llvm/ADT/VariadicFunction.h +++ b/include/llvm/ADT/VariadicFunction.h @@ -105,7 +105,7 @@ template <typename ResultT, typename ArgT, ResultT (*Func)(ArrayRef<const ArgT *>)> struct VariadicFunction { ResultT operator()() const { - return Func(ArrayRef<const ArgT *>()); + return Func(None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -152,7 +152,7 @@ template <typename ResultT, typename Param0T, typename ArgT, ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)> struct VariadicFunction1 { ResultT operator()(Param0T P0) const { - return Func(P0, ArrayRef<const ArgT *>()); + return Func(P0, None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -199,7 +199,7 @@ template <typename ResultT, typename Param0T, typename Param1T, typename ArgT, ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)> struct VariadicFunction2 { ResultT operator()(Param0T P0, Param1T P1) const { - return Func(P0, P1, ArrayRef<const ArgT *>()); + return Func(P0, P1, None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -248,7 +248,7 @@ template <typename ResultT, typename Param0T, typename Param1T, ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)> struct VariadicFunction3 { ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const { - return Func(P0, P1, P2, ArrayRef<const ArgT *>()); + return Func(P0, P1, P2, None); } #define LLVM_DEFINE_OVERLOAD(N) \ diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index bc148452f217..8c19a6f4547a 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -579,60 +579,6 @@ public: void splice(iterator where, iplist &L2, iterator first, iterator last) { if (first != last) transfer(where, L2, first, last); } - - - - //===----------------------------------------------------------------------=== - // High-Level Functionality that shouldn't really be here, but is part of list - // - - // These two functions are actually called remove/remove_if in list<>, but - // they actually do the job of erase, rename them accordingly. - // - void erase(const NodeTy &val) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (*I == val) erase(I); - I = next; - } - } - template<class Pr1> void erase_if(Pr1 pred) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (pred(*I)) erase(I); - I = next; - } - } - - template<class Pr2> void unique(Pr2 pred) { - if (empty()) return; - for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { - if (pred(*I)) - erase(Next); - else - I = Next; - Next = I; - } - } - void unique() { unique(op_equal); } - - template<class Pr3> void merge(iplist &right, Pr3 pred) { - iterator first1 = begin(), last1 = end(); - iterator first2 = right.begin(), last2 = right.end(); - while (first1 != last1 && first2 != last2) - if (pred(*first2, *first1)) { - iterator next = first2; - transfer(first1, right, first2, ++next); - first2 = next; - } else { - ++first1; - } - if (first2 != last2) transfer(last1, right, first2, last2); - } - void merge(iplist &right) { return merge(right, op_less); } - - template<class Pr3> void sort(Pr3 pred); - void sort() { sort(op_less); } }; diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index 85aa7a4b1f7f..26d0b55e4093 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_ILISTNODE_H -#define LLVM_ADT_ILISTNODE_H +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H namespace llvm { diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 56041dbb106c..e2c9e5ea6bda 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -10,8 +10,8 @@ #ifndef LLVM_ADT_ITERATOR_H #define LLVM_ADT_ITERATOR_H -#include <iterator> #include <cstddef> +#include <iterator> namespace llvm { diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index dd17d6c8f7b4..523a86f02e08 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -32,7 +32,6 @@ class iterator_range { IteratorT begin_iterator, end_iterator; public: - iterator_range() {} iterator_range(IteratorT begin_iterator, IteratorT end_iterator) : begin_iterator(std::move(begin_iterator)), end_iterator(std::move(end_iterator)) {} @@ -48,6 +47,10 @@ public: template <class T> iterator_range<T> make_range(T x, T y) { return iterator_range<T>(std::move(x), std::move(y)); } + +template <typename T> iterator_range<T> make_range(std::pair<T, T> p) { + return iterator_range<T>(std::move(p.first), std::move(p.second)); +} } #endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 689766446445..763f37298811 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -39,6 +39,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Metadata.h" namespace llvm { @@ -112,13 +113,14 @@ public: /// there are restrictions on stepping out of one object and into another. /// See http://llvm.org/docs/LangRef.html#pointeraliasing uint64_t Size; - /// TBAATag - The metadata node which describes the TBAA type of - /// the location, or null if there is no known unique tag. - const MDNode *TBAATag; + /// AATags - The metadata nodes which describes the aliasing of the + /// location (each member is null if that kind of information is + /// unavailable).. + AAMDNodes AATags; explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize, - const MDNode *N = nullptr) - : Ptr(P), Size(S), TBAATag(N) {} + const AAMDNodes &N = AAMDNodes()) + : Ptr(P), Size(S), AATags(N) {} Location getWithNewPtr(const Value *NewPtr) const { Location Copy(*this); @@ -132,9 +134,9 @@ public: return Copy; } - Location getWithoutTBAATag() const { + Location getWithoutAATags() const { Location Copy(*this); - Copy.TBAATag = nullptr; + Copy.AATags = AAMDNodes(); return Copy; } }; @@ -500,7 +502,7 @@ public: /// /// canBasicBlockModify - Return true if it is possible for execution of the - /// specified basic block to modify the value pointed to by Ptr. + /// specified basic block to modify the location Loc. bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); /// canBasicBlockModify - A convenience wrapper. @@ -508,17 +510,20 @@ public: return canBasicBlockModify(BB, Location(P, Size)); } - /// canInstructionRangeModify - Return true if it is possible for the - /// execution of the specified instructions to modify the value pointed to by - /// Ptr. The instructions to consider are all of the instructions in the - /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Location &Loc); + /// canInstructionRangeModRef - Return true if it is possible for the + /// execution of the specified instructions to mod\ref (according to the + /// mode) the location Loc. The instructions to consider are all + /// of the instructions in the range of [I1,I2] INCLUSIVE. + /// I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Location &Loc, + const ModRefResult Mode); - /// canInstructionRangeModify - A convenience wrapper. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, uint64_t Size) { - return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + /// canInstructionRangeModRef - A convenience wrapper. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Value *Ptr, + uint64_t Size, const ModRefResult Mode) { + return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode); } //===--------------------------------------------------------------------===// @@ -566,25 +571,23 @@ public: template<> struct DenseMapInfo<AliasAnalysis::Location> { static inline AliasAnalysis::Location getEmptyKey() { - return - AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(), - 0, nullptr); + return AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(), + 0); } static inline AliasAnalysis::Location getTombstoneKey() { - return - AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(), - 0, nullptr); + return AliasAnalysis::Location( + DenseMapInfo<const Value *>::getTombstoneKey(), 0); } static unsigned getHashValue(const AliasAnalysis::Location &Val) { return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^ DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^ - DenseMapInfo<const MDNode *>::getHashValue(Val.TBAATag); + DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags); } static bool isEqual(const AliasAnalysis::Location &LHS, const AliasAnalysis::Location &RHS) { return LHS.Ptr == RHS.Ptr && LHS.Size == RHS.Size && - LHS.TBAATag == RHS.TBAATag; + LHS.AATags == RHS.AATags; } }; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index e32b6d628b7f..036d58dfa810 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -20,6 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" #include <vector> @@ -40,11 +41,11 @@ class AliasSet : public ilist_node<AliasSet> { PointerRec **PrevInList, *NextInList; AliasSet *AS; uint64_t Size; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; public: PointerRec(Value *V) : Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0), - TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {} + AAInfo(DenseMapInfo<AAMDNodes>::getEmptyKey()) {} Value *getValue() const { return Val; } @@ -56,27 +57,27 @@ class AliasSet : public ilist_node<AliasSet> { return &NextInList; } - void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) { + void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) { if (NewSize > Size) Size = NewSize; - if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey()) - // We don't have a TBAAInfo yet. Set it to NewTBAAInfo. - TBAAInfo = NewTBAAInfo; - else if (TBAAInfo != NewTBAAInfo) - // NewTBAAInfo conflicts with TBAAInfo. - TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey(); + if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey()) + // We don't have a AAInfo yet. Set it to NewAAInfo. + AAInfo = NewAAInfo; + else if (AAInfo != NewAAInfo) + // NewAAInfo conflicts with AAInfo. + AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey(); } uint64_t getSize() const { return Size; } - /// getTBAAInfo - Return the TBAAInfo, or null if there is no + /// getAAInfo - Return the AAInfo, or null if there is no /// information or conflicting information. - const MDNode *getTBAAInfo() const { - // If we have missing or conflicting TBAAInfo, return null. - if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() || - TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey()) - return nullptr; - return TBAAInfo; + AAMDNodes getAAInfo() const { + // If we have missing or conflicting AAInfo, return null. + if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey() || + AAInfo == DenseMapInfo<AAMDNodes>::getTombstoneKey()) + return AAMDNodes(); + return AAInfo; } AliasSet *getAliasSet(AliasSetTracker &AST) { @@ -204,7 +205,7 @@ public: Value *getPointer() const { return CurNode->getValue(); } uint64_t getSize() const { return CurNode->getSize(); } - const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); } + AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); } iterator& operator++() { // Preincrement assert(CurNode && "Advancing past AliasSet.end()!"); @@ -250,7 +251,7 @@ private: void removeFromTracker(AliasSetTracker &AST); void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool KnownMustAlias = false); void addUnknownInst(Instruction *I, AliasAnalysis &AA); void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { @@ -270,7 +271,7 @@ public: /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// - bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, + bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; }; @@ -325,7 +326,7 @@ public: /// These methods return true if inserting the instruction resulted in the /// addition of a new alias set (i.e., the pointer did not alias anything). /// - bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location + bool add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc. bool add(LoadInst *LI); bool add(StoreInst *SI); bool add(VAArgInst *VAAI); @@ -338,7 +339,7 @@ public: /// be aliased by the specified instruction. These methods return true if any /// alias sets were eliminated. // Remove a location - bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); + bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); bool remove(LoadInst *LI); bool remove(StoreInst *SI); bool remove(VAArgInst *VAAI); @@ -357,20 +358,24 @@ public: /// true if a new alias set is created to contain the pointer (because the /// pointer didn't alias anything). AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool *New = nullptr); /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, - const MDNode *TBAAInfo) { - return findAliasSetForPointer(P, Size, TBAAInfo); + const AAMDNodes &AAInfo) { + return findAliasSetForPointer(P, Size, AAInfo); } /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const; + bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; + + /// Return true if the specified instruction "may" (or must) alias one of the + /// members in any of the sets. + bool containsUnknown(Instruction *I) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -417,16 +422,16 @@ private: return *Entry; } - AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, + AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, AliasSet::AccessType E, bool &NewSet) { NewSet = false; - AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet); + AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet); AS.AccessTy |= E; return AS; } AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo); + const AAMDNodes &AAInfo); AliasSet *findAliasSetForUnknownInst(Instruction *Inst); }; diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h new file mode 100644 index 000000000000..b129e6796328 --- /dev/null +++ b/include/llvm/Analysis/AssumptionCache.h @@ -0,0 +1,142 @@ +//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that keeps track of @llvm.assume intrinsics in +// the functions of a module (allowing assumptions within any function to be +// found cheaply by other parts of the optimizer). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H +#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include <memory> + +namespace llvm { + +/// \brief A cache of @llvm.assume calls within a function. +/// +/// This cache provides fast lookup of assumptions within a function by caching +/// them and amortizing the cost of scanning for them across all queries. The +/// cache is also conservatively self-updating so that it will never return +/// incorrect results about a function even as the function is being mutated. +/// However, flushing the cache and rebuilding it (or explicitly updating it) +/// may allow it to discover new assumptions. +class AssumptionCache { + /// \brief The function for which this cache is handling assumptions. + /// + /// We track this to lazily populate our assumptions. + Function &F; + + /// \brief Vector of weak value handles to calls of the @llvm.assume + /// intrinsic. + SmallVector<WeakVH, 4> AssumeHandles; + + /// \brief Flag tracking whether we have scanned the function yet. + /// + /// We want to be as lazy about this as possible, and so we scan the function + /// at the last moment. + bool Scanned; + + /// \brief Scan the function for assumptions and add them to the cache. + void scanFunction(); + +public: + /// \brief Construct an AssumptionCache from a function by scanning all of + /// its instructions. + AssumptionCache(Function &F) : F(F), Scanned(false) {} + + /// \brief Add an @llvm.assume intrinsic to this function's cache. + /// + /// The call passed in must be an instruction within this fuction and must + /// not already be in the cache. + void registerAssumption(CallInst *CI); + + /// \brief Clear the cache of @llvm.assume intrinsics for a function. + /// + /// It will be re-scanned the next time it is requested. + void clear() { + AssumeHandles.clear(); + Scanned = false; + } + + /// \brief Access the list of assumption handles currently tracked for this + /// fuction. + /// + /// Note that these produce weak handles that may be null. The caller must + /// handle that case. + /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>> + /// when we can write that to filter out the null values. Then caller code + /// will become simpler. + MutableArrayRef<WeakVH> assumptions() { + if (!Scanned) + scanFunction(); + return AssumeHandles; + } +}; + +/// \brief An immutable pass that tracks lazily created \c AssumptionCache +/// objects. +/// +/// This is essentially a workaround for the legacy pass manager's weaknesses +/// which associates each assumption cache with Function and clears it if the +/// function is deleted. The nature of the AssumptionCache is that it is not +/// invalidated by any changes to the function body and so this is sufficient +/// to be conservatively correct. +class AssumptionCacheTracker : public ImmutablePass { + /// A callback value handle applied to function objects, which we use to + /// delete our cache of intrinsics for a function when it is deleted. + class FunctionCallbackVH : public CallbackVH { + AssumptionCacheTracker *ACT; + void deleted() override; + + public: + typedef DenseMapInfo<Value *> DMI; + + FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr) + : CallbackVH(V), ACT(ACT) {} + }; + + friend FunctionCallbackVH; + + typedef DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>, + FunctionCallbackVH::DMI> FunctionCallsMap; + FunctionCallsMap AssumptionCaches; + +public: + /// \brief Get the cached assumptions for a function. + /// + /// If no assumptions are cached, this will scan the function. Otherwise, the + /// existing cache will be returned. + AssumptionCache &getAssumptionCache(Function &F); + + AssumptionCacheTracker(); + ~AssumptionCacheTracker(); + + void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } + + void verifyAnalysis() const override; + bool doFinalization(Module &) override { + verifyAnalysis(); + return false; + } + + static char ID; // Pass identification, replacement for typeid +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index bb256c7bbcc8..57b515420925 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -260,7 +260,7 @@ public: /// loop. /// /// This function should only be called when distributing mass. As long as - /// there are no irreducilbe edges to Node, then it will have complexity + /// there are no irreducible edges to Node, then it will have complexity /// O(1) in this context. /// /// In general, the complexity is O(L), where L is the number of loop diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4414c84f6b7a..89eef68d8431 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -111,6 +111,10 @@ public: void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors, uint32_t Weight); + static uint32_t getBranchWeightStackProtector(bool IsLikely) { + return IsLikely ? (1u << 20) - 1 : 1; + } + private: // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index e6d2ed1a6864..035764837e6f 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -72,13 +72,13 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); --i; } else if (ColNum == MaxColumns) { // Wrap lines. - if (LastSpace) { - OutStr.insert(LastSpace, "\\l..."); - ColNum = i - LastSpace; - LastSpace = 0; - i += 3; // The loop will advance 'i' again. - } - // Else keep trying to find a space. + // Wrap very long names even though we can't find a space. + if (!LastSpace) + LastSpace = i; + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. } else ++ColNum; diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 09101ae6d0d1..0d4fe932481b 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -18,138 +18,28 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H -#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H +#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H +#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H -#include "llvm/IR/PassManager.h" #include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/PassManager.h" namespace llvm { -class CGSCCAnalysisManager; - -class CGSCCPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCPassManager() {} - CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - /// \brief Run all of the CGSCC passes in this pass manager over a SCC. - PreservedAnalyses run(LazyCallGraph::SCC *C, - CGSCCAnalysisManager *AM = nullptr); - - template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) { - Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass))); - } - - static StringRef name() { return "CGSCCPassManager"; } - -private: - // Pull in the concept type and model template specialized for SCCs. - typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager> - CGSCCPassConcept; - template <typename PassT> - struct CGSCCPassModel - : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> { - CGSCCPassModel(PassT Pass) - : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>( - std::move(Pass)) {} - }; - - CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - - std::vector<std::unique_ptr<CGSCCPassConcept>> Passes; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class CGSCCAnalysisManager : public detail::AnalysisManagerBase< - CGSCCAnalysisManager, LazyCallGraph::SCC *> { - friend class detail::AnalysisManagerBase<CGSCCAnalysisManager, - LazyCallGraph::SCC *>; - typedef detail::AnalysisManagerBase<CGSCCAnalysisManager, - LazyCallGraph::SCC *> BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // Most public APIs are inherited from the CRTP base class. - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManager() {} - CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) - : BaseT(std::move(static_cast<BaseT &>(Arg))), - CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} - CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); - return *this; - } - - /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; - - /// \brief Clear the function analysis result cache. - /// - /// This routine allows cleaning up when the set of functions itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); - -private: - CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - CGSCCAnalysisManager & - operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, - LazyCallGraph::SCC *C) const; - - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Invalidate the results for a function.. - void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); +/// \brief The CGSCC pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequency of SCC passes over each SCC that the manager is run over. This +/// typedef serves as a convenient way to refer to this construct. +typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager; - /// \brief List of function analysis pass IDs and associated concept pointers. - /// - /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides both the pass ID and concept pointer such that it is - /// half of a bijection and provides storage for the actual result concept. - typedef std::list< - std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept< - LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT; - - /// \brief Map type from function pointer to our custom list type. - typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT> - CGSCCAnalysisResultListMapT; - - /// \brief Map from function to a list of function analysis results. - /// - /// Provides linear time removal of all analysis results for a function and - /// the ultimate storage for a particular cached analysis result. - CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; - - /// \brief Map type from a pair of analysis ID and function pointer to an - /// iterator into a particular result list. - typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>, - CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; - - /// \brief Map from an analysis ID and function to a particular cached - /// analysis result. - CGSCCAnalysisResultMapT CGSCCAnalysisResults; -}; +/// \brief The CGSCC analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This typedef serves as a convenient way to refer to this +/// construct in the adaptors and proxies used to integrate this into the larger +/// pass manager infrastructure. +typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager; /// \brief A module analysis which acts as a proxy for a CGSCC analysis /// manager. @@ -187,7 +77,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c CGSCCAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: CGSCCAnalysisManager *CGAM; @@ -195,12 +85,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; } + explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - CGSCCAnalysisManagerModuleProxy( - const CGSCCAnalysisManagerModuleProxy &Arg) + CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg) : CGAM(Arg.CGAM) {} CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) : CGAM(std::move(Arg.CGAM)) {} @@ -219,7 +110,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the CGSCC analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -257,7 +148,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(LazyCallGraph::SCC *) { return false; } + bool invalidate(LazyCallGraph::SCC &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -265,12 +156,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; } + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - ModuleAnalysisManagerCGSCCProxy( - const ModuleAnalysisManagerCGSCCProxy &Arg) + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg) : MAM(Arg.MAM) {} ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) : MAM(std::move(Arg.MAM)) {} @@ -283,7 +175,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(LazyCallGraph::SCC *) { return Result(*MAM); } + Result run(LazyCallGraph::SCC &) { return Result(*MAM); } private: static char PassID; @@ -323,7 +215,7 @@ public: } /// \brief Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { assert(AM && "We need analyses to compute the call graph!"); // Setup the CGSCC analysis manager from its proxy. @@ -335,15 +227,17 @@ public: PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { - PreservedAnalyses PassPA = Pass.run(&C, &CGAM); + PreservedAnalyses PassPA = Pass.run(C, &CGAM); // We know that the CGSCC pass couldn't have invalidated any other // SCC's analyses (that's the contract of a CGSCC pass), so - // directly handle the CGSCC analysis manager's invalidation here. + // directly handle the CGSCC analysis manager's invalidation here. We + // also update the preserved set of analyses to reflect that invalidated + // analyses are now safe to preserve. // FIXME: This isn't quite correct. We need to handle the case where the // pass updated the CG, particularly some child of the current SCC, and // invalidate its analyses. - CGAM.invalidate(&C, PassPA); + PassPA = CGAM.invalidate(C, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -409,7 +303,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); + bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -417,6 +311,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; } + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -441,7 +337,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(LazyCallGraph::SCC *C); + Result run(LazyCallGraph::SCC &C); private: static char PassID; @@ -479,7 +375,7 @@ public: const CGSCCAnalysisManager &getManager() const { return *CGAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const CGSCCAnalysisManager *CGAM; @@ -487,6 +383,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; } + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC @@ -505,7 +403,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c CGAM reference into the /// result. - Result run(Function *) { return Result(*CGAM); } + Result run(Function &) { return Result(*CGAM); } private: static char PassID; @@ -531,7 +429,8 @@ public: : Pass(Arg.Pass) {} CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { + friend void swap(CGSCCToFunctionPassAdaptor &LHS, + CGSCCToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -541,21 +440,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (LazyCallGraph::Node *N : *C) { - PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); + for (LazyCallGraph::Node *N : C) { + PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. + // Also, update the preserved analyses to reflect that once invalidated + // these can again be preserved. if (FAM) - FAM->invalidate(&N->getFunction(), PassPA); + PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -585,7 +486,6 @@ CGSCCToFunctionPassAdaptor<FunctionPassT> createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); } - } #endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 9a6a4a76eb73..76d9073799f8 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -58,7 +58,6 @@ #include "llvm/IR/Function.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" -#include "llvm/Support/IncludeFile.h" #include <map> namespace llvm { @@ -418,13 +417,24 @@ template <> struct GraphTraits<CallGraphNode *> { template <> struct GraphTraits<const CallGraphNode *> { typedef const CallGraphNode NodeType; - typedef NodeType::const_iterator ChildIteratorType; + + typedef CallGraphNode::CallRecord CGNPairTy; + typedef std::pointer_to_unary_function<CGNPairTy, const CallGraphNode *> + CGNDerefFun; static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } + + typedef mapped_iterator<NodeType::const_iterator, CGNDerefFun> + ChildIteratorType; + static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); } - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static inline ChildIteratorType child_end(NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + static const CallGraphNode *CGNDeref(CGNPairTy P) { return P.second; } }; template <> @@ -451,17 +461,24 @@ template <> struct GraphTraits<const CallGraph *> : public GraphTraits< const CallGraphNode *> { static NodeType *getEntryNode(const CallGraph *CGN) { - return CGN->getExternalCallingNode(); + return CGN->getExternalCallingNode(); // Start at the external node! } + typedef std::pair<const Function *, const CallGraphNode *> PairTy; + typedef std::pointer_to_unary_function<PairTy, const CallGraphNode &> + DerefFun; + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef CallGraph::const_iterator nodes_iterator; - static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); } - static nodes_iterator nodes_end(const CallGraph *CG) { return CG->end(); } + typedef mapped_iterator<CallGraph::const_iterator, DerefFun> nodes_iterator; + static nodes_iterator nodes_begin(const CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end(const CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + + static const CallGraphNode &CGdereference(PairTy P) { return *P.second; } }; } // End llvm namespace -// Make sure that any clients of this file link in CallGraph.cpp -FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph) - #endif diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 04b39c176946..2f5969129e02 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -16,10 +16,13 @@ #define LLVM_ANALYSIS_CODEMETRICS_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/CallSite.h" namespace llvm { +class AssumptionCache; class BasicBlock; +class Loop; class Function; class Instruction; class DataLayout; @@ -85,7 +88,18 @@ struct CodeMetrics { NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} /// \brief Add information about a block to the current state. - void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI); + void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI, + SmallPtrSetImpl<const Value*> &EphValues); + + /// \brief Collect a loop's ephemeral values (those used only by an assume + /// or similar intrinsics in the loop). + static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, + SmallPtrSetImpl<const Value *> &EphValues); + + /// \brief Collect a functions's ephemeral values (those used only by an + /// assume or similar intrinsics in the function). + static void collectEphemeralValues(const Function *L, AssumptionCache *AC, + SmallPtrSetImpl<const Value *> &EphValues); }; } diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index 53c832cbebee..cb74e9f32d3d 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -66,15 +66,15 @@ public: bool runOnFunction(Function &F) override { GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); std::string Filename = Name + "." + F.getName().str() + ".dot"; - std::string ErrorInfo; + std::error_code EC; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); std::string Title = GraphName + " for '" + F.getName().str() + "' function"; - if (ErrorInfo.empty()) + if (!EC) WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; @@ -129,14 +129,14 @@ public: bool runOnModule(Module &M) override { GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); std::string Filename = Name + ".dot"; - std::string ErrorInfo; + std::error_code EC; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); - if (ErrorInfo.empty()) + if (!EC) WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 279755e47622..1041e3f0a4a9 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -287,9 +287,9 @@ namespace llvm { /// The flag PossiblyLoopIndependent should be set by the caller /// if it appears that control flow can reach from Src to Dst /// without traversing a loop back edge. - Dependence *depends(Instruction *Src, - Instruction *Dst, - bool PossiblyLoopIndependent); + std::unique_ptr<Dependence> depends(Instruction *Src, + Instruction *Dst, + bool PossiblyLoopIndependent); /// getSplitIteration - Give a dependence that's splittable at some /// particular level, return the iteration that should be used to split @@ -331,7 +331,7 @@ namespace llvm { /// /// breaks the dependence and allows us to vectorize/parallelize /// both loops. - const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level); + const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level); private: AliasAnalysis *AA; @@ -523,6 +523,12 @@ namespace llvm { /// in LoopNest. bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; + /// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same + /// integer type by sign-extending one of them when necessary. + /// Sign-extending a subscript is safe because getelementptr assumes the + /// array subscripts are signed. + void unifySubscriptType(Subscript *Pair); + /// removeMatchingExtensions - Examines a subscript pair. /// If the source and destination are identically sign (or zero) /// extended, it strips off the extension in an effort to @@ -911,7 +917,7 @@ namespace llvm { bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, SmallVectorImpl<Subscript> &Pair, - const SCEV *ElementSize) const; + const SCEV *ElementSize); public: static char ID; // Class identification, replacement for typeinfo diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index f42b9cbbfedd..996700efdb60 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -102,7 +102,9 @@ public: void print(raw_ostream &OS) const; /// dump - Dump the dominance frontier to dbgs(). +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const; +#endif }; //===------------------------------------- diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 04df2cc35d46..735bfb83671d 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H -#define LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Debug.h" @@ -172,9 +172,7 @@ ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT, DomSetType &S = this->Frontiers[currentBB]; // Visit each block only once. - if (visited.count(currentBB) == 0) { - visited.insert(currentBB); - + if (visited.insert(currentBB).second) { // Loop over CFG successors to calculate DFlocal[currentNode] for (auto SI = BlockTraits::child_begin(currentBB), SE = BlockTraits::child_end(currentBB); diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h deleted file mode 100644 index 574c947f4ebb..000000000000 --- a/include/llvm/Analysis/FindUsedTypes.h +++ /dev/null @@ -1,66 +0,0 @@ -//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass is used to seek out all of the types in use by the program. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H -#define LLVM_ANALYSIS_FINDUSEDTYPES_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/Pass.h" - -namespace llvm { - -class Type; -class Value; - -class FindUsedTypes : public ModulePass { - SetVector<Type *> UsedTypes; -public: - static char ID; // Pass identification, replacement for typeid - FindUsedTypes() : ModulePass(ID) { - initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); - } - - /// getTypes - After the pass has been run, return the set containing all of - /// the types used in the module. - /// - const SetVector<Type *> &getTypes() const { return UsedTypes; } - - /// Print the types found in the module. If the optional Module parameter is - /// passed in, then the types are printed symbolically if possible, using the - /// symbol table from the module. - /// - void print(raw_ostream &o, const Module *M) const override; - -private: - /// IncorporateType - Incorporate one type and all of its subtypes into the - /// collection of used types. - /// - void IncorporateType(Type *Ty); - - /// IncorporateValue - Incorporate all of the types used by this value. - /// - void IncorporateValue(const Value *V); - -public: - /// run - This incorporates all types used by the specified module - bool runOnModule(Module &M) override; - - /// getAnalysisUsage - We do not modify anything. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h new file mode 100644 index 000000000000..fce5a1a92bd9 --- /dev/null +++ b/include/llvm/Analysis/FunctionTargetTransformInfo.h @@ -0,0 +1,49 @@ +//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass wraps a TargetTransformInfo in a FunctionPass so that it can +// forward along the current Function so that we can make target specific +// decisions based on the particular subtarget specified for each Function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H +#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H + +#include "TargetTransformInfo.h" +#include "llvm/Pass.h" + +namespace llvm { +class FunctionTargetTransformInfo final : public FunctionPass { +private: + const Function *Fn; + const TargetTransformInfo *TTI; + + FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) + LLVM_DELETED_FUNCTION; + void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; + +public: + static char ID; + FunctionTargetTransformInfo(); + + // Implementation boilerplate. + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override; + bool runOnFunction(Function &F) override; + + // Shimmed functions from TargetTransformInfo. + void + getUnrollingPreferences(Loop *L, + TargetTransformInfo::UnrollingPreferences &UP) const { + TTI->getUnrollingPreferences(Fn, L, UP); + } +}; +} +#endif diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index 6038872207c3..d1f037021773 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -174,7 +174,7 @@ public: /// dump - This method is used for debugging. void dump() const; protected: - bool AddUsersImpl(Instruction *I, SmallPtrSet<Loop*,16> &SimpleLoopNests); + bool AddUsersImpl(Instruction *I, SmallPtrSetImpl<Loop*> &SimpleLoopNests); }; Pass *createIVUsersPass(); diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index aaed716b6a11..a064cfc897b0 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -19,6 +19,7 @@ #include <climits> namespace llvm { +class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; @@ -100,6 +101,7 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { const TargetTransformInfo *TTI; + AssumptionCacheTracker *ACT; public: static char ID; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 2367c0bf77aa..b88e0899f19a 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -37,6 +37,7 @@ namespace llvm { template<typename T> class ArrayRef; + class AssumptionCache; class DominatorTree; class Instruction; class DataLayout; @@ -50,150 +51,193 @@ namespace llvm { Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySubInst - Given operands for a Sub, see if we can /// fold the result. If not, this returns null. Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. - Value *SimplifyFMulInst(Value *LHS, Value *RHS, - FastMathFlags FMF, + Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyMulInst - Given operands for a Mul, see if we can /// fold the result. If not, this returns null. Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySDivInst - Given operands for an SDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyUDivInst - Given operands for a UDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySRemInst - Given operands for an SRem, see if we can /// fold the result. If not, this returns null. Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyURemInst - Given operands for a URem, see if we can /// fold the result. If not, this returns null. Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyShlInst - Given operands for a Shl, see if we can /// fold the result. If not, this returns null. Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyLShrInst - Given operands for a LShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyAShrInst - Given operands for a AShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyXorInst - Given operands for a Xor, see if we can /// fold the result. If not, this returns null. Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + Instruction *CxtI = nullptr); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we /// can fold the result. If not, this returns null. @@ -201,13 +245,17 @@ namespace llvm { ArrayRef<unsigned> Idxs, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); //=== Helper functions for higher up the class hierarchy. @@ -217,14 +265,18 @@ namespace llvm { Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. @@ -233,7 +285,9 @@ namespace llvm { Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, User::op_iterator ArgEnd, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and set of arguments, see if we can fold the /// result. @@ -242,14 +296,16 @@ namespace llvm { Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); - + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses /// recursively. @@ -262,7 +318,8 @@ namespace llvm { bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); /// \brief Recursively attempt to simplify an instruction. /// @@ -273,7 +330,8 @@ namespace llvm { bool recursivelySimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); } // end namespace llvm #endif diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 73aff76efe83..3b51d44099fa 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -165,10 +165,10 @@ private: // bool ProcessInterval(NodeTy *Node) { BasicBlock *Header = getNodeHeader(Node); - if (Visited.count(Header)) return false; + if (!Visited.insert(Header).second) + return false; Interval *Int = new Interval(Header); - Visited.insert(Header); // The header has now been visited! // Check all of our successors to see if they are in the interval... for (typename GT::ChildIteratorType I = GT::child_begin(Node), diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 54760aa02466..591e794a3901 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -16,7 +16,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Pass.h" - #include <vector> namespace llvm { @@ -37,7 +36,9 @@ class JumpInstrTableInfo : public ImmutablePass { public: static char ID; - JumpInstrTableInfo(); + /// The default byte alignment for jump tables is 16, which is large but + /// usually safe. + JumpInstrTableInfo(uint64_t ByteAlign = 16); virtual ~JumpInstrTableInfo(); const char *getPassName() const override { return "Jump-Instruction Table Info"; @@ -52,9 +53,19 @@ public: /// Gets the tables. const JumpTables &getTables() const { return Tables; } + /// Gets the alignment in bytes of a jumptable entry. + uint64_t entryByteAlignment() const { return ByteAlignment; } private: JumpTables Tables; + + /// A power-of-two alignment of a jumptable entry. + uint64_t ByteAlignment; }; + +/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This +/// bound specifies the maximum number of bytes needed to represent an +/// unconditional jump or a trap instruction in the back end currently in use. +ModulePass *createJumpInstrTableInfoPass(unsigned Bound); } #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 70a4df51c1ed..b0b9068de34b 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -32,8 +32,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH -#define LLVM_ANALYSIS_LAZY_CALL_GRAPH +#ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H +#define LLVM_ANALYSIS_LAZYCALLGRAPH_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" @@ -46,11 +46,11 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/Allocator.h" #include <iterator> namespace llvm { -class ModuleAnalysisManager; class PreservedAnalyses; class raw_ostream; @@ -252,6 +252,12 @@ public: /// \brief Test if this SCC is a descendant of \a C. bool isDescendantOf(const SCC &C) const; + /// \brief Short name useful for debugging or logging. + /// + /// We use the name of the first function in the SCC to name the SCC for + /// the purposes of debugging and logging. + StringRef getName() const { return (*begin())->getFunction().getName(); } + ///@{ /// \name Mutation API /// @@ -537,11 +543,13 @@ public: static void *ID() { return (void *)&PassID; } - /// \brief Compute the \c LazyCallGraph for a the module \c M. + static StringRef name() { return "Lazy CallGraph Analysis"; } + + /// \brief Compute the \c LazyCallGraph for the module \c M. /// /// This just builds the set of entry points to the call graph. The rest is /// built lazily as it is walked. - LazyCallGraph run(Module *M) { return LazyCallGraph(*M); } + LazyCallGraph run(Module &M) { return LazyCallGraph(M); } private: static char PassID; @@ -556,7 +564,7 @@ class LazyCallGraphPrinterPass { public: explicit LazyCallGraphPrinterPass(raw_ostream &OS); - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM); static StringRef name() { return "LazyCallGraphPrinterPass"; } }; diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 2fe7386e7302..9a67d52c3696 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -18,16 +18,20 @@ #include "llvm/Pass.h" namespace llvm { + class AssumptionCache; class Constant; class DataLayout; + class DominatorTree; + class Instruction; class TargetLibraryInfo; class Value; -/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint -/// information. +/// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { + AssumptionCache *AC; const DataLayout *DL; class TargetLibraryInfo *TLI; + DominatorTree *DT; void *PImpl; LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; @@ -38,7 +42,7 @@ public: } ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } - /// Tristate - This is used to return true/false/dunno results. + /// This is used to return true/false/dunno results. enum Tristate { Unknown = -1, False = 0, True = 1 }; @@ -46,26 +50,33 @@ public: // Public query interface. - /// getPredicateOnEdge - Determine whether the specified value comparison - /// with a constant is known to be true or false on the specified CFG edge. + /// Determine whether the specified value comparison with a constant is known + /// to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, - BasicBlock *FromBB, BasicBlock *ToBB); + BasicBlock *FromBB, BasicBlock *ToBB, + Instruction *CxtI = nullptr); - - /// getConstant - Determine whether the specified value is known to be a + /// Determine whether the specified value comparison with a constant is known + /// to be true or false at the specified instruction + /// (from an assume intrinsic). Pred is a CmpInst predicate. + Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, + Instruction *CxtI); + + /// Determine whether the specified value is known to be a /// constant at the end of the specified block. Return null if not. - Constant *getConstant(Value *V, BasicBlock *BB); + Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); - /// getConstantOnEdge - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant on the specified edge. Return null if not. - Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB); + Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, + Instruction *CxtI = nullptr); - /// threadEdge - Inform the analysis cache that we have threaded an edge from + /// Inform the analysis cache that we have threaded an edge from /// PredBB to OldSucc to be from PredBB to NewSucc instead. void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); - /// eraseBlock - Inform the analysis cache that we have erased a block. + /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); // Implementation boilerplate. diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 25c59288f34b..0fe34539f8f7 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -44,14 +44,14 @@ bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, /// If it is set to 0, it will scan the whole block. You can also optionally /// specify an alias analysis implementation, which makes this more precise. /// -/// If TBAATag is non-null and a load or store is found, the TBAA tag from the -/// load or store is recorded there. If there is no TBAA tag or if no access +/// If AATags is non-null and a load or store is found, the AA tags from the +/// load or store are recorded there. If there are no AA tags or if no access /// is found, it is left unmodified. Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan = 6, AliasAnalysis *AA = nullptr, - MDNode **TBAATag = nullptr); + AAMDNodes *AATags = nullptr); } diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 726e28636ac6..8650000fcfb6 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -82,6 +82,11 @@ public: /// deleteAnalysisValue - Delete analysis info associated with value V. virtual void deleteAnalysisValue(Value *V, Loop *L) {} + /// Delete analysis info associated with Loop L. + /// Called to notify a Pass that a loop has been deleted and any + /// associated analysis values can be deleted. + virtual void deleteAnalysisLoop(Loop *L) {} + protected: /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone /// and most transformation passes should skip it. @@ -152,6 +157,10 @@ public: /// that implement simple analysis interface. void deleteSimpleAnalysisValue(Value *V, Loop *L); + /// Invoke deleteAnalysisLoop hook for all passes that implement simple + /// analysis interface. + void deleteSimpleAnalysisLoop(Loop *L); + private: std::deque<Loop *> LQ; bool skipThisLoop; diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 1c4441bea670..67fd70a4561f 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -28,6 +28,7 @@ namespace llvm { class Instruction; class CallSite; class AliasAnalysis; + class AssumptionCache; class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; @@ -281,12 +282,12 @@ namespace llvm { /// Size - The maximum size of the dereferences of the /// pointer. May be UnknownSize if the sizes are unknown. uint64_t Size; - /// TBAATag - The TBAA tag associated with dereferences of the - /// pointer. May be null if there are no tags or conflicting tags. - const MDNode *TBAATag; + /// AATags - The AA tags associated with dereferences of the + /// pointer. The members may be null if there are no tags or + /// conflicting tags. + AAMDNodes AATags; - NonLocalPointerInfo() - : Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {} + NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {} }; /// CachedNonLocalPointerInfo - This map stores the cached results of doing @@ -325,6 +326,7 @@ namespace llvm { AliasAnalysis *AA; const DataLayout *DL; DominatorTree *DT; + AssumptionCache *AC; std::unique_ptr<PredIteratorCache> PredCache; public: @@ -364,12 +366,16 @@ namespace llvm { /// getNonLocalPointerDependency - Perform a full dependency query for an - /// access to the specified (non-volatile) memory location, returning the - /// set of instructions that either define or clobber the value. + /// access to the QueryInst's specified memory location, returning the set + /// of instructions that either define or clobber the value. /// - /// This method assumes the pointer has a "NonLocal" dependency within BB. - void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, + /// Warning: For a volatile query instruction, the dependencies will be + /// accurate, and thus usable for reordering, but it is never legal to + /// remove the query instruction. + /// + /// This method assumes the pointer has a "NonLocal" dependency within + /// QueryInst's parent basic block. + void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl<NonLocalDepResult> &Result); /// removeInstruction - Remove an instruction from the dependence analysis, diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 69f59071f94f..38730d8ea4f3 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -18,6 +18,7 @@ #include "llvm/IR/Instruction.h" namespace llvm { + class AssumptionCache; class DominatorTree; class DataLayout; class TargetLibraryInfo; @@ -41,12 +42,15 @@ class PHITransAddr { /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; - + + /// A cache of @llvm.assume calls used by SimplifyInstruction. + AssumptionCache *AC; + /// InstInputs - The inputs for our symbolic address. SmallVector<Instruction*, 4> InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL) - : Addr(addr), DL(DL), TLI(nullptr) { + PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast<Instruction>(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index fd65ae5ca5b2..10a56059ae10 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -66,6 +66,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createCFLAliasAnalysisPass - This pass implements a set-based approach to + // alias analysis. + // + ImmutablePass *createCFLAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows /// about the semantics of a set of libcalls specified by LCI. The newly /// constructed pass takes ownership of the pointer that is provided. @@ -88,11 +95,20 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createScopedNoAliasAAPass - This pass implements metadata-based + // scoped noalias analysis. + // + ImmutablePass *createScopedNoAliasAAPass(); + + //===--------------------------------------------------------------------===// + // // createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based // alias analysis. // ImmutablePass *createObjCARCAliasAnalysisPass(); + FunctionPass *createPAEvalPass(); + //===--------------------------------------------------------------------===// // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index d330755a0871..72cd35754c8a 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -19,7 +19,7 @@ namespace llvm { /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to -/// compute the a post-dominator tree. +/// compute the post-dominator tree. /// struct PostDominatorTree : public FunctionPass { static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 49c88fd5caeb..6ff7f97d01f5 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -424,8 +424,10 @@ public: void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, PrintStyle Style = PrintNone) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// @brief Print the region to stderr. void dump() const; +#endif /// @brief Check if the region contains a BasicBlock. /// @@ -732,7 +734,9 @@ public: static typename RegionT::PrintStyle printStyle; void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const; +#endif void releaseMemory(); diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index 4266b84c32c4..b0dc26312aaa 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -12,11 +12,11 @@ #ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H #define LLVM_ANALYSIS_REGIONINFOIMPL_H -#include "llvm/Analysis/RegionInfo.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -25,7 +25,7 @@ #include <iterator> #include <set> -using namespace llvm; +namespace llvm { #define DEBUG_TYPE "region" @@ -916,4 +916,8 @@ void RegionInfoBase<Tr>::calculate(FuncT &F) { buildRegionsTree(DT->getNode(BB), TopLevelRegion); } +#undef DEBUG_TYPE + +} // end namespace llvm + #endif diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 617e54541ee1..f394e335257f 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -35,6 +35,7 @@ namespace llvm { class APInt; + class AssumptionCache; class Constant; class ConstantInt; class DominatorTree; @@ -128,9 +129,11 @@ namespace llvm { /// purposes. void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// dump - This method is used for debugging. /// void dump() const; +#endif }; // Specialize FoldingSetTrait for SCEV to avoid needing to compute @@ -221,6 +224,9 @@ namespace llvm { /// Function *F; + /// The tracker for @llvm.assume intrinsics in this function. + AssumptionCache *AC; + /// LI - The loop information for the function we are currently analyzing. /// LoopInfo *LI; @@ -257,24 +263,13 @@ namespace llvm { /// loop exit's branch condition evaluates to the not-taken path. This is a /// temporary pair of exact and max expressions that are eventually /// summarized in ExitNotTakenInfo and BackedgeTakenInfo. - /// - /// If MustExit is true, then the exit must be taken when the BECount - /// reaches Exact (and before surpassing Max). If MustExit is false, then - /// BECount may exceed Exact or Max if the loop exits via another branch. In - /// either case, the loop may exit early via another branch. - /// - /// MustExit is true for most cases. However, an exit guarded by an - /// (in)equality on a nonunit stride may be skipped. struct ExitLimit { const SCEV *Exact; const SCEV *Max; - bool MustExit; - /*implicit*/ ExitLimit(const SCEV *E) - : Exact(E), Max(E), MustExit(true) {} + /*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {} - ExitLimit(const SCEV *E, const SCEV *M, bool MustExit) - : Exact(E), Max(M), MustExit(MustExit) {} + ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {} /// hasAnyInfo - Test whether this ExitLimit contains any computed /// information, or whether it's all SCEVCouldNotCompute values. @@ -749,6 +744,13 @@ namespace llvm { bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// \brief Returns the maximum trip count of the loop if it is a single-exit + /// loop and we can compute a small maximum for that loop. + /// + /// Implemented in terms of the \c getSmallConstantTripCount overload with + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripCount(Loop *L); + /// getSmallConstantTripCount - Returns the maximum trip count of this loop /// as a normal unsigned value. Returns 0 if the trip count is unknown or /// not constant. This "trip count" assumes that control exits via @@ -758,6 +760,14 @@ namespace llvm { /// the loop exits prematurely via another branch. unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock); + /// \brief Returns the largest constant divisor of the trip count of the + /// loop if it is a single-exit loop and we can compute a small maximum for + /// that loop. + /// + /// Implemented in terms of the \c getSmallConstantTripMultiple overload with + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripMultiple(Loop *L); + /// getSmallConstantTripMultiple - Returns the largest constant divisor of /// the trip count of this loop as a normal unsigned value, if /// possible. This means that the actual trip count is always a multiple of diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 2f1b1c3841f3..ff82db19b9e7 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" @@ -577,7 +577,7 @@ namespace llvm { SmallPtrSet<const SCEV *, 8> Visited; void push(const SCEV *S) { - if (Visited.insert(S) && Visitor.follow(S)) + if (Visited.insert(S).second && Visitor.follow(S)) Worklist.push_back(S); } public: @@ -624,7 +624,7 @@ namespace llvm { } }; - /// Use SCEVTraversal to visit all nodes in the givien expression tree. + /// Use SCEVTraversal to visit all nodes in the given expression tree. template<typename SV> void visitAll(const SCEV *Root, SV& Visitor) { SCEVTraversal<SV> T(Visitor); diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index f57f3eb009a1..4bd5dd8a221e 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -28,6 +28,7 @@ namespace llvm { +class Function; class GlobalValue; class Loop; class Type; @@ -183,7 +184,7 @@ public: /// should probably move to simpler cost metrics using the above. /// Alternatively, we could split the cost interface into distinct code-size /// and execution-speed costs. This would allow modelling the core of this - /// query more accurately as the a call is a single small instruction, but + /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. virtual bool isLoweredToCall(const Function *F) const; @@ -227,7 +228,8 @@ public: /// \brief Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. - virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; + virtual void getUnrollingPreferences(const Function *F, Loop *L, + UnrollingPreferences &UP) const; /// @} @@ -268,6 +270,13 @@ public: int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const; + /// \brief Return true if the target works with masked instruction + /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. + /// AVX-512 architecture will also allow masks for non-consecutive memory + /// accesses. + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const; + /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store /// of the specified type. @@ -335,6 +344,9 @@ public: OK_NonUniformConstantValue // Operand is a non uniform constant value. }; + /// \brief Additional properties of an operand's values. + enum OperandValueProperties { OP_None = 0, OP_PowerOf2 = 1 }; + /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. @@ -343,15 +355,18 @@ public: /// \return The width of the largest scalar or vector register type. virtual unsigned getRegisterBitWidth(bool Vector) const; - /// \return The maximum unroll factor that the vectorizer should try to + /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaximumUnrollFactor() const; + virtual unsigned getMaxInterleaveFactor() const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, - OperandValueKind Opd1Info = OK_AnyValue, - OperandValueKind Opd2Info = OK_AnyValue) const; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, + OperandValueKind Opd1Info = OK_AnyValue, + OperandValueKind Opd2Info = OK_AnyValue, + OperandValueProperties Opd1PropInfo = OP_None, + OperandValueProperties Opd2PropInfo = OP_None) const; /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and @@ -416,6 +431,13 @@ public: virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; + /// \returns The cost, if any, of keeping values of the given types alive + /// over a callsite. + /// + /// Some types may require the use of register classes that do not have + /// any callee-saved registers, so would require a spill and fill. + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const; + /// @} /// Analysis group identification. diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 83b5408fb1c2..cc588381727d 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,6 +25,8 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; + class AssumptionCache; + class DominatorTree; class TargetLibraryInfo; /// Determine which bits of V are known to be either zero or one and return @@ -35,8 +37,11 @@ namespace llvm { /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0); + void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// Compute known bits from the range metadata. /// \p KnownZero the set of bits that are known to be zero void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, @@ -45,21 +50,29 @@ namespace llvm { /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0); + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// isKnownToBeAPowerOfTwo - Return true if the given value is known to have /// exactly one bit set when defined. For vectors return true if every /// element is known to be a power of two when defined. Supports values with /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. - bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0); + bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// isKnownNonZero - Return true if the given value is known to be non-zero /// when defined. For vectors return true if every element is known to be /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, - unsigned Depth = 0); + unsigned Depth = 0, AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be @@ -70,10 +83,12 @@ namespace llvm { /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, - const DataLayout *TD = nullptr, unsigned Depth = 0); + bool MaskedValueIsZero(Value *V, const APInt &Mask, + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); - /// ComputeNumSignBits - Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us @@ -83,7 +98,9 @@ namespace llvm { /// 'Op' must have a scalar integer type. /// unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, - unsigned Depth = 0); + unsigned Depth = 0, AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// ComputeMultiple - This function computes the integer multiple of Base that /// equals V. If successful, it returns true and returns the multiple in @@ -191,6 +208,24 @@ namespace llvm { /// and byval arguments. bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); + /// Return true if it is valid to use the assumptions provided by an + /// assume intrinsic, I, at the point in the control-flow identified by the + /// context instruction, CxtI. + bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, + const DataLayout *DL = nullptr, + const DominatorTree *DT = nullptr); + + enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; + OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); + OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); } // end namespace llvm #endif diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h index 165c46d6f271..7ef78d73da17 100644 --- a/include/llvm/AsmParser/Parser.h +++ b/include/llvm/AsmParser/Parser.h @@ -14,12 +14,11 @@ #ifndef LLVM_ASMPARSER_PARSER_H #define LLVM_ASMPARSER_PARSER_H -#include <string> +#include "llvm/Support/MemoryBuffer.h" namespace llvm { class Module; -class MemoryBuffer; class SMDiagnostic; class LLVMContext; @@ -29,11 +28,12 @@ class LLVMContext; /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. /// @brief Parse LLVM Assembly from a file -Module *ParseAssemblyFile( - const std::string &Filename, ///< The name of the file to parse - SMDiagnostic &Error, ///< Error result info. - LLVMContext &Context ///< Context in which to allocate globals info. -); +/// @param Filename The name of the file to parse +/// @param Error Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr<Module> parseAssemblyFile(StringRef Filename, + SMDiagnostic &Error, + LLVMContext &Context); /// The function is a secondary interface to the LLVM Assembly Parser. It parses /// an ASCII string that (presumably) contains LLVM Assembly code. It returns a @@ -41,23 +41,31 @@ Module *ParseAssemblyFile( /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. /// @brief Parse LLVM Assembly from a string -Module *ParseAssemblyString( - const char *AsmString, ///< The string containing assembly - Module *M, ///< A module to add the assembly too. - SMDiagnostic &Error, ///< Error result info. - LLVMContext &Context -); +/// @param AsmString The string containing assembly +/// @param Error Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr<Module> parseAssemblyString(StringRef AsmString, + SMDiagnostic &Error, + LLVMContext &Context); + +/// parseAssemblyFile and parseAssemblyString are wrappers around this function. +/// @brief Parse LLVM Assembly from a MemoryBuffer. +/// @param F The MemoryBuffer containing assembly +/// @param Err Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, + LLVMContext &Context); /// This function is the low-level interface to the LLVM Assembly Parser. -/// ParseAssemblyFile and ParseAssemblyString are wrappers around this function. -/// @brief Parse LLVM Assembly from a MemoryBuffer. This function *always* -/// takes ownership of the MemoryBuffer. -Module *ParseAssembly( - MemoryBuffer *F, ///< The MemoryBuffer containing assembly - Module *M, ///< A module to add the assembly too. - SMDiagnostic &Err, ///< Error result info. - LLVMContext &Context -); +/// This is kept as an independent function instead of being inlined into +/// parseAssembly for the convenience of interactive users that want to add +/// recently parsed bits to an existing module. +/// +/// @param F The MemoryBuffer containing assembly +/// @param M The module to add data to. +/// @param Err Error result info. +/// @return true on error. +bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err); } // End llvm namespace diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index b510daf33147..ed2dcf84f924 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -18,6 +18,7 @@ #ifndef LLVM_BITCODE_BITCODES_H #define LLVM_BITCODE_BITCODES_H +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -161,16 +162,13 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; }; /// BitCodeAbbrev - This class represents an abbreviation record. An /// abbreviation allows a complex record that has redundancy to be stored in a /// specialized format instead of the fully-general, fully-vbr, format. -class BitCodeAbbrev { +class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> { SmallVector<BitCodeAbbrevOp, 32> OperandList; - unsigned char RefCount; // Number of things using this. ~BitCodeAbbrev() {} -public: - BitCodeAbbrev() : RefCount(1) {} - - void addRef() { ++RefCount; } - void dropRef() { if (--RefCount == 0) delete this; } + // Only RefCountedBase is allowed to delete. + friend class RefCountedBase<BitCodeAbbrev>; +public: unsigned getNumOperandInfos() const { return static_cast<unsigned>(OperandList.size()); } diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index 898cd523bd08..8fe9b7e8434d 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_BITCODE_WRITER_PASS_H -#define LLVM_BITCODE_BITCODE_WRITER_PASS_H +#ifndef LLVM_BITCODE_BITCODEWRITERPASS_H +#define LLVM_BITCODE_BITCODEWRITERPASS_H #include "llvm/ADT/StringRef.h" @@ -41,7 +41,7 @@ public: /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "BitcodeWriterPass"; } }; diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 6f478b72127d..865a3e668428 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -17,39 +17,37 @@ #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/StreamableMemoryObject.h" +#include "llvm/Support/StreamingMemoryObject.h" #include <climits> #include <string> #include <vector> namespace llvm { - class Deserializer; +class Deserializer; -/// BitstreamReader - This class is used to read from an LLVM bitcode stream, -/// maintaining information that is global to decoding the entire file. While -/// a file is being read, multiple cursors can be independently advanced or -/// skipped around within the file. These are represented by the -/// BitstreamCursor class. +/// This class is used to read from an LLVM bitcode stream, maintaining +/// information that is global to decoding the entire file. While a file is +/// being read, multiple cursors can be independently advanced or skipped around +/// within the file. These are represented by the BitstreamCursor class. class BitstreamReader { public: - /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. - /// These describe abbreviations that all blocks of the specified ID inherit. + /// This contains information emitted to BLOCKINFO_BLOCK blocks. These + /// describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector<BitCodeAbbrev*> Abbrevs; + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; std::string Name; std::vector<std::pair<unsigned, std::string> > RecordNames; }; private: - std::unique_ptr<StreamableMemoryObject> BitcodeBytes; + std::unique_ptr<MemoryObject> BitcodeBytes; std::vector<BlockInfo> BlockInfoRecords; - /// IgnoreBlockInfoNames - This is set to true if we don't care about the - /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer - /// uses this. + /// This is set to true if we don't care about the block/record name + /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; @@ -58,13 +56,24 @@ public: BitstreamReader() : IgnoreBlockInfoNames(true) { } - BitstreamReader(const unsigned char *Start, const unsigned char *End) { - IgnoreBlockInfoNames = true; + BitstreamReader(const unsigned char *Start, const unsigned char *End) + : IgnoreBlockInfoNames(true) { init(Start, End); } - BitstreamReader(StreamableMemoryObject *bytes) { - BitcodeBytes.reset(bytes); + BitstreamReader(std::unique_ptr<MemoryObject> BitcodeBytes) + : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {} + + BitstreamReader(BitstreamReader &&Other) { + *this = std::move(Other); + } + + BitstreamReader &operator=(BitstreamReader &&Other) { + BitcodeBytes = std::move(Other.BitcodeBytes); + // Explicitly swap block info, so that nothing gets destroyed twice. + std::swap(BlockInfoRecords, Other.BlockInfoRecords); + IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames; + return *this; } void init(const unsigned char *Start, const unsigned char *End) { @@ -72,22 +81,9 @@ public: BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); } - StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } + MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } - ~BitstreamReader() { - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } - } - - /// CollectBlockInfoNames - This is called by clients that want block/record - /// name information. + /// This is called by clients that want block/record name information. void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } @@ -95,13 +91,13 @@ public: // Block Manipulation //===--------------------------------------------------------------------===// - /// hasBlockInfoRecords - Return true if we've already read and processed the - /// block info block for this Bitstream. We only process it for the first - /// cursor that walks over it. + /// Return true if we've already read and processed the block info block for + /// this Bitstream. We only process it for the first cursor that walks over + /// it. bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } - /// getBlockInfo - If there is block info for the specified ID, return it, - /// otherwise return null. + /// If there is block info for the specified ID, return it, otherwise return + /// null. const BlockInfo *getBlockInfo(unsigned BlockID) const { // Common case, the most recent entry matches BlockID. if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) @@ -123,23 +119,26 @@ public: BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } -}; + /// Takes block info from the other bitstream reader. + /// + /// This is a "take" operation because BlockInfo records are non-trivial, and + /// indeed rather expensive. + void takeBlockInfo(BitstreamReader &&Other) { + assert(!hasBlockInfoRecords()); + BlockInfoRecords = std::move(Other.BlockInfoRecords); + } +}; -/// BitstreamEntry - When advancing through a bitstream cursor, each advance can -/// discover a few different kinds of entries: -/// Error - Malformed bitcode was found. -/// EndBlock - We've reached the end of the current block, (or the end of the -/// file, which is treated like a series of EndBlock records. -/// SubBlock - This is the start of a new subblock of a specific ID. -/// Record - This is a record with a specific AbbrevID. -/// +/// When advancing through a bitstream cursor, each advance can discover a few +/// different kinds of entries: struct BitstreamEntry { enum { - Error, - EndBlock, - SubBlock, - Record + Error, // Malformed bitcode was found. + EndBlock, // We've reached the end of the current block, (or the end of the + // file, which is treated like a series of EndBlock records. + SubBlock, // This is the start of a new subblock of a specific ID. + Record // This is a record with a specific AbbrevID. } Kind; unsigned ID; @@ -158,9 +157,9 @@ struct BitstreamEntry { } }; -/// BitstreamCursor - This represents a position within a bitcode file. There -/// may be multiple independent cursors reading within one bitstream, each -/// maintaining their own local state. +/// This represents a position within a bitcode file. There may be multiple +/// independent cursors reading within one bitstream, each maintaining their own +/// local state. /// /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not /// be passed by value. @@ -169,92 +168,74 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; + // The size of the bicode. 0 if we don't know it yet. + size_t Size; - /// CurWord/word_t - This is the current data we have pulled from the stream - /// but have not returned to the client. This is specifically and - /// intentionally defined to follow the word size of the host machine for - /// efficiency. We use word_t in places that are aware of this to make it - /// perfectly explicit what is going on. - typedef uint32_t word_t; + /// This is the current data we have pulled from the stream but have not + /// returned to the client. This is specifically and intentionally defined to + /// follow the word size of the host machine for efficiency. We use word_t in + /// places that are aware of this to make it perfectly explicit what is going + /// on. + typedef size_t word_t; word_t CurWord; - /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31/63] inclusive (depending on word size). + /// This is the number of bits in CurWord that are valid. This is always from + /// [0...bits_of(size_t)-1] inclusive. unsigned BitsInCurWord; - // CurCodeSize - This is the declared size of code values used for the current - // block, in bits. + // This is the declared size of code values used for the current block, in + // bits. unsigned CurCodeSize; - /// CurAbbrevs - Abbrevs installed at in this block. - std::vector<BitCodeAbbrev*> CurAbbrevs; + /// Abbrevs installed at in this block. + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; struct Block { unsigned PrevCodeSize; - std::vector<BitCodeAbbrev*> PrevAbbrevs; + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} }; - /// BlockScope - This tracks the codesize of parent blocks. + /// This tracks the codesize of parent blocks. SmallVector<Block, 8> BlockScope; public: - BitstreamCursor() : BitStream(nullptr), NextChar(0) {} - BitstreamCursor(const BitstreamCursor &RHS) - : BitStream(nullptr), NextChar(0) { - operator=(RHS); - } + BitstreamCursor() { init(nullptr); } - explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { - NextChar = 0; - CurWord = 0; - BitsInCurWord = 0; - CurCodeSize = 2; - } + explicit BitstreamCursor(BitstreamReader &R) { init(&R); } - void init(BitstreamReader &R) { + void init(BitstreamReader *R) { freeState(); - BitStream = &R; + BitStream = R; NextChar = 0; - CurWord = 0; + Size = 0; BitsInCurWord = 0; CurCodeSize = 2; } - ~BitstreamCursor() { - freeState(); - } - - void operator=(const BitstreamCursor &RHS); - void freeState(); - bool isEndPos(size_t pos) { - return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); - } - bool canSkipToPos(size_t pos) const { // pos can be skipped to if it is a valid address or one byte past the end. return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( static_cast<uint64_t>(pos - 1)); } - uint32_t getWord(size_t pos) { - uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf); - return *reinterpret_cast<support::ulittle32_t *>(buf); - } - bool AtEndOfStream() { - return BitsInCurWord == 0 && isEndPos(NextChar); + if (BitsInCurWord != 0) + return false; + if (Size != 0) + return Size == NextChar; + fillCurWord(); + return BitsInCurWord == 0; } - /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + /// Return the number of bits used to encode an abbrev #. unsigned getAbbrevIDWidth() const { return CurCodeSize; } - /// GetCurrentBitNo - Return the bit # of the bit we are reading. + /// Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { return NextChar*CHAR_BIT - BitsInCurWord; } @@ -268,19 +249,17 @@ public: /// Flags that modify the behavior of advance(). enum { - /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does - /// not automatically pop the block scope when the end of a block is - /// reached. + /// If this flag is used, the advance() method does not automatically pop + /// the block scope when the end of a block is reached. AF_DontPopBlockAtEnd = 1, - /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are - /// returned just like normal records. + /// If this flag is used, abbrev entries are returned just like normal + /// records. AF_DontAutoprocessAbbrevs = 2 }; - /// advance - Advance the current bitstream, returning the next entry in the - /// stream. - BitstreamEntry advance(unsigned Flags = 0) { + /// Advance the current bitstream, returning the next entry in the stream. + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { @@ -305,8 +284,8 @@ public: } } - /// advanceSkippingSubblocks - This is a convenience function for clients that - /// don't expect any subblocks. This just skips over them automatically. + /// This is a convenience function for clients that don't expect any + /// subblocks. This just skips over them automatically. BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { while (1) { // If we found a normal entry, return it. @@ -320,7 +299,7 @@ public: } } - /// JumpToBit - Reset the stream to the specified bit number. + /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); @@ -329,77 +308,74 @@ public: // Move the cursor to the right word. NextChar = ByteNo; BitsInCurWord = 0; - CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) { - if (sizeof(word_t) > 4) - Read64(WordBitNo); - else - Read(WordBitNo); + if (WordBitNo) + Read(WordBitNo); + } + + void fillCurWord() { + assert(Size == 0 || NextChar < (unsigned)Size); + + // Read the next word from the stream. + uint8_t Array[sizeof(word_t)] = {0}; + + uint64_t BytesRead = + BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); + + // If we run out of data, stop at the end of the stream. + if (BytesRead == 0) { + Size = NextChar; + return; } + + CurWord = + support::endian::read<word_t, support::little, support::unaligned>( + Array); + NextChar += BytesRead; + BitsInCurWord = BytesRead * 8; } + word_t Read(unsigned NumBits) { + static const unsigned BitsInWord = sizeof(word_t) * 8; - uint32_t Read(unsigned NumBits) { - assert(NumBits && NumBits <= 32 && - "Cannot return zero or more than 32 bits!"); + assert(NumBits && NumBits <= BitsInWord && + "Cannot return zero or more than BitsInWord bits!"); + + static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f; // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { - uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); - CurWord >>= NumBits; + word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits)); + + // Use a mask to avoid undefined behavior. + CurWord >>= (NumBits & Mask); + BitsInCurWord -= NumBits; return R; } - // If we run out of data, stop at the end of the stream. - if (isEndPos(NextChar)) { - CurWord = 0; - BitsInCurWord = 0; - return 0; - } - - uint32_t R = uint32_t(CurWord); - - // Read the next word from the stream. - uint8_t Array[sizeof(word_t)] = {0}; + word_t R = BitsInCurWord ? CurWord : 0; + unsigned BitsLeft = NumBits - BitsInCurWord; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); + fillCurWord(); - // Handle big-endian byte-swapping if necessary. - support::detail::packed_endian_specific_integral - <word_t, support::little, support::unaligned> EndianValue; - memcpy(&EndianValue, Array, sizeof(Array)); + // If we run out of data, stop at the end of the stream. + if (BitsLeft > BitsInCurWord) + return 0; - CurWord = EndianValue; + word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); - NextChar += sizeof(word_t); + // Use a mask to avoid undefined behavior. + CurWord >>= (BitsLeft & Mask); - // Extract NumBits-BitsInCurWord from what we just read. - unsigned BitsLeft = NumBits-BitsInCurWord; + BitsInCurWord -= BitsLeft; - // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive. - R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft))) - << BitsInCurWord); + R |= R2 << (NumBits - BitsLeft); - // BitsLeft bits have just been used up from CurWord. BitsLeft is in the - // range [1..32]/[1..64] so be careful how we shift. - if (BitsLeft != sizeof(word_t)*8) - CurWord >>= BitsLeft; - else - CurWord = 0; - BitsInCurWord = sizeof(word_t)*8-BitsLeft; return R; } - uint64_t Read64(unsigned NumBits) { - if (NumBits <= 32) return Read(NumBits); - - uint64_t V = Read(32); - return V | (uint64_t)Read(NumBits-32) << 32; - } - uint32_t ReadVBR(unsigned NumBits) { uint32_t Piece = Read(NumBits); if ((Piece & (1U << (NumBits-1))) == 0) @@ -418,8 +394,8 @@ public: } } - // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The - // chunk size of the VBR must still be <= 32 bits though. + // Read a VBR that may have a value up to 64-bits in size. The chunk size of + // the VBR must still be <= 32 bits though. uint64_t ReadVBR64(unsigned NumBits) { uint32_t Piece = Read(NumBits); if ((Piece & (1U << (NumBits-1))) == 0) @@ -450,7 +426,6 @@ private: } BitsInCurWord = 0; - CurWord = 0; } public: @@ -462,15 +437,13 @@ public: // Block header: // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] - /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for - /// the block. + /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. unsigned ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); } - /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip - /// over the body of this block. If the block record is malformed, return - /// true. + /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body + /// of this block. If the block record is malformed, return true. bool SkipBlock() { // Read and ignore the codelen value. Since we are skipping this block, we // don't care what code widths are used inside of it. @@ -488,8 +461,8 @@ public: return false; } - /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter - /// the block, and return true if the block has an error. + /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true + /// if the block has an error. bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); bool ReadBlockEnd() { @@ -508,12 +481,7 @@ private: void popBlockScope() { CurCodeSize = BlockScope.back().PrevCodeSize; - // Delete abbrevs from popped scope. - for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs); BlockScope.pop_back(); } @@ -521,23 +489,16 @@ private: // Record Processing //===--------------------------------------------------------------------===// -private: - void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op, - SmallVectorImpl<uint64_t> &Vals); - void readAbbreviatedField(const BitCodeAbbrevOp &Op, - SmallVectorImpl<uint64_t> &Vals); - void skipAbbreviatedField(const BitCodeAbbrevOp &Op); - public: - /// getAbbrev - Return the abbreviation for the specified AbbrevId. + /// Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - return CurAbbrevs[AbbrevNo]; + return CurAbbrevs[AbbrevNo].get(); } - /// skipRecord - Read the current record and discard it. + /// Read the current record and discard it. void skipRecord(unsigned AbbrevID); unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index dcfebd9cc105..9e2c2fa4a156 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -40,12 +40,12 @@ class BitstreamWriter { unsigned BlockInfoCurBID; /// CurAbbrevs - Abbrevs installed at in this block. - std::vector<BitCodeAbbrev*> CurAbbrevs; + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; struct Block { unsigned PrevCodeSize; unsigned StartSizeWord; - std::vector<BitCodeAbbrev*> PrevAbbrevs; + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; @@ -56,7 +56,7 @@ class BitstreamWriter { /// These describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector<BitCodeAbbrev*> Abbrevs; + std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; }; std::vector<BlockInfo> BlockInfoRecords; @@ -99,16 +99,6 @@ public: ~BitstreamWriter() { assert(CurBit == 0 && "Unflushed data remaining"); assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); - - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } } /// \brief Retrieve the current position in the stream, in bits. @@ -231,22 +221,13 @@ public: // If there is a blockinfo for this BlockID, add all the predefined abbrevs // to the abbrev list. if (BlockInfo *Info = getBlockInfo(BlockID)) { - for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - Info->Abbrevs[i]->addRef(); - } + CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), + Info->Abbrevs.end()); } } void ExitBlock() { assert(!BlockScope.empty() && "Block scope imbalance!"); - - // Delete all abbrevs. - for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - const Block &B = BlockScope.back(); // Block tail: @@ -263,7 +244,7 @@ public: // Restore the inner block's code size and abbrev table. CurCodeSize = B.PrevCodeSize; - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + CurAbbrevs = std::move(B.PrevAbbrevs); BlockScope.pop_back(); } @@ -317,7 +298,7 @@ private: unsigned BlobLen = (unsigned) Blob.size(); unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); EmitCode(Abbrev); diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index ee2efa2257b1..043ecd3d65d7 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -137,14 +137,14 @@ namespace bitc { enum MetadataCodes { METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. + METADATA_VALUE = 2, // VALUE: [type num, value num] + METADATA_NODE = 3, // NODE: [n x md num] METADATA_NAME = 4, // STRING: [values] - // 5 is unused. + METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num] METADATA_KIND = 6, // [n x [id, name]] - // 7 is unused. - METADATA_NODE = 8, // NODE: [n x (type num, value num)] - METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)] + METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?] + METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)] + METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)] METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] }; @@ -330,7 +330,8 @@ namespace bitc { }; enum UseListCodes { - USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD. + USELIST_CODE_DEFAULT = 1, // DEFAULT: [index..., value-id] + USELIST_CODE_BB = 2 // BB: [index..., bb-id] }; enum AttributeKindCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 8cf573544f8d..48bdabc88391 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -14,12 +14,14 @@ #ifndef LLVM_BITCODE_READERWRITER_H #define LLVM_BITCODE_READERWRITER_H +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include <memory> #include <string> namespace llvm { class BitstreamWriter; - class MemoryBuffer; class DataStreamer; class LLVMContext; class Module; @@ -27,30 +29,30 @@ namespace llvm { class raw_ostream; /// Read the header of the specified bitcode buffer and prepare for lazy - /// deserialization of function bodies. If successful, this takes ownership - /// of 'buffer. On error, this *does not* take ownership of Buffer. - ErrorOr<Module *> getLazyBitcodeModule(MemoryBuffer *Buffer, - LLVMContext &Context); - - /// getStreamedBitcodeModule - Read the header of the specified stream - /// and prepare for lazy deserialization and streaming of function bodies. - /// On error, this returns null, and fills in *ErrMsg with an error - /// description if ErrMsg is non-null. - Module *getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, - LLVMContext &Context, - std::string *ErrMsg = nullptr); + /// deserialization of function bodies. If successful, this moves Buffer. On + /// error, this *does not* move Buffer. + ErrorOr<Module *> + getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the header of the specified stream and prepare for lazy + /// deserialization and streaming of function bodies. + ErrorOr<std::unique_ptr<Module>> getStreamedBitcodeModule( + StringRef Name, DataStreamer *Streamer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the header of the specified bitcode buffer and extract just the - /// triple information. If successful, this returns a string and *does not* - /// take ownership of 'buffer'. On error, this returns "". - std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, - LLVMContext &Context); + /// triple information. If successful, this returns a string. On error, this + /// returns "". + std::string + getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the specified bitcode file, returning the module. - /// This method *never* takes ownership of Buffer. - ErrorOr<Module *> parseBitcodeFile(MemoryBuffer *Buffer, - LLVMContext &Context); + ErrorOr<Module *> + parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// WriteBitcodeToFile - Write the specified module to the specified /// raw output stream. For streams where it matters, the given stream @@ -139,6 +141,32 @@ namespace llvm { BufEnd = BufPtr+Size; return false; } + + const std::error_category &BitcodeErrorCategory(); + enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; + inline std::error_code make_error_code(BitcodeError E) { + return std::error_code(static_cast<int>(E), BitcodeErrorCategory()); + } + + class BitcodeDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + std::error_code EC; + + public: + BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, + const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + std::error_code getError() const { return EC; }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Bitcode; + } + }; + } // End llvm namespace +namespace std { +template <> struct is_error_code_enum<llvm::BitcodeError> : std::true_type {}; +} + #endif diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index ca4fd1338ed7..ff805396eb0c 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -1,18 +1,5 @@ add_subdirectory(IR) -if( MSVC_IDE OR XCODE ) - # Creates a dummy target containing all headers for the benefit of - # XCode and Visual Studio users. - file(GLOB_RECURSE headers *.h) - add_td_sources(headers) - add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL - # We need at least one source file: - ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp - ${headers}) - set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc" - EXCLUDE_FROM_DEFAULT_BUILD ON) -endif() - # If we're doing an out-of-tree build, copy a module map for generated # header files into the build area. if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index b791ba09adaf..c4b94ede4f55 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -22,7 +22,7 @@ #include "llvm/IR/Instructions.h" namespace llvm { -class GlobalVariable; +class GlobalValue; class TargetLoweringBase; class TargetLowering; class TargetMachine; @@ -31,10 +31,21 @@ class SDValue; class SelectionDAG; struct EVT; -/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence -/// of insertvalue or extractvalue indices that identify a member, return -/// the linearized index of the start of the member. +/// \brief Compute the linearized index of a member in a nested +/// aggregate/struct/array. /// +/// Given an LLVM IR aggregate type and a sequence of insertvalue or +/// extractvalue indices that identify a member, return the linearized index of +/// the start of the member, i.e the number of element in memory before the +/// seeked one. This is disconnected from the number of bytes. +/// +/// \param Ty is the type indexed by \p Indices. +/// \param Indices is an optional pointer in the indices list to the current +/// index. +/// \param IndicesEnd is the end of the indices list. +/// \param CurIndex is the current index in the recursion. +/// +/// \returns \p CurIndex plus the linear index in \p Ty the indices list. unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, @@ -59,7 +70,7 @@ void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, uint64_t StartingOffset = 0); /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. -GlobalVariable *ExtractTypeInfo(Value *V); +GlobalValue *ExtractTypeInfo(Value *V); /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being /// processed uses a memory 'm' constraint. @@ -97,6 +108,13 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const ReturnInst *Ret, const TargetLoweringBase &TLI); +// True if GV can be left out of the object symbol table. This is the case +// for linkonce_odr values whose address is not significant. While legal, it is +// not normally profitable to omit them from the .o symbol table. Using this +// analysis makes sense when the information can be passed down to the linker +// or we are in LTO. +bool canBeOmittedFromSymbolTable(const GlobalValue *GV); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e1c9a14c9009..e3ce57ad1850 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -44,6 +44,7 @@ class MachineModuleInfo; class MCAsmInfo; class MCCFIInstruction; class MCContext; +class MCExpr; class MCInst; class MCInstrInfo; class MCSection; @@ -132,6 +133,7 @@ public: virtual ~AsmPrinter(); DwarfDebug *getDwarfDebug() { return DD; } + DwarfDebug *getDwarfDebug() const { return DD; } /// Return true if assembly output should contain comments. /// @@ -203,6 +205,8 @@ public: void emitCFIInstruction(const MachineInstr &MI); + void emitFrameAlloc(const MachineInstr &MI); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); @@ -238,6 +242,9 @@ public: /// alignment (if present) and a comment describing it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Lower the specified LLVM Constant to an MCExpr. + const MCExpr *lowerConstant(const Constant *CV); + /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); @@ -264,6 +271,9 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the end of a basic block. + virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} + /// Targets should implement this to emit instructions. virtual void EmitInstruction(const MachineInstr *) { llvm_unreachable("EmitInstruction not implemented"); @@ -346,12 +356,6 @@ public: void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const; - /// Emit something like ".long Hi+Offset-Lo" where the size in bytes of the - /// directive is specified by Size and Hi/Lo specify the labels. This - /// implicitly uses .set if it is available. - void EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, - const MCSymbol *Lo, unsigned Size) const; - /// Emit something like ".long Label+Offset" where the size in bytes of the /// directive is specified by Size and Label specifies the label. This /// implicitly uses .set if it is available. @@ -402,6 +406,13 @@ public: /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } + /// Emit a dwarf register operation for describing + /// - a small value occupying only part of a register or + /// - a register representing only part of a value. + void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, + unsigned OffsetInBits = 0) const; + + /// \brief Emit a partial DWARF register operation. /// \param MLoc the register /// \param PieceSize size and @@ -418,7 +429,7 @@ public: unsigned PieceSize = 0, unsigned PieceOffset = 0) const; - /// Emit dwarf register operation. + /// EmitDwarfRegOp - Emit a dwarf register operation. /// \param Indirect whether this is a register-indirect address virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, bool Indirect) const; @@ -461,6 +472,10 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS); + /// Let the target do anything it needs to do before emitting inlineasm. + /// \p StartInfo - the subtarget info before parsing inline asm + virtual void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const; + /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the /// inlineasm contains directives to switch modes. diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 0d79b1d41bdb..91fb0a9d7e77 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -30,8 +30,10 @@ namespace llvm { /// @param UseDefFreq Expected number of executed use and def instructions /// per function call. Derived from block frequencies. /// @param Size Size of live interval as returnexd by getSize() + /// @param NumInstr Number of instructions using this live interval /// - static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) { + static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size, + unsigned NumInstr) { // The constant 25 instructions is added to avoid depending too much on // accidental SlotIndex gaps for small intervals. The effect is that small // intervals have a spill weight that is mostly proportional to the number @@ -44,7 +46,7 @@ namespace llvm { /// spill weight and allocation hint. class VirtRegAuxInfo { public: - typedef float (*NormalizingFn)(float, unsigned); + typedef float (*NormalizingFn)(float, unsigned, unsigned); private: MachineFunction &MF; diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index abe00a167fd6..dd7703b1dbf7 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -35,18 +35,18 @@ public: SExt, // The value is sign extended in the location. ZExt, // The value is zero extended in the location. AExt, // The value is extended with undefined upper bits. - BCvt, // The value is bit-converted in the location. - VExt, // The value is vector-widened in the location. - // FIXME: Not implemented yet. Code that uses AExt to mean - // vector-widen should be fixed to use VExt instead. - FPExt, // The floating-point value is fp-extended in the location. - Indirect, // The location contains pointer to the value. SExtUpper, // The value is in the upper bits of the location and should be // sign extended when retrieved. ZExtUpper, // The value is in the upper bits of the location and should be // zero extended when retrieved. - AExtUpper // The value is in the upper bits of the location and should be + AExtUpper, // The value is in the upper bits of the location and should be // extended with undefined upper bits when retrieved. + BCvt, // The value is bit-converted in the location. + VExt, // The value is vector-widened in the location. + // FIXME: Not implemented yet. Code that uses AExt to mean + // vector-widen should be fixed to use VExt instead. + FPExt, // The floating-point value is fp-extended in the location. + Indirect // The location contains pointer to the value. // TODO: a subset of the value is in the location. }; @@ -158,6 +158,16 @@ public: } }; +/// Describes a register that needs to be forwarded from the prologue to a +/// musttail call. +struct ForwardedRegister { + ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT) + : VReg(VReg), PReg(PReg), VT(VT) {} + unsigned VReg; + MCPhysReg PReg; + MVT VT; +}; + /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. It returns 'true' if it failed to handle Val. typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, @@ -184,7 +194,6 @@ private: CallingConv::ID CallingConv; bool IsVarArg; MachineFunction &MF; - const TargetMachine &TM; const TargetRegisterInfo &TRI; SmallVectorImpl<CCValAssign> &Locs; LLVMContext &Context; @@ -248,15 +257,13 @@ protected: public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs, - LLVMContext &C); + SmallVectorImpl<CCValAssign> &locs, LLVMContext &C); void addLoc(const CCValAssign &V) { Locs.push_back(V); } LLVMContext &getContext() const { return Context; } - const TargetMachine &getTarget() const { return TM; } MachineFunction &getMachineFunction() const { return MF; } CallingConv::ID getCallingConv() const { return CallingConv; } bool isVarArg() const { return IsVarArg; } @@ -348,8 +355,12 @@ public: /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive /// registers. If this is not possible, return zero. Otherwise, return the first /// register of the block that were allocated, marking the entire block as allocated. - unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) { - for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) { + unsigned AllocateRegBlock(ArrayRef<uint16_t> Regs, unsigned RegsRequired) { + if (RegsRequired > Regs.size()) + return 0; + + for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; + ++StartIdx) { bool BlockAvailable = true; // Check for already-allocated regs in this block for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { @@ -387,8 +398,8 @@ public: /// AllocateStack - Allocate a chunk of stack space with the specified size /// and alignment. unsigned AllocateStack(unsigned Size, unsigned Align) { - assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. - StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align - 1) & ~(Align - 1)); unsigned Result = StackOffset; StackOffset += Size; MF.getFrameInfo()->ensureMaxAlignment(Align); @@ -469,6 +480,19 @@ public: return PendingLocs; } + /// Compute the remaining unused register parameters that would be used for + /// the given value type. This is useful when varargs are passed in the + /// registers that normal prototyped parameters would be passed in, or for + /// implementing perfect forwarding. + void getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs, MVT VT, + CCAssignFn Fn); + + /// Compute the set of registers that need to be preserved and forwarded to + /// any musttail calls. + void analyzeMustTailForwardedRegisters( + SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes, + CCAssignFn Fn); + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 449d93418a4c..973c5954f9ad 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -54,6 +54,16 @@ RelocModel("relocation-model", "Relocatable external references, non-relocatable code"), clEnumValEnd)); +cl::opt<ThreadModel::Model> +TMModel("thread-model", + cl::desc("Choose threading model"), + cl::init(ThreadModel::POSIX), + cl::values(clEnumValN(ThreadModel::POSIX, "posix", + "POSIX thread model"), + clEnumValN(ThreadModel::Single, "single", + "Single thread model"), + clEnumValEnd)); + cl::opt<llvm::CodeModel::Model> CMModel("code-model", cl::desc("Choose code model"), @@ -83,11 +93,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), clEnumValEnd)); cl::opt<bool> -DisableRedZone("disable-red-zone", - cl::desc("Do not emit code that uses the red zone."), - cl::init(false)); - -cl::opt<bool> EnableFPMAD("enable-fp-mad", cl::desc("Enable less precise MAD instructions to be generated"), cl::init(false)); @@ -180,8 +185,8 @@ EnablePIE("enable-pie", cl::init(false)); cl::opt<bool> -UseInitArray("use-init-array", - cl::desc("Use .init_array instead of .ctors."), +UseCtors("use-ctors", + cl::desc("Use .ctors instead of .init_array."), cl::init(false)); cl::opt<std::string> StopAfter("stop-after", @@ -217,6 +222,44 @@ JTableType("jump-table-type", "Create one table per unique function type."), clEnumValEnd)); +cl::opt<bool> +FCFI("fcfi", + cl::desc("Apply forward-edge control-flow integrity"), + cl::init(false)); + +cl::opt<llvm::CFIntegrity> +CFIType("cfi-type", + cl::desc("Choose the type of Control-Flow Integrity check to add"), + cl::init(CFIntegrity::Sub), + cl::values( + clEnumValN(CFIntegrity::Sub, "sub", + "Subtract the pointer from the table base, then mask."), + clEnumValN(CFIntegrity::Ror, "ror", + "Use rotate to check the offset from a table base."), + clEnumValN(CFIntegrity::Add, "add", + "Mask out the high bits and add to an aligned base."), + clEnumValEnd)); + +cl::opt<bool> +CFIEnforcing("cfi-enforcing", + cl::desc("Enforce CFI or pass the violation to a function."), + cl::init(false)); + +// Note that this option is linked to the cfi-enforcing option above: if +// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If +// cfi-enforcing is false and no cfi-func-name is set, then a default function +// will be generated that ignores all CFI violations. The expected signature for +// functions called with CFI violations is +// +// void (i8*, i8*) +// +// The first pointer is a C string containing the name of the function in which +// the violation occurs, and the second pointer is the pointer that violated +// CFI. +cl::opt<std::string> +CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"), + cl::init("")); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -238,12 +281,18 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.StackAlignmentOverride = OverrideStackAlignment; Options.TrapFuncName = TrapFuncName; Options.PositionIndependentExecutable = EnablePIE; - Options.UseInitArray = UseInitArray; + Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; + Options.FCFI = FCFI; + Options.CFIType = CFIType; + Options.CFIEnforcing = CFIEnforcing; + Options.CFIFuncName = CFIFuncName; + + Options.ThreadModel = TMModel; return Options; } diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index 9d25fd377b7e..f9cdc2a469ff 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -91,7 +91,6 @@ public: // API call is made to prune the dependence. class VLIWPacketizerList { protected: - const TargetMachine &TM; const MachineFunction &MF; const TargetInstrInfo *TII; @@ -107,9 +106,7 @@ protected: std::map<MachineInstr*, SUnit*> MIToSUnit; public: - VLIWPacketizerList( - MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, - bool IsPostRA); + VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, bool IsPostRA); virtual ~VLIWPacketizerList(); diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h new file mode 100644 index 000000000000..e310aef3dcbb --- /dev/null +++ b/include/llvm/CodeGen/DIE.h @@ -0,0 +1,587 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Dwarf.h" +#include <vector> + +namespace llvm { +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; + + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; + + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector<DIEAbbrevData, 12> Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; + +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + // This can't be a vector<DIE> because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list<DIE> because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector<std::unique_ptr<DIE>> Children; + + DIE *Parent; + + /// Attribute values. + /// + SmallVector<DIEValue *, 12> Values; + +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + +public: + explicit DIE(dwarf::Tag Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector<std::unique_ptr<DIE>> &getChildren() const { + return Children; + } + const SmallVectorImpl<DIEValue *> &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(std::unique_ptr<DIE> Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Child->Parent = this; + Children.push_back(std::move(Child)); + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, + }; + +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + +#ifndef NDEBUG + virtual void print(raw_ostream &O) const = 0; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; + +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} + + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; + +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + StringRef Str; + +public: + DIEString(const DIEValue *Acc, StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} + + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE &Entry; + +public: + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { + } + + DIE &getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 0d1b1dc09560..1dca2ce1ab22 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -18,72 +18,52 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { -class AllocaInst; -class Constant; -class ConstantFP; -class CallInst; -class DataLayout; -class FunctionLoweringInfo; -class Instruction; -class IntrinsicInst; -class LoadInst; -class MVT; -class MachineConstantPool; -class MachineFrameInfo; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class TargetInstrInfo; -class TargetLibraryInfo; -class TargetLowering; -class TargetMachine; -class TargetRegisterClass; -class TargetRegisterInfo; -class User; -class Value; - -/// This is a fast-path instruction selection class that generates poor code and -/// doesn't support illegal types or non-trivial lowering, but runs quickly. +/// \brief This is a fast-path instruction selection class that generates poor +/// code and doesn't support illegal types or non-trivial lowering, but runs +/// quickly. class FastISel { - public: +public: struct ArgListEntry { Value *Val; Type *Ty; - bool isSExt : 1; - bool isZExt : 1; - bool isInReg : 1; - bool isSRet : 1; - bool isNest : 1; - bool isByVal : 1; - bool isInAlloca : 1; - bool isReturned : 1; + bool IsSExt : 1; + bool IsZExt : 1; + bool IsInReg : 1; + bool IsSRet : 1; + bool IsNest : 1; + bool IsByVal : 1; + bool IsInAlloca : 1; + bool IsReturned : 1; uint16_t Alignment; ArgListEntry() - : Val(nullptr), Ty(nullptr), isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), isInAlloca(false), - isReturned(false), Alignment(0) { } + : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false), + IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), + IsInAlloca(false), IsReturned(false), Alignment(0) {} + /// \brief Set CallLoweringInfo attribute flags based on a call instruction + /// and called function attributes. void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; typedef std::vector<ArgListEntry> ArgListTy; struct CallLoweringInfo { Type *RetTy; - bool RetSExt : 1; - bool RetZExt : 1; - bool IsVarArg : 1; - bool IsInReg : 1; - bool DoesNotReturn : 1; + bool RetSExt : 1; + bool RetZExt : 1; + bool IsVarArg : 1; + bool IsInReg : 1; + bool DoesNotReturn : 1; bool IsReturnValueUsed : 1; - // IsTailCall should be modified by implementations of - // FastLowerCall that perform tail call conversions. + // \brief IsTailCall Should be modified by implementations of FastLowerCall + // that perform tail call conversions. bool IsTailCall; unsigned NumFixedArgs; @@ -96,6 +76,8 @@ class FastISel { unsigned ResultReg; unsigned NumResultRegs; + bool IsPatchPoint; + SmallVector<Value *, 16> OutVals; SmallVector<ISD::ArgFlagsTy, 16> OutFlags; SmallVector<unsigned, 16> OutRegs; @@ -103,12 +85,11 @@ class FastISel { SmallVector<unsigned, 4> InRegs; CallLoweringInfo() - : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), - IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), - IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0) - {} + : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), + IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), + IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), + Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), + ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -124,8 +105,8 @@ class FastISel { RetZExt = Call.paramHasAttr(0, Attribute::ZExt); CallConv = Call.getCallingConv(); - NumFixedArgs = FuncTy->getNumParams(); Args = std::move(ArgsList); + NumFixedArgs = FuncTy->getNumParams(); CS = &Call; @@ -148,8 +129,8 @@ class FastISel { RetZExt = Call.paramHasAttr(0, Attribute::ZExt); CallConv = Call.getCallingConv(); - NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; Args = std::move(ArgsList); + NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; CS = &Call; @@ -162,8 +143,19 @@ class FastISel { RetTy = ResultTy; Callee = Target; CallConv = CC; + Args = std::move(ArgsList); NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; + return *this; + } + + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, + const char *Target, ArgListTy &&ArgsList, + unsigned FixedArgs = ~0U) { + RetTy = ResultTy; + SymName = Target; + CallConv = CC; Args = std::move(ArgsList); + NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; return *this; } @@ -172,10 +164,13 @@ class FastISel { return *this; } - ArgListTy &getArgs() { - return Args; + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; } + ArgListTy &getArgs() { return Args; } + void clearOuts() { OutVals.clear(); OutFlags.clear(); @@ -202,61 +197,64 @@ protected: const TargetLowering &TLI; const TargetRegisterInfo &TRI; const TargetLibraryInfo *LibInfo; + bool SkipTargetIndependentISel; - /// The position of the last instruction for materializing constants for use - /// in the current block. It resets to EmitStartPt when it makes sense (for - /// example, it's usually profitable to avoid function calls between the + /// \brief The position of the last instruction for materializing constants + /// for use in the current block. It resets to EmitStartPt when it makes sense + /// (for example, it's usually profitable to avoid function calls between the /// definition and the use) MachineInstr *LastLocalValue; - /// The top most instruction in the current block that is allowed for emitting - /// local variables. LastLocalValue resets to EmitStartPt when it makes sense - /// (for example, on function calls) + /// \brief The top most instruction in the current block that is allowed for + /// emitting local variables. LastLocalValue resets to EmitStartPt when it + /// makes sense (for example, on function calls) MachineInstr *EmitStartPt; public: - /// Return the position of the last instruction emitted for materializing - /// constants for use in the current block. + /// \brief Return the position of the last instruction emitted for + /// materializing constants for use in the current block. MachineInstr *getLastLocalValue() { return LastLocalValue; } - /// Update the position of the last instruction emitted for materializing - /// constants for use in the current block. + /// \brief Update the position of the last instruction emitted for + /// materializing constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// Set the current block to which generated machine instructions will be - /// appended, and clear the local CSE map. + /// \brief Set the current block to which generated machine instructions will + /// be appended, and clear the local CSE map. void startNewBlock(); - /// Return current debug location information. + /// \brief Return current debug location information. DebugLoc getCurDebugLoc() const { return DbgLoc; } - - /// Do "fast" instruction selection for function arguments and append machine - /// instructions to the current block. Return true if it is successful. - bool LowerArguments(); - /// Do "fast" instruction selection for the given LLVM IR instruction, and - /// append generated machine instructions to the current block. Return true if - /// selection was successful. - bool SelectInstruction(const Instruction *I); + /// \brief Do "fast" instruction selection for function arguments and append + /// the machine instructions to the current block. Returns true when + /// successful. + bool lowerArguments(); - /// Do "fast" instruction selection for the given LLVM IR operator + /// \brief Do "fast" instruction selection for the given LLVM IR instruction + /// and append the generated machine instructions to the current block. + /// Returns true if selection was successful. + bool selectInstruction(const Instruction *I); + + /// \brief Do "fast" instruction selection for the given LLVM IR operator /// (Instruction or ConstantExpr), and append generated machine instructions /// to the current block. Return true if selection was successful. - bool SelectOperator(const User *I, unsigned Opcode); + bool selectOperator(const User *I, unsigned Opcode); - /// Create a virtual register and arrange for it to be assigned the value for - /// the given LLVM value. + /// \brief Create a virtual register and arrange for it to be assigned the + /// value for the given LLVM value. unsigned getRegForValue(const Value *V); - /// Look up the value to see if its value is already cached in a register. It - /// may be defined by instructions across blocks or defined locally. + /// \brief Look up the value to see if its value is already cached in a + /// register. It may be defined by instructions across blocks or defined + /// locally. unsigned lookUpRegForValue(const Value *V); - /// This is a wrapper around getRegForValue that also takes care of truncating - /// or sign-extending the given getelementptr index value. + /// \brief This is a wrapper around getRegForValue that also takes care of + /// truncating or sign-extending the given getelementptr index value. std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note @@ -284,11 +282,11 @@ public: return false; } - /// Reset InsertPt to prepare for inserting instructions into the current - /// block. + /// \brief Reset InsertPt to prepare for inserting instructions into the + /// current block. void recomputeInsertPt(); - /// Remove all dead instructions between the I and E. + /// \brief Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -297,221 +295,195 @@ public: DebugLoc DL; }; - /// Prepare InsertPt to begin inserting instructions into the local value area - /// and return the old insert position. + /// \brief Prepare InsertPt to begin inserting instructions into the local + /// value area and return the old insert position. SavePoint enterLocalValueArea(); - /// Reset InsertPt to the given old insert position. + /// \brief Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); virtual ~FastISel(); protected: - explicit FastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo); - - /// This method is called by target-independent code when the normal FastISel - /// process fails to select an instruction. This gives targets a chance to - /// emit code for anything that doesn't fit into FastISel's framework. It - /// returns true if it was successful. - virtual bool TargetSelectInstruction(const Instruction *I) = 0; - - /// This method is called by target-independent code to do target specific - /// argument lowering. It returns true if it was successful. - virtual bool FastLowerArguments(); - - /// \brief This method is called by target-independent code to do target + explicit FastISel(FunctionLoweringInfo &FuncInfo, + const TargetLibraryInfo *LibInfo, + bool SkipTargetIndependentISel = false); + + /// \brief This method is called by target-independent code when the normal + /// FastISel process fails to select an instruction. This gives targets a + /// chance to emit code for anything that doesn't fit into FastISel's + /// framework. It returns true if it was successful. + virtual bool fastSelectInstruction(const Instruction *I) = 0; + + /// \brief This method is called by target-independent code to do target- + /// specific argument lowering. It returns true if it was successful. + virtual bool fastLowerArguments(); + + /// \brief This method is called by target-independent code to do target- /// specific call lowering. It returns true if it was successful. - virtual bool FastLowerCall(CallLoweringInfo &CLI); + virtual bool fastLowerCall(CallLoweringInfo &CLI); - /// \brief This method is called by target-independent code to do target + /// \brief This method is called by target-independent code to do target- /// specific intrinsic lowering. It returns true if it was successful. - virtual bool FastLowerIntrinsicCall(const IntrinsicInst *II); + virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type and opcode be emitted. - virtual unsigned FastEmit_(MVT VT, - MVT RetVT, - unsigned Opcode); + virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operand be emitted. - virtual unsigned FastEmit_r(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill); + virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operands be emitted. - virtual unsigned FastEmit_rr(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill); + virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and immediate - /// operands be emitted. - virtual unsigned FastEmit_ri(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - uint64_t Imm); + // operands be emitted. + virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, uint64_t Imm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and floating-point /// immediate operands be emitted. - virtual unsigned FastEmit_rf(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm); + virtual unsigned fastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, const ConstantFP *FPImm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and immediate /// operands be emitted. - virtual unsigned FastEmit_rri(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, - uint64_t Imm); - - /// \brief This method is a wrapper of FastEmit_ri. - /// + virtual unsigned fastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode, + unsigned Op0, bool Op0IsKill, unsigned Op1, + bool Op1IsKill, uint64_t Imm); + + /// \brief This method is a wrapper of fastEmit_ri. + /// /// It first tries to emit an instruction with an immediate operand using - /// FastEmit_ri. If that fails, it materializes the immediate into a register - /// and try FastEmit_rr instead. - unsigned FastEmit_ri_(MVT VT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, + /// fastEmit_ri. If that fails, it materializes the immediate into a register + /// and try fastEmit_rr instead. + unsigned fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and immediate operand be emitted. - virtual unsigned FastEmit_i(MVT VT, - MVT RetVT, - unsigned Opcode, - uint64_t Imm); + virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and floating-point immediate /// operand be emitted. - virtual unsigned FastEmit_f(MVT VT, - MVT RetVT, - unsigned Opcode, + virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, const ConstantFP *FPImm); - /// Emit a MachineInstr with no operands and a result register in the given - /// register class. - unsigned FastEmitInst_(unsigned MachineInstOpcode, + /// \brief Emit a MachineInstr with no operands and a result register in the + /// given register class. + unsigned fastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass *RC); - /// Emit a MachineInstr with one register operand and a result register in the - /// given register class. - unsigned FastEmitInst_r(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill); - - /// Emit a MachineInstr with two register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill); - - /// Emit a MachineInstr with three register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, - unsigned Op2, bool Op2IsKill); - - /// Emit a MachineInstr with a register operand, an immediate, and a result + /// \brief Emit a MachineInstr with one register operand and a result register + /// in the given register class. + unsigned fastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill); + + /// \brief Emit a MachineInstr with two register operands and a result + /// register in the given register class. + unsigned fastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill); + + /// \brief Emit a MachineInstr with three register operands and a result /// register in the given register class. - unsigned FastEmitInst_ri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - uint64_t Imm); - - /// Emit a MachineInstr with one register operand and two immediate operands. - unsigned FastEmitInst_rii(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - uint64_t Imm1, uint64_t Imm2); - - /// Emit a MachineInstr with two register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rf(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm); - - /// Emit a MachineInstr with two register operands, an immediate, and a result + unsigned fastEmitInst_rrr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, + unsigned Op2, bool Op2IsKill); + + /// \brief Emit a MachineInstr with a register operand, an immediate, and a + /// result register in the given register class. + unsigned fastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, uint64_t Imm); + + /// \brief Emit a MachineInstr with one register operand and two immediate + /// operands. + unsigned fastEmitInst_rii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); + + /// \brief Emit a MachineInstr with two register operands and a result /// register in the given register class. - unsigned FastEmitInst_rri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, + unsigned fastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, const ConstantFP *FPImm); + + /// \brief Emit a MachineInstr with two register operands, an immediate, and a + /// result register in the given register class. + unsigned fastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// Emit a MachineInstr with two register operands, two immediates operands, - /// and a result register in the given register class. - unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, + /// \brief Emit a MachineInstr with two register operands, two immediates + /// operands, and a result register in the given register class. + unsigned fastEmitInst_rrii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm1, uint64_t Imm2); - /// Emit a MachineInstr with a single immediate operand, and a result register - /// in the given register class. - unsigned FastEmitInst_i(unsigned MachineInstrOpcode, - const TargetRegisterClass *RC, - uint64_t Imm); - - /// Emit a MachineInstr with a two immediate operands. - unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, - const TargetRegisterClass *RC, - uint64_t Imm1, uint64_t Imm2); - - /// Emit a MachineInstr for an extract_subreg from a specified index of a - /// superregister to a specified type. - unsigned FastEmitInst_extractsubreg(MVT RetVT, - unsigned Op0, bool Op0IsKill, + /// \brief Emit a MachineInstr with a single immediate operand, and a result + /// register in the given register class. + unsigned fastEmitInst_i(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, uint64_t Imm); + + /// \brief Emit a MachineInstr with a two immediate operands. + unsigned fastEmitInst_ii(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, uint64_t Imm1, + uint64_t Imm2); + + /// \brief Emit a MachineInstr for an extract_subreg from a specified index of + /// a superregister to a specified type. + unsigned fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); - /// Emit MachineInstrs to compute the value of Op with all but the least - /// significant bit set to zero. - unsigned FastEmitZExtFromI1(MVT VT, - unsigned Op0, bool Op0IsKill); + /// \brief Emit MachineInstrs to compute the value of Op with all but the + /// least significant bit set to zero. + unsigned fastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill); - /// Emit an unconditional branch to the given block, unless it is the + /// \brief Emit an unconditional branch to the given block, unless it is the /// immediate (fall-through) successor, and update the CFG. - void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); + void fastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); - void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1); + /// \brief Update the value map to include the new mapping for this + /// instruction, or insert an extra copy to get the result in a previous + /// determined register. + /// + /// NOTE: This is only necessary because we might select a block that uses a + /// value before we select the block that defines the value. It might be + /// possible to fix this by selecting blocks in reverse postorder. + void updateValueMap(const Value *I, unsigned Reg, unsigned NumRegs = 1); unsigned createResultReg(const TargetRegisterClass *RC); - /// Try to constrain Op so that it is usable by argument OpNum of the provided - /// MCInstrDesc. If this fails, create a new virtual register in the correct - /// class and COPY the value there. + /// \brief Try to constrain Op so that it is usable by argument OpNum of the + /// provided MCInstrDesc. If this fails, create a new virtual register in the + /// correct class and COPY the value there. unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, unsigned OpNum); - /// Emit a constant in a register using target-specific logic, such as + /// \brief Emit a constant in a register using target-specific logic, such as /// constant pool loads. - virtual unsigned TargetMaterializeConstant(const Constant* C) { - return 0; - } + virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; } - /// Emit an alloca address in a register using target-specific logic. - virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { - return 0; - } + /// \brief Emit an alloca address in a register using target-specific logic. + virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; } - virtual unsigned TargetMaterializeFloatZero(const ConstantFP* CF) { + /// \brief Emit the floating-point constant +0.0 in a register using target- + /// specific logic. + virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) { return 0; } @@ -524,36 +496,46 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// Test whether the given value has exactly one use. - bool hasTrivialKill(const Value *V) const; + /// \brief Test whether the given value has exactly one use. + bool hasTrivialKill(const Value *V); /// \brief Create a machine mem operand from the given instruction. MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; - bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); - bool LowerCallTo(CallLoweringInfo &CLI); - -private: - bool SelectBinaryOp(const User *I, unsigned ISDOpcode); - - bool SelectFNeg(const User *I); - - bool SelectGetElementPtr(const User *I); + CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const; - bool SelectStackmap(const CallInst *I); - bool SelectPatchpoint(const CallInst *I); - bool LowerCall(const CallInst *I); - bool SelectCall(const User *Call); - bool SelectIntrinsicCall(const IntrinsicInst *II); + bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); + bool lowerCallTo(CallLoweringInfo &CLI); - bool SelectBitCast(const User *I); - - bool SelectCast(const User *I, unsigned Opcode); + bool isCommutativeIntrinsic(IntrinsicInst const *II) { + switch (II->getIntrinsicID()) { + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: + return true; + default: + return false; + } + } - bool SelectExtractValue(const User *I); - bool SelectInsertValue(const User *I); + bool lowerCall(const CallInst *I); + /// \brief Select and emit code for a binary operator instruction, which has + /// an opcode which directly corresponds to the given ISD opcode. + bool selectBinaryOp(const User *I, unsigned ISDOpcode); + bool selectFNeg(const User *I); + bool selectGetElementPtr(const User *I); + bool selectStackmap(const CallInst *I); + bool selectPatchpoint(const CallInst *I); + bool selectCall(const User *Call); + bool selectIntrinsicCall(const IntrinsicInst *II); + bool selectBitCast(const User *I); + bool selectCast(const User *I, unsigned Opcode); + bool selectExtractValue(const User *I); + bool selectInsertValue(const User *I); +private: /// \brief Handle PHI nodes in successor blocks. /// /// Emit code to ensure constants are copied into registers when needed. @@ -561,18 +543,27 @@ private: /// nodes as input. We cannot just directly add them, because expansion might /// result in multiple MBB's for one BB. As such, the start of the BB might /// correspond to a different MBB than the end. - bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + + /// \brief Helper for materializeRegForValue to materialize a constant in a + /// target-independent way. + unsigned materializeConstant(const Value *V, MVT VT); - /// Helper for getRegForVale. This function is called when the value isn't - /// already available in a register and must be materialized with new + /// \brief Helper for getRegForVale. This function is called when the value + /// isn't already available in a register and must be materialized with new /// instructions. unsigned materializeRegForValue(const Value *V, MVT VT); - /// Clears LocalValueMap and moves the area for the new local variables to the - /// beginning of the block. It helps to avoid spilling cached variables across - /// heavy instructions like calls. + /// \brief Clears LocalValueMap and moves the area for the new local variables + /// to the beginning of the block. It helps to avoid spilling cached variables + /// across heavy instructions like calls. void flushLocalValueMap(); + /// \brief Insertion point before trying to select the current instruction. + MachineBasicBlock::iterator SavedInsertPt; + + /// \brief Add a stackmap or patchpoint intrinsic call's live variable + /// operands to a stackmap or patchpoint machine instruction. bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops, const CallInst *CI, unsigned StartIdx); bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs, @@ -580,6 +571,6 @@ private: CallLoweringInfo &CLI); }; -} +} // end namespace llvm #endif diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h new file mode 100644 index 000000000000..ec8e2ef243b7 --- /dev/null +++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h @@ -0,0 +1,122 @@ +//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments indirect calls with checks to ensure that these calls +// pass through the appropriate jump-instruction table generated by +// JumpInstrTables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H +#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetOptions.h" +#include <string> + +namespace llvm { + +class AnalysisUsage; +class BasicBlock; +class Constant; +class Function; +class Instruction; +class Module; +class Value; + +/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to +/// prepend checks to indirect calls to make sure that these calls target valid +/// locations. +class ForwardControlFlowIntegrity : public ModulePass { +public: + static char ID; + + ForwardControlFlowIntegrity(); + ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT, + CFIntegrity CFIType, + bool CFIEnforcing, std::string CFIFuncName); + ~ForwardControlFlowIntegrity() override; + + /// Runs the CFI pass on a given module. This works best if the module in + /// question is the result of link-time optimization (see lib/LTO). + bool runOnModule(Module &M) override; + const char *getPassName() const override { + return "Forward Control-Flow Integrity"; + } + void getAnalysisUsage(AnalysisUsage &AU) const override; + +private: + typedef SmallVector<Instruction *, 64> CallSet; + + /// A structure that is used to keep track of constant table information. + struct CFIConstants { + Constant *StartValue; + Constant *MaskValue; + Constant *Size; + }; + + /// A map from function type to the base of the table for this type and a mask + /// for the table + typedef DenseMap<FunctionType *, CFIConstants> CFITables; + + CallSet IndirectCalls; + + /// The type of jumptable implementation. + JumpTable::JumpTableType JTType; + + /// The type of CFI check to add before each indirect call. + CFIntegrity CFIType; + + /// A value that controls whether or not CFI violations cause a halt. + bool CFIEnforcing; + + /// The name of the function to call in case of a CFI violation when + /// CFIEnforcing is false. There is a default function that ignores + /// violations. + std::string CFIFuncName; + + /// The alignment of each entry in the table, from JumpInstrTableInfo. The + /// JumpInstrTableInfo class always makes this a power of two. + uint64_t ByteAlignment; + + /// The base-2 logarithm of ByteAlignment, needed for some of the transforms + /// (like CFIntegrity::Ror) + unsigned LogByteAlignment; + + /// Adds checks to each indirect call site to make sure that it is calling a + /// function in our jump table. + void updateIndirectCalls(Module &M, CFITables &CFIT); + + /// Walks the instructions to find all the indirect calls. + void getIndirectCalls(Module &M); + + /// Adds a function that handles violations in non-enforcing mode + /// (!CFIEnforcing). The default warning function simply returns, since the + /// exact details of how to handle CFI violations depend on the application. + void addWarningFunction(Module &M); + + /// Rewrites a function pointer in a call/invoke instruction to force it into + /// a table. + void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr, + Constant *JumpTableStart, Constant *JumpTableMask, + Constant *JumpTableSize); + + /// Inserts a check and a call to a warning function at a given instruction + /// that must be an indirect call. + void insertWarning(Module &M, BasicBlock *Block, Instruction *I, + Value *FunPtr); +}; + +ModulePass * +createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT, + CFIntegrity CFIType, + bool CFIEnforcing, StringRef CFIFuncName); +} + +#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 9636b51e303d..7c574df4ba41 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -20,6 +20,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" @@ -50,10 +51,10 @@ class Value; /// function that is used when lowering a region of the function. /// class FunctionLoweringInfo { - const TargetMachine &TM; public: const Function *Fn; MachineFunction *MF; + const TargetLowering *TLI; MachineRegisterInfo *RegInfo; BranchProbabilityInfo *BPI; /// CanLowerReturn - true iff the function's return value can be lowered to @@ -87,6 +88,12 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap<unsigned, unsigned> RegFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) + /// used to spill values at a statepoint. We store them here to enable + /// reuse of the same stack slots across different statepoints in different + /// basic blocks. + SmallVector<unsigned, 50> StatepointStackSlots; + /// MBB - The current block. MachineBasicBlock *MBB; @@ -106,6 +113,10 @@ public: KnownZero(1, 0) {} }; + /// Record the preferred extend type (ISD::SIGN_EXTEND or ISD::ZERO_EXTEND) + /// for a value. + DenseMap<const Value *, ISD::NodeType> PreferredExtendType; + /// VisitedBBs - The set of basic blocks visited thus far by instruction /// selection. SmallPtrSet<const BasicBlock*, 4> VisitedBBs; @@ -115,14 +126,13 @@ public: /// TODO: This isn't per-function state, it's per-basic-block state. But /// there's no other convenient place for it to live right now. std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate; + unsigned OrigNumPHINodesToUpdate; /// If the current MBB is a landing pad, the exception pointer and exception /// selector registers are copied into these virtual registers by /// SelectionDAGISel::PrepareEHLandingPad(). unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; - explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {} - /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. /// @@ -196,6 +206,9 @@ public: return; unsigned Reg = It->second; + if (Reg == 0) + return; + LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index ddcc823ecd9e..c7f1ab87fcb1 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -37,7 +37,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" - #include <memory> namespace llvm { @@ -80,8 +79,8 @@ namespace llvm { }; - /// GCFunctionInfo - Garbage collection metadata for a single function. - /// + /// Garbage collection metadata for a single function. Currently, this + /// information only applies to GCStrategies which use GCRoot. class GCFunctionInfo { public: typedef std::vector<GCPoint>::iterator iterator; @@ -160,21 +159,37 @@ namespace llvm { size_t live_size(const iterator &p) const { return roots_size(); } }; - - /// GCModuleInfo - Garbage collection metadata for a whole module. - /// + /// An analysis pass which caches information about the entire Module. + /// Records both the function level information used by GCRoots and a + /// cache of the 'active' gc strategy objects for the current Module. class GCModuleInfo : public ImmutablePass { typedef StringMap<GCStrategy*> strategy_map_type; typedef std::vector<std::unique_ptr<GCStrategy>> list_type; - typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type; strategy_map_type StrategyMap; list_type StrategyList; - finfo_map_type FInfoMap; GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); public: + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + + + private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type; + finfo_map_type FInfoMap; + public: + typedef list_type::const_iterator iterator; static char ID; @@ -191,8 +206,9 @@ namespace llvm { iterator begin() const { return StrategyList.begin(); } iterator end() const { return StrategyList.end(); } - /// get - Look up function metadata. - /// + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. GCFunctionInfo &getFunctionInfo(const Function &F); }; diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 4a6b5ac19c36..25fafba93f8b 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -32,16 +32,11 @@ namespace llvm { /// defaults from Registry. typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry; - /// GCMetadataPrinter - Emits GC metadata as assembly code. - /// + /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are + /// created, managed, and owned by the AsmPrinter. class GCMetadataPrinter { - public: - typedef GCStrategy::list_type list_type; - typedef GCStrategy::iterator iterator; - private: GCStrategy *S; - friend class AsmPrinter; protected: @@ -55,16 +50,15 @@ namespace llvm { public: GCStrategy &getStrategy() { return *S; } - const Module &getModule() const { return S->getModule(); } - - /// begin/end - Iterate over the collected function metadata. - iterator begin() { return S->begin(); } - iterator end() { return S->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(AsmPrinter &AP); - virtual void finishAssembly(AsmPrinter &AP); + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, + AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, + AsmPrinter &AP) {} virtual ~GCMetadataPrinter(); }; diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 81e1f85286e1..0b0c3124c537 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -12,9 +12,14 @@ // specified in a function's 'gc' attribute. Algorithms are enabled by setting // flags in a subclass's constructor, and some virtual methods can be // overridden. +// +// GCStrategy is relevant for implementations using either gc.root or +// gc.statepoint based lowering strategies, but is currently focused mostly on +// options for gc.root. This will change over time. // -// When requested, the GCStrategy will be populated with data about each -// function which uses it. Specifically: +// When requested by a subclass of GCStrategy, the gc.root implementation will +// populate GCModuleInfo and GCFunctionInfo with that about each Function in +// the Module that opts in to garbage collection. Specifically: // // - Safe points // Garbage collection is generally only possible at certain points in code. @@ -31,40 +36,42 @@ // This information can used to emit the metadata tables which are required by // the target garbage collector runtime. // +// When used with gc.statepoint, information about safepoint and roots can be +// found in the binary StackMap section after code generation. Safepoint +// placement is currently the responsibility of the frontend, though late +// insertion support is planned. gc.statepoint does not currently support +// custom stack map formats; such can be generated by parsing the standard +// stack map section if desired. +// +// The read and write barrier support can be used with either implementation. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_GCSTRATEGY_H #define LLVM_CODEGEN_GCSTRATEGY_H +#include "llvm/ADT/Optional.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Support/Registry.h" #include <string> namespace llvm { - - class GCStrategy; - - /// The GC strategy registry uses all the defaults from Registry. - /// - typedef Registry<GCStrategy> GCRegistry; - /// GCStrategy describes a garbage collector algorithm's code generation /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. + /// be abstractly described. GCStrategy objects currently must be looked up + /// through the GCModuleInfo analysis pass. They are owned by the analysis + /// pass and recreated every time that pass is invalidated. class GCStrategy { - public: - typedef std::vector<std::unique_ptr<GCFunctionInfo>> list_type; - typedef list_type::iterator iterator; - private: - friend class GCModuleInfo; - const Module *M; std::string Name; - - list_type Functions; + friend class GCModuleInfo; protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + unsigned NeededSafePoints; ///< Bitmask of required safe points. bool CustomReadBarriers; ///< Default is to insert loads. bool CustomWriteBarriers; ///< Default is to insert stores. @@ -76,78 +83,114 @@ namespace llvm { public: GCStrategy(); - virtual ~GCStrategy() {} - - /// getName - The name of the GC strategy, for debugging. - /// + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. const std::string &getName() const { return Name; } - /// getModule - The module within which the GC strategy is operating. - /// - const Module &getModule() const { return *M; } + /// By default, write barriers are replaced with simple store + /// instructions. If true, then performCustomLowering must instead lower + /// them. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, then performCustomLowering must instead lower + /// them. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ - /// needsSafePoitns - True if safe points of any kind are required. By - // default, none are recorded. + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional<bool> isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. bool needsSafePoints() const { return CustomSafePoints || NeededSafePoints != 0; } - /// needsSafePoint(Kind) - True if the given kind of safe point is - // required. By default, none are recorded. + /// True if the given kind of safe point is required. By default, none are + /// recorded. bool needsSafePoint(GC::PointKind Kind) const { return (NeededSafePoints & 1 << Kind) != 0; } - - /// customWriteBarrier - By default, write barriers are replaced with simple - /// store instructions. If true, then - /// performCustomLowering must instead lower them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// customReadBarrier - By default, read barriers are replaced with simple - /// load instructions. If true, then - /// performCustomLowering must instead lower them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// customRoots - By default, roots are left for the code generator so it - /// can generate a stack map. If true, then - // performCustomLowering must delete them. + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, then performCustomLowering must delete them. bool customRoots() const { return CustomRoots; } - /// customSafePoints - By default, the GC analysis will find safe - /// points according to NeededSafePoints. If true, - /// then findCustomSafePoints must create them. + /// By default, the GC analysis will find safe points according to + /// NeededSafePoints. If true, then findCustomSafePoints must create them. bool customSafePoints() const { return CustomSafePoints; } - /// initializeRoots - If set, gcroot intrinsics should initialize their - // allocas to null before the first use. This is - // necessary for most GCs and is enabled by default. + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. bool initializeRoots() const { return InitRoots; } - /// usesMetadata - If set, appropriate metadata tables must be emitted by - /// the back-end (assembler, JIT, or otherwise). + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. bool usesMetadata() const { return UsesMetadata; } - - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insertFunctionMetadata - Creates metadata for a function. - /// - GCFunctionInfo *insertFunctionInfo(const Function &F); + ///@} + /// initializeCustomLowering/performCustomLowering - If any of the actions /// are set to custom, performCustomLowering must be overriden to transform /// the corresponding actions to LLVM IR. initializeCustomLowering is /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. - virtual bool initializeCustomLowering(Module &F); - virtual bool performCustomLowering(Function &F); - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF); + /// which the LLVM IR can be modified. These methods apply mostly to + /// gc.root based implementations, but can be overriden to provide custom + /// barrier lowerings with gc.statepoint as well. + ///@{ + virtual bool initializeCustomLowering(Module &F) { + // No changes made + return false; + } + virtual bool performCustomLowering(Function &F) { + llvm_unreachable("GCStrategy subclass specified a configuration which" + "requires a custom lowering without providing one"); + } + ///@} + /// Called if customSafepoints returns true, used only by gc.root + /// implementations. + virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF) { + llvm_unreachable("GCStrategy subclass specified a configuration which" + "requests custom safepoint identification without" + "providing an implementation for such"); + } }; - + + /// Subclasses of GCStrategy are made available for use during compilation by + /// adding them to the global GCRegistry. This can done either within the + /// LLVM source tree or via a loadable plugin. An example registeration + /// would be: + /// static GCRegistry::Add<CustomGC> X("custom-name", + /// "my custom supper fancy gc strategy"); + /// + /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also + /// register your GCMetadataPrinter subclass with the + /// GCMetadataPrinterRegistery as well. + typedef Registry<GCStrategy> GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index bb170c85cbf8..51a31842a5c0 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -36,6 +36,8 @@ namespace llvm { /// Creates a shadow stack garbage collector. This collector requires no code /// generator support. void linkShadowStackGC(); + + void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 84447616c989..952362ed6ce3 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover + /// intrinsic. Materializes the offset from the frame pointer of another + /// function to the result of llvm.frameallocate. + FRAME_ALLOC_RECOVER, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. READ_REGISTER, @@ -485,7 +490,8 @@ namespace ISD { FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, - + FMINNUM, FMAXNUM, + /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -674,6 +680,9 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + // Masked load and store + MLOAD, MSTORE, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, @@ -744,7 +753,7 @@ namespace ISD { LAST_LOADEXT_TYPE }; - NodeType getExtForLoadExtType(LoadExtType); + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h deleted file mode 100644 index dc2a0272db4e..000000000000 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ /dev/null @@ -1,344 +0,0 @@ -//===-- llvm/CodeGen/JITCodeEmitter.h - Code emission ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an abstract interface that is used by the machine code -// emission framework to output the code. This allows machine code emission to -// be separated from concerns such as resolution of call targets, and where the -// machine code will be written (memory or disk, f.e.). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_JITCODEEMITTER_H -#define LLVM_CODEGEN_JITCODEEMITTER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/MathExtras.h" -#include <string> - -namespace llvm { - -class MachineBasicBlock; -class MachineConstantPool; -class MachineJumpTableInfo; -class MachineFunction; -class MachineModuleInfo; -class MachineRelocation; -class Value; -class GlobalValue; -class Function; - -/// JITCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxiliary -/// structures, such as jump tables, relocations, etc. -/// -/// Emission of machine code is complicated by the fact that we don't (in -/// general) know the size of the machine code that we're about to emit before -/// we emit it. As such, we preallocate a certain amount of memory, and set the -/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we -/// emit machine instructions, we advance the CurBufferPtr to indicate the -/// location of the next byte to emit. In the case of a buffer overflow (we -/// need to emit more machine code than we have allocated space for), the -/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire -/// function has been emitted, the overflow condition is checked, and if it has -/// occurred, more memory is allocated, and we reemit the code into it. -/// -class JITCodeEmitter : public MachineCodeEmitter { - void anchor() override; -public: - virtual ~JITCodeEmitter() {} - - /// startFunction - This callback is invoked when the specified function is - /// about to be code generated. This initializes the BufferBegin/End/Ptr - /// fields. - /// - void startFunction(MachineFunction &F) override = 0; - - /// finishFunction - This callback is invoked when the specified function has - /// finished code generation. If a buffer overflow has occurred, this method - /// returns true (the callee is required to try again), otherwise it returns - /// false. - /// - bool finishFunction(MachineFunction &F) override = 0; - - /// allocIndirectGV - Allocates and fills storage for an indirect - /// GlobalValue, and returns the address. - virtual void *allocIndirectGV(const GlobalValue *GV, - const uint8_t *Buffer, size_t Size, - unsigned Alignment) = 0; - - /// emitByte - This callback is invoked when a byte needs to be written to the - /// output stream. - /// - void emitByte(uint8_t B) { - if (CurBufferPtr != BufferEnd) - *CurBufferPtr++ = B; - } - - /// emitWordLE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitWordLE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitWordBE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitWordBE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordLE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitDWordLE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordBE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitDWordBE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitAlignment - Move the CurBufferPtr pointer up to the specified - /// alignment (saturated to BufferEnd of course). - void emitAlignment(unsigned Alignment) { - if (Alignment == 0) Alignment = 1; - uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, - Alignment); - CurBufferPtr = std::min(NewPtr, BufferEnd); - } - - /// emitAlignmentWithFill - Similar to emitAlignment, except that the - /// extra bytes are filled with the provided byte. - void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) { - if (Alignment == 0) Alignment = 1; - uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, - Alignment); - // Fail if we don't have room. - if (NewPtr > BufferEnd) { - CurBufferPtr = BufferEnd; - return; - } - while (CurBufferPtr < NewPtr) { - *CurBufferPtr++ = Fill; - } - } - - /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be - /// written to the output stream. - void emitULEB128Bytes(uint64_t Value, unsigned PadTo = 0) { - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - if (Value || PadTo != 0) Byte |= 0x80; - emitByte(Byte); - } while (Value); - - if (PadTo) { - do { - uint8_t Byte = (PadTo > 1) ? 0x80 : 0x0; - emitByte(Byte); - } while (--PadTo); - } - } - - /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be - /// written to the output stream. - void emitSLEB128Bytes(int64_t Value) { - int32_t Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - emitByte(Byte); - } while (IsMore); - } - - /// emitString - This callback is invoked when a String needs to be - /// written to the output stream. - void emitString(const std::string &String) { - for (size_t i = 0, N = String.size(); i < N; ++i) { - uint8_t C = String[i]; - emitByte(C); - } - emitByte(0); - } - - /// emitInt32 - Emit a int32 directive. - void emitInt32(uint32_t Value) { - if (4 <= BufferEnd-CurBufferPtr) { - *((uint32_t*)CurBufferPtr) = Value; - CurBufferPtr += 4; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt64 - Emit a int64 directive. - void emitInt64(uint64_t Value) { - if (8 <= BufferEnd-CurBufferPtr) { - *((uint64_t*)CurBufferPtr) = Value; - CurBufferPtr += 8; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt32At - Emit the Int32 Value in Addr. - void emitInt32At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint32_t*)Addr) = (uint32_t)Value; - } - - /// emitInt64At - Emit the Int64 Value in Addr. - void emitInt64At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint64_t*)Addr) = (uint64_t)Value; - } - - - /// emitLabel - Emits a label - void emitLabel(MCSymbol *Label) override = 0; - - /// allocateSpace - Allocate a block of space in the current output buffer, - /// returning null (and setting conditions to indicate buffer overflow) on - /// failure. Alignment is the alignment in bytes of the buffer desired. - void *allocateSpace(uintptr_t Size, unsigned Alignment) override { - emitAlignment(Alignment); - void *Result; - - // Check for buffer overflow. - if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { - CurBufferPtr = BufferEnd; - Result = nullptr; - } else { - // Allocate the space. - Result = CurBufferPtr; - CurBufferPtr += Size; - } - - return Result; - } - - /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, - /// this method does not allocate memory in the current output buffer, - /// because a global may live longer than the current function. - virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; - - /// StartMachineBasicBlock - This should be called by the target when a new - /// basic block is about to be emitted. This way the MCE knows where the - /// start of the block is, and can implement getMachineBasicBlockAddress. - void StartMachineBasicBlock(MachineBasicBlock *MBB) override = 0; - - /// getCurrentPCValue - This returns the address that the next emitted byte - /// will be output to. - /// - uintptr_t getCurrentPCValue() const override { - return (uintptr_t)CurBufferPtr; - } - - /// getCurrentPCOffset - Return the offset from the start of the emitted - /// buffer that we are currently writing to. - uintptr_t getCurrentPCOffset() const override { - return CurBufferPtr-BufferBegin; - } - - /// earlyResolveAddresses - True if the code emitter can use symbol addresses - /// during code emission time. The JIT is capable of doing this because it - /// creates jump tables or constant pools in memory on the fly while the - /// object code emitters rely on a linker to have real addresses and should - /// use relocations instead. - bool earlyResolveAddresses() const override { return true; } - - /// addRelocation - Whenever a relocatable address is needed, it should be - /// noted with this interface. - void addRelocation(const MachineRelocation &MR) override = 0; - - /// FIXME: These should all be handled with relocations! - - /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in - /// the constant pool that was last emitted with the emitConstantPool method. - /// - uintptr_t getConstantPoolEntryAddress(unsigned Index) const override = 0; - - /// getJumpTableEntryAddress - Return the address of the jump table with index - /// 'Index' in the function that last called initJumpTableInfo. - /// - uintptr_t getJumpTableEntryAddress(unsigned Index) const override = 0; - - /// getMachineBasicBlockAddress - Return the address of the specified - /// MachineBasicBlock, only usable after the label for the MBB has been - /// emitted. - /// - uintptr_t - getMachineBasicBlockAddress(MachineBasicBlock *MBB) const override = 0; - - /// getLabelAddress - Return the address of the specified Label, only usable - /// after the Label has been emitted. - /// - uintptr_t getLabelAddress(MCSymbol *Label) const override = 0; - - /// Specifies the MachineModuleInfo object. This is used for exception handling - /// purposes. - void setModuleInfo(MachineModuleInfo* Info) override = 0; - - /// getLabelLocations - Return the label locations map of the label IDs to - /// their address. - virtual DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() { - return nullptr; - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h index 6ca3d7d1765f..005bc1eb2b2d 100644 --- a/include/llvm/CodeGen/JumpInstrTables.h +++ b/include/llvm/CodeGen/JumpInstrTables.h @@ -39,13 +39,14 @@ class Module; /// jmp f_orig@PLT /// \endverbatim /// -/// Support for an architecture depends on two functions in TargetInstrInfo: -/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the -/// appropriate instructions for the jump statement (an unconditional branch) -/// and for padding to make the table have a size that is a power of two. This -/// padding uses a trap instruction to ensure that calls to this area halt the -/// program. The default implementations of these functions call -/// llvm_unreachable. +/// Support for an architecture depends on three functions in TargetInstrInfo: +/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter +/// uses these to generate the appropriate instructions for the jump statement +/// (an unconditional branch) and for padding to make the table have a size that +/// is a power of two. This padding uses a trap instruction to ensure that calls +/// to this area halt the program. The default implementations of these +/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound, +/// which returns 0 by default. class JumpInstrTables : public ModulePass { public: static char ID; @@ -64,6 +65,14 @@ public: /// Checks to see if there is already a table for the given FunctionType. bool hasTable(FunctionType *FunTy); + /// Maps the function into a subset of function types, depending on the + /// jump-instruction table style selected from JumpTableTypes in + /// JumpInstrTables.cpp. The choice of mapping determines the number of + /// jump-instruction tables generated by this pass. E.g., the simplest mapping + /// converts every function type into void f(); so, all functions end up in a + /// single table. + static FunctionType *transformType(JumpTable::JumpTableType JTT, + FunctionType *FunTy); private: /// The metadata used while a jump table is being built struct TableMeta { @@ -76,14 +85,6 @@ private: typedef DenseMap<FunctionType *, struct TableMeta> JumpMap; - /// Maps the function into a subset of function types, depending on the - /// jump-instruction table style selected from JumpTableTypes in - /// JumpInstrTables.cpp. The choice of mapping determines the number of - /// jump-instruction tables generated by this pass. E.g., the simplest mapping - /// converts every function type into void f(); so, all functions end up in a - /// single table. - FunctionType *transformType(FunctionType *FunTy); - /// The current state of functions and jump entries in the table(s). JumpMap Metadata; diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 036aea30a510..11a360a491a7 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -19,14 +19,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" -#include <utility> #include <unordered_map> +#include <utility> namespace llvm { class MachineInstr; @@ -48,6 +48,8 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + assert((!D || D->isResolved()) && "Expected resolved node"); + assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); } @@ -116,8 +118,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - AssertingVH<const MDNode> Desc; // Debug info descriptor. - AssertingVH<const MDNode> InlinedAtLocation; // Location at which this + const MDNode *Desc; // Debug info descriptor. + const MDNode *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. @@ -148,12 +150,6 @@ public: /// empty - Return true if there is any lexical scope information available. bool empty() { return CurrentFnLexicalScope == nullptr; } - /// isCurrentFunctionScope - Return true if given lexical scope represents - /// current function. - bool isCurrentFunctionScope(const LexicalScope *LS) { - return LS == CurrentFnLexicalScope; - } - /// getCurrentFunctionScope - Return lexical scope for the current function. LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope; @@ -163,7 +159,7 @@ public: /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. void getMachineBasicBlocks(DebugLoc DL, - SmallPtrSet<const MachineBasicBlock *, 4> &MBBs); + SmallPtrSetImpl<const MachineBasicBlock *> &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 372c294da306..e7ccbfa617e5 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,6 +39,7 @@ namespace { llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); + llvm::linkStatepointExampleGC(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 6629e6046532..ce9845ee1673 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -119,6 +119,12 @@ namespace llvm { return isDeadDef() ? nullptr : LateVal; } + /// Returns the value alive at the end of the instruction, if any. This can + /// be a live-through value, a live def or a dead def. + VNInfo *valueOutOrDead() const { + return LateVal; + } + /// Return the value defined by this instruction, if any. This includes /// dead defs, it is the value created by the instruction's def operands. VNInfo *valueDefined() const { @@ -204,6 +210,23 @@ namespace llvm { const_vni_iterator vni_begin() const { return valnos.begin(); } const_vni_iterator vni_end() const { return valnos.end(); } + /// Constructs a new LiveRange object. + LiveRange() { + } + + /// Constructs a new LiveRange object by copying segments and valnos from + /// another LiveRange. + LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) { + // Duplicate valnos. + for (const VNInfo *VNI : Other.valnos) { + createValueCopy(VNI, Allocator); + } + // Now we can copy segments and remap their valnos. + for (const Segment &S : Other.segments) { + segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); + } + } + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the /// end of the range. If no Segment contains this position, but the @@ -217,6 +240,14 @@ namespace llvm { return I; } + const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster /// when searching large ranges. @@ -397,6 +428,12 @@ namespace llvm { /// scanning the Other range starting at I. bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + /// Returns true if all segments of the @p Other live range are completely + /// covered by this live range. + /// Adjacent live ranges do not affect the covering:the liverange + /// [1,5](5,10] covers (3,7]. + bool covers(const LiveRange &Other) const; + /// Add the specified Segment to this range, merging segments as /// appropriate. This returns an iterator to the inserted segment (which /// may have grown since it was inserted). @@ -435,6 +472,12 @@ namespace llvm { removeSegment(S.start, S.end, RemoveDeadValNo); } + /// Remove segment pointed to by iterator @p I from this range. This does + /// not remove dead value numbers. + iterator removeSegment(iterator I) { + return segments.erase(I); + } + /// Query Liveness at Idx. /// The sub-instruction slot of Idx doesn't matter, only the instruction /// it refers to is considered. @@ -484,9 +527,9 @@ namespace llvm { /// Returns true if the live range is zero length, i.e. no live segments /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { - for (const_iterator i = begin(), e = end(); i != e; ++i) - if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < - i->end.getBaseIndex()) + for (const Segment &S : segments) + if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < + S.end.getBaseIndex()) return false; return true; } @@ -509,6 +552,10 @@ namespace llvm { void verify() const; #endif + protected: + /// Append a segment to the list of segments. + void append(const LiveRange::Segment S); + private: iterator addSegmentFrom(Segment S, iterator From); @@ -529,11 +576,122 @@ namespace llvm { public: typedef LiveRange super; + /// A live range for subregisters. The LaneMask specifies which parts of the + /// super register are covered by the interval. + /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). + class SubRange : public LiveRange { + public: + SubRange *Next; + unsigned LaneMask; + + /// Constructs a new SubRange object. + SubRange(unsigned LaneMask) + : Next(nullptr), LaneMask(LaneMask) { + } + + /// Constructs a new SubRange object by copying liveness from @p Other. + SubRange(unsigned LaneMask, const LiveRange &Other, + BumpPtrAllocator &Allocator) + : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) { + } + }; + + private: + SubRange *SubRanges; ///< Single linked list of subregister live ranges. + + public: const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + : SubRanges(nullptr), reg(Reg), weight(Weight) {} + + template<typename T> + class SingleLinkedListIterator { + T *P; + public: + SingleLinkedListIterator<T>(T *P) : P(P) {} + SingleLinkedListIterator<T> &operator++() { + P = P->Next; + return *this; + } + SingleLinkedListIterator<T> &operator++(int) { + SingleLinkedListIterator res = *this; + ++*this; + return res; + } + bool operator!=(const SingleLinkedListIterator<T> &Other) { + return P != Other.operator->(); + } + bool operator==(const SingleLinkedListIterator<T> &Other) { + return P == Other.operator->(); + } + T &operator*() const { + return *P; + } + T *operator->() const { + return P; + } + }; + + typedef SingleLinkedListIterator<SubRange> subrange_iterator; + subrange_iterator subrange_begin() { + return subrange_iterator(SubRanges); + } + subrange_iterator subrange_end() { + return subrange_iterator(nullptr); + } + + typedef SingleLinkedListIterator<const SubRange> const_subrange_iterator; + const_subrange_iterator subrange_begin() const { + return const_subrange_iterator(SubRanges); + } + const_subrange_iterator subrange_end() const { + return const_subrange_iterator(nullptr); + } + + iterator_range<subrange_iterator> subranges() { + return make_range(subrange_begin(), subrange_end()); + } + + iterator_range<const_subrange_iterator> subranges() const { + return make_range(subrange_begin(), subrange_end()); + } + + /// Creates a new empty subregister live range. The range is added at the + /// beginning of the subrange list; subrange iterators stay valid. + SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) { + SubRange *Range = new (Allocator) SubRange(LaneMask); + appendSubRange(Range); + return Range; + } + + /// Like createSubRange() but the new range is filled with a copy of the + /// liveness information in @p CopyFrom. + SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask, + const LiveRange &CopyFrom) { + SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); + appendSubRange(Range); + return Range; + } + + /// Returns true if subregister liveness information is available. + bool hasSubRanges() const { + return SubRanges != nullptr; + } + + /// Removes all subregister liveness information. + void clearSubRanges() { + SubRanges = nullptr; + } + + /// Removes all subranges without any segments (subranges without segments + /// are not considered valid and should only exist temporarily). + void removeEmptySubRanges(); + + /// Construct main live range by merging the SubRanges of @p LI. + void constructMainRangeFromSubranges(const SlotIndexes &Indexes, + VNInfo::Allocator &VNIAllocator); /// getSize - Returns the sum of sizes of all the LiveRange's. /// @@ -558,9 +716,23 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; + /// \brief Walks the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify(const MachineRegisterInfo *MRI = nullptr) const {} +#else + void verify(const MachineRegisterInfo *MRI = nullptr) const; +#endif + private: LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; + /// Appends @p Range to SubRanges list. + void appendSubRange(SubRange *Range) { + Range->Next = SubRanges; + SubRanges = Range; + } }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 176665bc2566..d8c921fce313 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H -#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#ifndef LLVM_CODEGEN_LIVEINTERVALANALYSIS_H +#define LLVM_CODEGEN_LIVEINTERVALANALYSIS_H #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" @@ -50,7 +50,6 @@ namespace llvm { class LiveIntervals : public MachineFunctionPass { MachineFunction* MF; MachineRegisterInfo* MRI; - const TargetMachine* TM; const TargetRegisterInfo* TRI; const TargetInstrInfo* TII; AliasAnalysis *AA; @@ -155,16 +154,11 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead = nullptr); - /// \brief Walk the values in the given interval and compute which ones - /// are dead. Dead values are not deleted, however: - /// - Dead PHIDef values are marked as unused. - /// - New dead machine instructions are added to the dead vector. - /// - CanSeparate is set to true if the interval may have been separated - /// into multiple connected components. - void computeDeadValues(LiveInterval *li, - LiveRange &LR, - bool *CanSeparate, - SmallVectorImpl<MachineInstr*> *dead); + /// Specialized version of + /// shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead) + /// that works on a subregister live range and only looks at uses matching + /// the lane mask of the subregister range. + void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -176,14 +170,21 @@ namespace llvm { /// See also LiveRangeCalc::extend(). void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices); - /// pruneValue - If an LI value is live at Kill, prune its live range by - /// removing any liveness reachable from Kill. Add live range end points to + + /// If @p LR has a live value at @p Kill, prune its live range by removing + /// any liveness reachable from Kill. Add live range end points to /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the /// value's live range. /// /// Calling pruneValue() and extendToIndices() can be used to reconstruct /// SSA form after adding defs to a virtual register. - void pruneValue(LiveInterval *LI, SlotIndex Kill, + void pruneValue(LiveRange &LR, SlotIndex Kill, + SmallVectorImpl<SlotIndex> *EndPoints); + + /// Subregister aware variant of pruneValue(LiveRange &LR, SlotIndex Kill, + /// SmallVectorImpl<SlotIndex> &EndPoints). Prunes the value in the main + /// range and all sub ranges. + void pruneValue(LiveInterval &LI, SlotIndex Kill, SmallVectorImpl<SlotIndex> *EndPoints); SlotIndexes *getSlotIndexes() const { @@ -405,6 +406,16 @@ namespace llvm { /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); + /// Walk the values in @p LI and check for dead values: + /// - Dead PHIDef values are marked as unused. + /// - Dead operands are marked as such. + /// - Completely dead machine instructions are added to the @p dead vector + /// if it is not nullptr. + /// Returns true if any PHI value numbers have been removed which may + /// have separated the interval into multiple connected components. + bool computeDeadValues(LiveInterval &LI, + SmallVectorImpl<MachineInstr*> *dead); + static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; @@ -414,6 +425,16 @@ namespace llvm { void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + + /// Helper function for repairIntervalsInRange(), walks backwards and + /// creates/modifies live segments in @p LR to match the operands found. + /// Only full operands or operands with subregisters matching @p LaneMask + /// are considered. + void repairOldRegInRange(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + const SlotIndex endIdx, LiveRange &LR, + unsigned Reg, unsigned LaneMask = ~0u); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 2f40509a1111..1381c46a2750 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -84,10 +84,16 @@ public: bool changedSince(unsigned tag) const { return tag != Tag; } // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg); + void unify(LiveInterval &VirtReg, const LiveRange &Range); + void unify(LiveInterval &VirtReg) { + unify(VirtReg, VirtReg); + } // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg); + void extract(LiveInterval &VirtReg, const LiveRange &Range); + void extract(LiveInterval &VirtReg) { + extract(VirtReg, VirtReg); + } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 847092b1d824..91e4ddcde170 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -26,8 +26,8 @@ // %XMM0<def> = ..., %YMM0<imp-use> (%YMM0 and all its sub-registers are alive) //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVE_PHYS_REGS_H -#define LLVM_CODEGEN_LIVE_PHYS_REGS_H +#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H +#define LLVM_CODEGEN_LIVEPHYSREGS_H #include "llvm/ADT/SparseSet.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -143,4 +143,4 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) { } // namespace llvm -#endif // LLVM_CODEGEN_LIVE_PHYS_REGS_H +#endif diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 5767cab1a4db..44c3c4eaf7b1 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { @@ -111,18 +112,15 @@ public: /// @param vrm Map of virtual registers to physical registers for this /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. - LiveRangeEdit(LiveInterval *parent, - SmallVectorImpl<unsigned> &newRegs, - MachineFunction &MF, - LiveIntervals &lis, - VirtRegMap *vrm, + LiveRangeEdit(LiveInterval *parent, SmallVectorImpl<unsigned> &newRegs, + MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, Delegate *delegate = nullptr) - : Parent(parent), NewRegs(newRegs), - MRI(MF.getRegInfo()), LIS(lis), VRM(vrm), - TII(*MF.getTarget().getInstrInfo()), - TheDelegate(delegate), - FirstNew(newRegs.size()), - ScannedRemattable(false) { MRI.setDelegate(this); } + : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis), + VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), + TheDelegate(delegate), FirstNew(newRegs.size()), + ScannedRemattable(false) { + MRI.setDelegate(this); + } ~LiveRangeEdit() { MRI.resetDelegate(this); } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index a4a5fcc31e12..55b97dc3e71d 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -134,14 +134,14 @@ private: // Intermediate data structures // PhysRegInfo - Keep track of which instruction was the last def of a // physical register. This is a purely local property, because all physical // register references are presumed dead across basic blocks. - MachineInstr **PhysRegDef; + std::vector<MachineInstr *> PhysRegDef; // PhysRegInfo - Keep track of which instruction was the last use of a // physical register. This is a purely local property, because all physical // register references are presumed dead across basic blocks. - MachineInstr **PhysRegUse; + std::vector<MachineInstr *> PhysRegUse; - SmallVector<unsigned, 4> *PHIVarInfo; + std::vector<SmallVector<unsigned, 4>> PHIVarInfo; // DistanceMap - Keep track the distance of a MI from the start of the // current basic block. @@ -175,6 +175,10 @@ private: // Intermediate data structures /// register which is used in a PHI node. We map that to the BB the vreg /// is coming from. void analyzePHINodes(const MachineFunction& Fn); + + void runOnInstr(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs); + + void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs); public: bool runOnMachineFunction(MachineFunction &MF) override; diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index a08cc2eb508a..1440b967aea2 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -486,11 +486,15 @@ public: /// Insert a range of instructions into the instruction list before I. template<typename IT> void insert(iterator I, IT S, IT E) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); Insts.insert(I.getInstrIterator(), S, E); } /// Insert MI into the instruction list before I. iterator insert(iterator I, MachineInstr *MI) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && "Cannot insert instruction with bundle flags"); return Insts.insert(I.getInstrIterator(), MI); @@ -498,6 +502,8 @@ public: /// Insert MI into the instruction list after I. iterator insertAfter(iterator I, MachineInstr *MI) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && "Cannot insert instruction with bundle flags"); return Insts.insertAfter(I.getInstrIterator(), MI); diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h deleted file mode 100644 index 81b0ba1e7c71..000000000000 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ /dev/null @@ -1,334 +0,0 @@ -//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an abstract interface that is used by the machine code -// emission framework to output the code. This allows machine code emission to -// be separated from concerns such as resolution of call targets, and where the -// machine code will be written (memory or disk, f.e.). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H -#define LLVM_CODEGEN_MACHINECODEEMITTER_H - -#include "llvm/IR/DebugLoc.h" -#include "llvm/Support/DataTypes.h" -#include <string> - -namespace llvm { - -class MachineBasicBlock; -class MachineConstantPool; -class MachineJumpTableInfo; -class MachineFunction; -class MachineModuleInfo; -class MachineRelocation; -class Value; -class GlobalValue; -class Function; -class MCSymbol; - -/// MachineCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxiliary -/// structures, such as jump tables, relocations, etc. -/// -/// Emission of machine code is complicated by the fact that we don't (in -/// general) know the size of the machine code that we're about to emit before -/// we emit it. As such, we preallocate a certain amount of memory, and set the -/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we -/// emit machine instructions, we advance the CurBufferPtr to indicate the -/// location of the next byte to emit. In the case of a buffer overflow (we -/// need to emit more machine code than we have allocated space for), the -/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire -/// function has been emitted, the overflow condition is checked, and if it has -/// occurred, more memory is allocated, and we reemit the code into it. -/// -class MachineCodeEmitter { - virtual void anchor(); -protected: - /// BufferBegin/BufferEnd - Pointers to the start and end of the memory - /// allocated for this code buffer. - uint8_t *BufferBegin, *BufferEnd; - /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting - /// code. This is guaranteed to be in the range [BufferBegin,BufferEnd]. If - /// this pointer is at BufferEnd, it will never move due to code emission, and - /// all code emission requests will be ignored (this is the buffer overflow - /// condition). - uint8_t *CurBufferPtr; - -public: - virtual ~MachineCodeEmitter() {} - - /// startFunction - This callback is invoked when the specified function is - /// about to be code generated. This initializes the BufferBegin/End/Ptr - /// fields. - /// - virtual void startFunction(MachineFunction &F) = 0; - - /// finishFunction - This callback is invoked when the specified function has - /// finished code generation. If a buffer overflow has occurred, this method - /// returns true (the callee is required to try again), otherwise it returns - /// false. - /// - virtual bool finishFunction(MachineFunction &F) = 0; - - /// emitByte - This callback is invoked when a byte needs to be written to the - /// output stream. - /// - void emitByte(uint8_t B) { - if (CurBufferPtr != BufferEnd) - *CurBufferPtr++ = B; - } - - /// emitWordLE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitWordLE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - emitWordLEInto(CurBufferPtr, W); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be - /// written to an arbitrary buffer in little-endian format. Buf must have at - /// least 4 bytes of available space. - /// - static void emitWordLEInto(uint8_t *&Buf, uint32_t W) { - *Buf++ = (uint8_t)(W >> 0); - *Buf++ = (uint8_t)(W >> 8); - *Buf++ = (uint8_t)(W >> 16); - *Buf++ = (uint8_t)(W >> 24); - } - - /// emitWordBE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitWordBE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordLE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitDWordLE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordBE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitDWordBE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitAlignment - Move the CurBufferPtr pointer up to the specified - /// alignment (saturated to BufferEnd of course). - void emitAlignment(unsigned Alignment) { - if (Alignment == 0) Alignment = 1; - - if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { - // Move the current buffer ptr up to the specified alignment. - CurBufferPtr = - (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & - ~(uintptr_t)(Alignment-1)); - } else { - CurBufferPtr = BufferEnd; - } - } - - - /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be - /// written to the output stream. - void emitULEB128Bytes(uint64_t Value) { - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - if (Value) Byte |= 0x80; - emitByte(Byte); - } while (Value); - } - - /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be - /// written to the output stream. - void emitSLEB128Bytes(uint64_t Value) { - uint64_t Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - emitByte(Byte); - } while (IsMore); - } - - /// emitString - This callback is invoked when a String needs to be - /// written to the output stream. - void emitString(const std::string &String) { - for (unsigned i = 0, N = static_cast<unsigned>(String.size()); - i < N; ++i) { - uint8_t C = String[i]; - emitByte(C); - } - emitByte(0); - } - - /// emitInt32 - Emit a int32 directive. - void emitInt32(int32_t Value) { - if (4 <= BufferEnd-CurBufferPtr) { - *((uint32_t*)CurBufferPtr) = Value; - CurBufferPtr += 4; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt64 - Emit a int64 directive. - void emitInt64(uint64_t Value) { - if (8 <= BufferEnd-CurBufferPtr) { - *((uint64_t*)CurBufferPtr) = Value; - CurBufferPtr += 8; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt32At - Emit the Int32 Value in Addr. - void emitInt32At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint32_t*)Addr) = (uint32_t)Value; - } - - /// emitInt64At - Emit the Int64 Value in Addr. - void emitInt64At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint64_t*)Addr) = (uint64_t)Value; - } - - /// processDebugLoc - Records debug location information about a - /// MachineInstruction. This is called before emitting any bytes associated - /// with the instruction. Even if successive instructions have the same debug - /// location, this method will be called for each one. - virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {} - - /// emitLabel - Emits a label - virtual void emitLabel(MCSymbol *Label) = 0; - - /// allocateSpace - Allocate a block of space in the current output buffer, - /// returning null (and setting conditions to indicate buffer overflow) on - /// failure. Alignment is the alignment in bytes of the buffer desired. - virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { - emitAlignment(Alignment); - void *Result; - - // Check for buffer overflow. - if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { - CurBufferPtr = BufferEnd; - Result = nullptr; - } else { - // Allocate the space. - Result = CurBufferPtr; - CurBufferPtr += Size; - } - - return Result; - } - - /// StartMachineBasicBlock - This should be called by the target when a new - /// basic block is about to be emitted. This way the MCE knows where the - /// start of the block is, and can implement getMachineBasicBlockAddress. - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; - - /// getCurrentPCValue - This returns the address that the next emitted byte - /// will be output to. - /// - virtual uintptr_t getCurrentPCValue() const { - return (uintptr_t)CurBufferPtr; - } - - /// getCurrentPCOffset - Return the offset from the start of the emitted - /// buffer that we are currently writing to. - virtual uintptr_t getCurrentPCOffset() const { - return CurBufferPtr-BufferBegin; - } - - /// earlyResolveAddresses - True if the code emitter can use symbol addresses - /// during code emission time. The JIT is capable of doing this because it - /// creates jump tables or constant pools in memory on the fly while the - /// object code emitters rely on a linker to have real addresses and should - /// use relocations instead. - virtual bool earlyResolveAddresses() const = 0; - - /// addRelocation - Whenever a relocatable address is needed, it should be - /// noted with this interface. - virtual void addRelocation(const MachineRelocation &MR) = 0; - - /// FIXME: These should all be handled with relocations! - - /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in - /// the constant pool that was last emitted with the emitConstantPool method. - /// - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; - - /// getJumpTableEntryAddress - Return the address of the jump table with index - /// 'Index' in the function that last called initJumpTableInfo. - /// - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; - - /// getMachineBasicBlockAddress - Return the address of the specified - /// MachineBasicBlock, only usable after the label for the MBB has been - /// emitted. - /// - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; - - /// getLabelAddress - Return the address of the specified Label, only usable - /// after the LabelID has been emitted. - /// - virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0; - - /// Specifies the MachineModuleInfo object. This is used for exception handling - /// purposes. - virtual void setModuleInfo(MachineModuleInfo* Info) = 0; -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h deleted file mode 100644 index 820bc87425b9..000000000000 --- a/include/llvm/CodeGen/MachineCodeInfo.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- MachineCodeInfo.h - Class used to report JIT info -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines MachineCodeInfo, a class used by the JIT ExecutionEngine -// to report information about the generated machine code. -// -// See JIT::runJITOnFunction for usage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECODEINFO_H -#define LLVM_CODEGEN_MACHINECODEINFO_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class MachineCodeInfo { -private: - size_t Size; // Number of bytes in memory used - void *Address; // The address of the function in memory - -public: - MachineCodeInfo() : Size(0), Address(nullptr) {} - - void setSize(size_t s) { - Size = s; - } - - void setAddress(void *a) { - Address = a; - } - - size_t size() const { - return Size; - } - - void *address() const { - return Address; - } - -}; - -} - -#endif - diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h new file mode 100644 index 000000000000..176af14dc317 --- /dev/null +++ b/include/llvm/CodeGen/MachineCombinerPattern.h @@ -0,0 +1,29 @@ +//===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by +// combiner ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines instruction pattern supported by combiner +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECOMBINERPATTERN_H +#define LLVM_CODEGEN_MACHINECOMBINERPATTERN_H + +namespace llvm { + +/// Enumeration of instruction pattern supported by machine combiner +/// +/// +namespace MachineCombinerPattern { +// Forward declaration +enum MC_PATTERN : int; +} // end namespace MachineCombinerPattern +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index f1ae0bf5f9cf..a6980a6daeac 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H #define LLVM_CODEGEN_MACHINEDOMINATORS_H +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -38,6 +39,103 @@ typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode; /// compute a normal dominator tree. /// class MachineDominatorTree : public MachineFunctionPass { + /// \brief Helper structure used to hold all the basic blocks + /// involved in the split of a critical edge. + struct CriticalEdge { + MachineBasicBlock *FromBB; + MachineBasicBlock *ToBB; + MachineBasicBlock *NewBB; + CriticalEdge(MachineBasicBlock *FromBB, MachineBasicBlock *ToBB, + MachineBasicBlock *NewBB) + : FromBB(FromBB), ToBB(ToBB), NewBB(NewBB) {} + }; + + /// \brief Pile up all the critical edges to be split. + /// The splitting of a critical edge is local and thus, it is possible + /// to apply several of those changes at the same time. + mutable SmallVector<CriticalEdge, 32> CriticalEdgesToSplit; + /// \brief Remember all the basic blocks that are inserted during + /// edge splitting. + /// Invariant: NewBBs == all the basic blocks contained in the NewBB + /// field of all the elements of CriticalEdgesToSplit. + /// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs + /// such as BB == elt.NewBB. + mutable SmallSet<MachineBasicBlock *, 32> NewBBs; + + /// \brief Apply all the recorded critical edges to the DT. + /// This updates the underlying DT information in a way that uses + /// the fast query path of DT as much as possible. + /// + /// \post CriticalEdgesToSplit.empty(). + void applySplitCriticalEdges() const { + // Bail out early if there is nothing to do. + if (CriticalEdgesToSplit.empty()) + return; + + // For each element in CriticalEdgesToSplit, remember whether or + // not element is the new immediate domminator of its successor. + // The mapping is done by index, i.e., the information for the ith + // element of CriticalEdgesToSplit is the ith element of IsNewIDom. + SmallVector<bool, 32> IsNewIDom; + IsNewIDom.resize(CriticalEdgesToSplit.size()); + size_t Idx = 0; + + // Collect all the dominance properties info, before invalidating + // the underlying DT. + for (CriticalEdge &Edge : CriticalEdgesToSplit) { + // Update dominator information. + MachineBasicBlock *Succ = Edge.ToBB; + MachineDomTreeNode *SucccDTNode = DT->getNode(Succ); + + IsNewIDom[Idx] = true; + for (MachineBasicBlock *PredBB : Succ->predecessors()) { + if (PredBB == Edge.NewBB) + continue; + // If we are in this situation: + // FromBB1 FromBB2 + // + + + // + + + + + // + + + + + // ... Split1 Split2 ... + // + + + // + + + // + + // Succ + // Instead of checking the domiance property with Split2, we + // check it with FromBB2 since Split2 is still unknown of the + // underlying DT structure. + if (NewBBs.count(PredBB)) { + assert(PredBB->pred_size() == 1 && "A basic block resulting from a " + "critical edge split has more " + "than one predecessor!"); + PredBB = *PredBB->pred_begin(); + } + if (!DT->dominates(SucccDTNode, DT->getNode(PredBB))) { + IsNewIDom[Idx] = false; + break; + } + } + ++Idx; + } + + // Now, update DT with the collected dominance properties info. + Idx = 0; + for (CriticalEdge &Edge : CriticalEdgesToSplit) { + // We know FromBB dominates NewBB. + MachineDomTreeNode *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB); + MachineDomTreeNode *SucccDTNode = DT->getNode(Edge.ToBB); + + // If all the other predecessors of "Succ" are dominated by "Succ" itself + // then the new block is the new immediate dominator of "Succ". Otherwise, + // the new block doesn't dominate anything. + if (IsNewIDom[Idx]) + DT->changeImmediateDominator(SucccDTNode, NewDTNode); + ++Idx; + } + NewBBs.clear(); + CriticalEdgesToSplit.clear(); + } + public: static char ID; // Pass ID, replacement for typeid DominatorTreeBase<MachineBasicBlock>* DT; @@ -46,7 +144,10 @@ public: ~MachineDominatorTree(); - DominatorTreeBase<MachineBasicBlock>& getBase() { return *DT; } + DominatorTreeBase<MachineBasicBlock> &getBase() { + applySplitCriticalEdges(); + return *DT; + } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -55,14 +156,17 @@ public: /// dominators, this will always be a single block (the entry node). /// inline const std::vector<MachineBasicBlock*> &getRoots() const { + applySplitCriticalEdges(); return DT->getRoots(); } inline MachineBasicBlock *getRoot() const { + applySplitCriticalEdges(); return DT->getRoot(); } inline MachineDomTreeNode *getRootNode() const { + applySplitCriticalEdges(); return DT->getRootNode(); } @@ -70,17 +174,20 @@ public: inline bool dominates(const MachineDomTreeNode* A, const MachineDomTreeNode* B) const { + applySplitCriticalEdges(); return DT->dominates(A, B); } inline bool dominates(const MachineBasicBlock* A, const MachineBasicBlock* B) const { + applySplitCriticalEdges(); return DT->dominates(A, B); } // dominates - Return true if A dominates B. This performs the // special checks necessary if A and B are in the same basic block. bool dominates(const MachineInstr *A, const MachineInstr *B) const { + applySplitCriticalEdges(); const MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); if (BBA != BBB) return DT->dominates(BBA, BBB); @@ -100,11 +207,13 @@ public: inline bool properlyDominates(const MachineDomTreeNode* A, const MachineDomTreeNode* B) const { + applySplitCriticalEdges(); return DT->properlyDominates(A, B); } inline bool properlyDominates(const MachineBasicBlock* A, const MachineBasicBlock* B) const { + applySplitCriticalEdges(); return DT->properlyDominates(A, B); } @@ -112,10 +221,12 @@ public: /// for basic block A and B. If there is no such block then return NULL. inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B) { + applySplitCriticalEdges(); return DT->findNearestCommonDominator(A, B); } inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { + applySplitCriticalEdges(); return DT->getNode(BB); } @@ -123,6 +234,7 @@ public: /// block. This is the same as using operator[] on this class. /// inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { + applySplitCriticalEdges(); return DT->getNode(BB); } @@ -131,6 +243,7 @@ public: /// the children list of the immediate dominator. inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, MachineBasicBlock *DomBB) { + applySplitCriticalEdges(); return DT->addNewBlock(BB, DomBB); } @@ -139,11 +252,13 @@ public: /// inline void changeImmediateDominator(MachineBasicBlock *N, MachineBasicBlock* NewIDom) { + applySplitCriticalEdges(); DT->changeImmediateDominator(N, NewIDom); } inline void changeImmediateDominator(MachineDomTreeNode *N, MachineDomTreeNode* NewIDom) { + applySplitCriticalEdges(); DT->changeImmediateDominator(N, NewIDom); } @@ -151,24 +266,49 @@ public: /// dominate any other blocks. Removes node from its immediate dominator's /// children list. Deletes dominator node associated with basic block BB. inline void eraseNode(MachineBasicBlock *BB) { + applySplitCriticalEdges(); DT->eraseNode(BB); } /// splitBlock - BB is split and now it has one successor. Update dominator /// tree to reflect this change. inline void splitBlock(MachineBasicBlock* NewBB) { + applySplitCriticalEdges(); DT->splitBlock(NewBB); } /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. bool isReachableFromEntry(const MachineBasicBlock *A) { + applySplitCriticalEdges(); return DT->isReachableFromEntry(A); } void releaseMemory() override; void print(raw_ostream &OS, const Module*) const override; + + /// \brief Record that the critical edge (FromBB, ToBB) has been + /// split with NewBB. + /// This is best to use this method instead of directly update the + /// underlying information, because this helps mitigating the + /// number of time the DT information is invalidated. + /// + /// \note Do not use this method with regular edges. + /// + /// \note To benefit from the compile time improvement incurred by this + /// method, the users of this method have to limit the queries to the DT + /// interface between two edges splitting. In other words, they have to + /// pack the splitting of critical edges as much as possible. + void recordSplitCriticalEdge(MachineBasicBlock *FromBB, + MachineBasicBlock *ToBB, + MachineBasicBlock *NewBB) { + bool Inserted = NewBBs.insert(NewBB).second; + (void)Inserted; + assert(Inserted && + "A basic block inserted via edge splitting cannot appear twice"); + CriticalEdgesToSplit.push_back(CriticalEdge(FromBB, ToBB, NewBB)); + } }; //===------------------------------------- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index c51f8fe03bbf..667736021f92 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -109,13 +109,23 @@ class MachineFrameInfo { // block and doesn't need additional handling for allocation beyond that. bool PreAllocated; + // If true, an LLVM IR value might point to this object. + // Normally, spill slots and fixed-offset objects don't alias IR-accessible + // objects, but there are exceptions (on PowerPC, for example, some byval + // arguments have ABI-prescribed offsets). + bool isAliased; + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, - bool isSS, const AllocaInst *Val) + bool isSS, const AllocaInst *Val, bool A) : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), - isSpillSlot(isSS), Alloca(Val), PreAllocated(false) {} + isSpillSlot(isSS), Alloca(Val), PreAllocated(false), isAliased(A) {} }; - const TargetMachine &TM; + /// StackAlignment - The alignment of the stack. + unsigned StackAlignment; + + /// StackRealignable - Can the stack be realigned. + bool StackRealignable; /// Objects - The list of stack objects allocated... /// @@ -230,10 +240,17 @@ class MachineFrameInfo { /// pointer. bool HasInlineAsmWithSPAdjust; - const TargetFrameLowering *getFrameLowering() const; + /// True if the function contains a call to the llvm.vastart intrinsic. + bool HasVAStart; + + /// True if this is a varargs function that contains a musttail call. + bool HasMustTailInVarArgFunc; + public: - explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) - : TM(TM), RealignOption(RealignOpt) { + explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, + bool RealignOpt) + : StackAlignment(StackAlign), StackRealignable(isStackRealign), + RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; @@ -250,6 +267,8 @@ public: LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; HasInlineAsmWithSPAdjust = false; + HasVAStart = false; + HasMustTailInVarArgFunc = false; } /// hasStackObjects - Return true if there are any stack objects in this @@ -469,6 +488,14 @@ public: bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } + /// Returns true if the function calls the llvm.va_start intrinsic. + bool hasVAStart() const { return HasVAStart; } + void setHasVAStart(bool B) { HasVAStart = B; } + + /// Returns true if the function is variadic and contains a musttail call. + bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } + void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and @@ -479,21 +506,34 @@ public: /// CreateFixedObject - Create a new object at a fixed location on the stack. /// All fixed objects should be created before other objects are created for - /// efficiency. By default, fixed objects are immutable. This returns an - /// index with a negative value. + /// efficiency. By default, fixed objects are not pointed to by LLVM IR + /// values. This returns an index with a negative value. /// - int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable); + int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable, + bool isAliased = false); /// CreateFixedSpillStackObject - Create a spill slot at a fixed location /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); + /// Allocates memory at a fixed, target-specific offset from the frame + /// pointer. Marks the function as having its frame address taken. + int CreateFrameAllocation(uint64_t Size); + /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); } + /// isAliasedObjectIndex - Returns true if the specified index corresponds + /// to an object that might be pointed to by an LLVM IR value. + bool isAliasedObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isAliased; + } + /// isImmutableObjectIndex - Returns true if the specified index corresponds /// to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 042c62b4a887..4e9ff9ebb4fe 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -21,6 +21,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/Recycler.h" @@ -38,6 +39,7 @@ class MachineModuleInfo; class MCContext; class Pass; class TargetMachine; +class TargetSubtargetInfo; class TargetRegisterClass; struct MachinePointerInfo; @@ -70,15 +72,24 @@ private: /// MachineFunction is destroyed. struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); + + /// \brief Factory function: default behavior is to call new using the + /// supplied allocator. + /// + /// This function can be overridden in a derive class. + template<typename Ty> + static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { + return new (Allocator.Allocate<Ty>()) Ty(MF); + } }; class MachineFunction { const Function *Fn; const TargetMachine &Target; + const TargetSubtargetInfo *STI; MCContext &Ctx; MachineModuleInfo &MMI; - GCModuleInfo *GMI; - + // RegInfo - Information about each register in use in the function. MachineRegisterInfo *RegInfo; @@ -138,12 +149,10 @@ class MachineFunction { void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; public: MachineFunction(const Function *Fn, const TargetMachine &TM, - unsigned FunctionNum, MachineModuleInfo &MMI, - GCModuleInfo* GMI); + unsigned FunctionNum, MachineModuleInfo &MMI); ~MachineFunction(); MachineModuleInfo &getMMI() const { return MMI; } - GCModuleInfo *getGMI() const { return GMI; } MCContext &getContext() const { return Ctx; } /// getFunction - Return the LLVM function that this machine code represents @@ -162,6 +171,11 @@ public: /// const TargetMachine &getTarget() const { return Target; } + /// getSubtarget - Return the subtarget for which this machine code is being + /// compiled. + const TargetSubtargetInfo &getSubtarget() const { return *STI; } + void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } @@ -234,7 +248,7 @@ public: template<typename Ty> Ty *getInfo() { if (!MFInfo) - MFInfo = new (Allocator.Allocate<Ty>()) Ty(*this); + MFInfo = Ty::template create<Ty>(Allocator, *this); return static_cast<Ty*>(MFInfo); } @@ -399,7 +413,7 @@ public: MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, uint64_t s, unsigned base_alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); /// getMachineMemOperand - Allocate a new MachineMemOperand by copying diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 3c828116411e..bcf1f5caaa8c 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -244,12 +244,22 @@ public: /// DebugLoc getDebugLoc() const { return debugLoc; } - /// getDebugVariable() - Return the debug variable referenced by + /// \brief Return the debug variable referenced by /// this DBG_VALUE instruction. DIVariable getDebugVariable() const { assert(isDebugValue() && "not a DBG_VALUE"); - const MDNode *Var = getOperand(getNumOperands() - 1).getMetadata(); - return DIVariable(Var); + DIVariable Var(getOperand(2).getMetadata()); + assert(Var.Verify() && "not a DIVariable"); + return Var; + } + + /// \brief Return the complex address expression referenced by + /// this DBG_VALUE instruction. + DIExpression getDebugExpression() const { + assert(isDebugValue() && "not a DBG_VALUE"); + DIExpression Expr(getOperand(3).getMetadata()); + assert(Expr.Verify() && "not a DIExpression"); + return Expr; } /// emitError - Emit an error referring to the source location of this @@ -510,6 +520,49 @@ public: return hasProperty(MCID::FoldableAsLoad, Type); } + /// \brief Return true if this instruction behaves + /// the same way as the generic REG_SEQUENCE instructions. + /// E.g., on ARM, + /// dX VMOVDRR rY, rZ + /// is equivalent to + /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be + /// override accordingly. + bool isRegSequenceLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::RegSequence, Type); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic EXTRACT_SUBREG instructions. + /// E.g., on ARM, + /// rX, rY VMOVRRD dZ + /// is equivalent to two EXTRACT_SUBREG: + /// rX = EXTRACT_SUBREG dZ, ssub_0 + /// rY = EXTRACT_SUBREG dZ, ssub_1 + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be + /// override accordingly. + bool isExtractSubregLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::ExtractSubreg, Type); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic INSERT_SUBREG instructions. + /// E.g., on ARM, + /// dX = VSETLNi32 dY, rZ, Imm + /// is equivalent to a INSERT_SUBREG: + /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be + /// override accordingly. + bool isInsertSubregLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::InsertSubreg, Type); + } + //===--------------------------------------------------------------------===// // Side Effect Analysis //===--------------------------------------------------------------------===// @@ -614,7 +667,6 @@ public: /// are not marking copies from and to the same register class with this flag. bool isAsCheapAsAMove(QueryType Type = AllInBundle) const { // Only returns true for a bundle if all bundled instructions are cheap. - // FIXME: This probably requires a target hook. return hasProperty(MCID::CheapAsAMove, Type); } @@ -672,6 +724,12 @@ public: /// eraseFromBundle() to erase individual bundled instructions. void eraseFromParent(); + /// Unlink 'this' from the containing basic block and delete it. + /// + /// For all definitions mark their uses in DBG_VALUE nodes + /// as undefined. Otherwise like eraseFromParent(). + void eraseFromParentAndMarkDBGValuesForRemoval(); + /// Unlink 'this' form its basic block and delete it. /// /// If the instruction is part of a bundle, the other instructions in the @@ -1081,7 +1139,10 @@ public: /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. /// - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(const DebugLoc dl) { + debugLoc = dl; + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + } /// RemoveOperand - Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 21a482cdbd4c..8859b6a019ea 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -58,6 +58,10 @@ public: MachineInstr *operator->() const { return MI; } operator MachineBasicBlock::iterator() const { return MI; } + /// If conversion operators fail, use this method to get the MachineInstr + /// explicitly. + MachineInstr *getInstr() const { return MI; } + /// addReg - Add a new virtual register operand... /// const @@ -170,6 +174,8 @@ public: const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); + assert((MI->isDebugValue() ? MI->getDebugVariable().Verify() : true) && + "first MDNode argument of a DBG_VALUE not a DIVariable"); return *this; } @@ -345,24 +351,25 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, /// address. The convention is that a DBG_VALUE is indirect iff the /// second operand is an immediate. /// -inline MachineInstrBuilder BuildMI(MachineFunction &MF, - DebugLoc DL, - const MCInstrDesc &MCID, - bool IsIndirect, - unsigned Reg, - unsigned Offset, - const MDNode *MD) { +inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(DIVariable(Variable).Verify() && "not a DIVariable"); + assert(DIExpression(Expr).Verify() && "not a DIExpression"); if (IsIndirect) return BuildMI(MF, DL, MCID) - .addReg(Reg, RegState::Debug) - .addImm(Offset) - .addMetadata(MD); + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(Variable) + .addMetadata(Expr); else { assert(Offset == 0 && "A direct address cannot have an offset."); return BuildMI(MF, DL, MCID) - .addReg(Reg, RegState::Debug) - .addReg(0U, RegState::Debug) - .addMetadata(MD); + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(Variable) + .addMetadata(Expr); } } @@ -371,15 +378,15 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, /// address and inserts it at position I. /// inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - DebugLoc DL, - const MCInstrDesc &MCID, - bool IsIndirect, - unsigned Reg, - unsigned Offset, - const MDNode *MD) { + MachineBasicBlock::iterator I, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(DIVariable(Variable).Verify() && "not a DIVariable"); + assert(DIExpression(Expr).Verify() && "not a DIExpression"); MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD); + MachineInstr *MI = + BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); BB.insert(I, MI); return MachineInstrBuilder(MF, MI); } diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 2532c16271f0..eb5086cbe5a5 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -18,6 +18,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*> #include "llvm/Support/DataTypes.h" @@ -91,7 +92,7 @@ class MachineMemOperand { MachinePointerInfo PtrInfo; uint64_t Size; unsigned Flags; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; const MDNode *Ranges; public: @@ -117,7 +118,8 @@ public: /// MachineMemOperand - Construct an MachineMemOperand object with the /// specified PtrInfo, flags, size, and base alignment. MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, - unsigned base_alignment, const MDNode *TBAAInfo = nullptr, + unsigned base_alignment, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } @@ -161,8 +163,8 @@ public: /// base address, without the offset. uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; } - /// getTBAAInfo - Return the TBAA tag for the memory reference. - const MDNode *getTBAAInfo() const { return TBAAInfo; } + /// getAAInfo - Return the AA tags for the memory reference. + AAMDNodes getAAInfo() const { return AAInfo; } /// getRanges - Return the range tag for the memory reference. const MDNode *getRanges() const { return Ranges; } diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6d8d05684c56..f0d0b2dbcdbc 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -66,6 +66,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke. SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke. + SmallVector<MCSymbol*, 1> ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector<int> TypeIds; // List of type ids (filters negative) @@ -110,10 +111,6 @@ class MachineModuleInfo : public ImmutablePass { /// by debug and exception handling consumers. std::vector<MCCFIInstruction> FrameInstructions; - /// CompactUnwindEncoding - If the target supports it, this is the compact - /// unwind encoding. It replaces a function's CIE and FDE. - uint32_t CompactUnwindEncoding; - /// LandingPads - List of LandingPadInfo describing the landing pad /// information in the current function. std::vector<LandingPadInfo> LandingPads; @@ -131,7 +128,7 @@ class MachineModuleInfo : public ImmutablePass { unsigned CurCallSite; /// TypeInfos - List of C++ TypeInfo used in the current function. - std::vector<const GlobalVariable *> TypeInfos; + std::vector<const GlobalValue *> TypeInfos; /// FilterIds - List of typeids encoding filters used in the current function. std::vector<unsigned> FilterIds; @@ -165,13 +162,24 @@ class MachineModuleInfo : public ImmutablePass { /// to _fltused on Windows targets. bool UsesVAFloatArgument; + /// UsesMorestackAddr - True if the module calls the __morestack function + /// indirectly, as is required under the large code model on x86. This is used + /// to emit a definition of a symbol, __morestack_addr, containing the + /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more + /// details. + bool UsesMorestackAddr; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingVH<MDNode> Var; + TrackingMDNodeRef Var; + TrackingMDNodeRef Expr; unsigned Slot; DebugLoc Loc; + + VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy; VariableDbgInfoMapTy VariableDbgInfos; @@ -234,6 +242,14 @@ public: UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. @@ -247,15 +263,6 @@ public: return FrameInstructions.size() - 1; } - /// getCompactUnwindEncoding - Returns the compact unwind encoding for a - /// function if the target supports the encoding. This encoding replaces a - /// function's CIE and FDE. - uint32_t getCompactUnwindEncoding() const { return CompactUnwindEncoding; } - - /// setCompactUnwindEncoding - Set the compact unwind encoding for a function - /// if the target supports the encoding. - void setCompactUnwindEncoding(uint32_t Enc) { CompactUnwindEncoding = Enc; } - /// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// block when its address is taken. This cannot be its normal LBB label /// because the block may be accessed outside its containing function. @@ -313,20 +320,25 @@ public: /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// void addCatchTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef<const GlobalVariable *> TyInfo); + ArrayRef<const GlobalValue *> TyInfo); /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. /// void addFilterTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef<const GlobalVariable *> TyInfo); + ArrayRef<const GlobalValue *> TyInfo); /// addCleanup - Add a cleanup action for a landing pad. /// void addCleanup(MachineBasicBlock *LandingPad); + /// Add a clause for a landing pad. Returns a new label for the clause. This + /// is used by EH schemes that have more than one landing pad. In this case, + /// each clause gets its own basic block. + MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. - unsigned getTypeIDFor(const GlobalVariable *TI); + unsigned getTypeIDFor(const GlobalValue *TI); /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is /// function wide. @@ -387,7 +399,7 @@ public: /// getTypeInfos - Return a reference to the C++ typeinfo for the current /// function. - const std::vector<const GlobalVariable *> &getTypeInfos() const { + const std::vector<const GlobalValue *> &getTypeInfos() const { return TypeInfos; } @@ -403,9 +415,9 @@ public: /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. - void setVariableDbgInfo(MDNode *N, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo Info = { N, Slot, Loc }; - VariableDbgInfos.push_back(std::move(Info)); + void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, + DebugLoc Loc) { + VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 22969bc80776..eed1e575f93b 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -506,6 +506,11 @@ public: Contents.ImmVal = immVal; } + void setFPImm(const ConstantFP *CFP) { + assert(isFPImm() && "Wrong MachineOperand mutator"); + Contents.CFP = CFP; + } + void setOffset(int64_t Offset) { assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || isBlockAddress()) && "Wrong MachineOperand accessor"); @@ -544,6 +549,11 @@ public: /// the setImm method should be used. void ChangeToImmediate(int64_t ImmVal); + /// ChangeToFPImmediate - Replace this operand with a new FP immediate operand + /// of the specified value. If an operand is known to be an FP immediate + /// already, the setFPImm method should be used. + void ChangeToFPImmediate(const ConstantFP *FPImm); + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. @@ -702,6 +712,8 @@ public: friend class MachineInstr; friend class MachineRegisterInfo; private: + void removeRegFromUses(); + //===--------------------------------------------------------------------===// // Methods for handling register use/def lists. //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index beb2c4f0c5c0..aab5c407629f 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -22,7 +22,7 @@ namespace llvm { /// /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used -/// to compute the a post-dominator tree. +/// to compute the post-dominator tree. /// struct MachinePostDominatorTree : public MachineFunctionPass { private: diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 51139f72ba22..caa48a5cf0cf 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,9 +17,10 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include <vector> namespace llvm { @@ -39,7 +40,7 @@ public: }; private: - const TargetMachine &TM; + const MachineFunction *MF; Delegate *TheDelegate; /// IsSSA - True when the machine function is in SSA form and virtual @@ -51,6 +52,9 @@ private: /// accurate when after this flag is cleared. bool TracksLiveness; + /// True if subregister liveness is tracked. + bool TracksSubRegLiveness; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -69,7 +73,7 @@ private: /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. - MachineOperand **PhysRegUseDefLists; + std::vector<MachineOperand *> PhysRegUseDefLists; /// getRegUseDefListHead - Return the head pointer for the register use/def /// list for the specified virtual or physical register. @@ -122,11 +126,10 @@ private: MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: - explicit MachineRegisterInfo(const TargetMachine &TM); - ~MachineRegisterInfo(); + explicit MachineRegisterInfo(const MachineFunction *MF); const TargetRegisterInfo *getTargetRegisterInfo() const { - return TM.getRegisterInfo(); + return MF->getSubtarget().getRegisterInfo(); } void resetDelegate(Delegate *delegate) { @@ -179,6 +182,12 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } + bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + + void enableSubRegLiveness(bool Enable = true) { + TracksSubRegLiveness = Enable; + } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -515,8 +524,12 @@ public: /// /// That function will return NULL if the virtual registers have incompatible /// constraints. + /// + /// Note that if ToReg is a physical register the function will replace and + /// apply sub registers to ToReg in order to obtain a final/proper physical + /// register. void replaceRegWith(unsigned FromReg, unsigned ToReg); - + /// getVRegDef - Return the machine instr that defines the specified virtual /// register or null if none is found. This assumes that the code is in SSA /// form, so there should only be one definition. @@ -764,6 +777,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); + /// Returns a mask covering all bits that can appear in lane masks of + /// subregisters of the virtual register @p Reg. + unsigned getMaxLaneMaskForVReg(unsigned Reg) const; + /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h deleted file mode 100644 index e77845745165..000000000000 --- a/include/llvm/CodeGen/MachineRelocation.h +++ /dev/null @@ -1,342 +0,0 @@ -//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachineRelocation class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINERELOCATION_H -#define LLVM_CODEGEN_MACHINERELOCATION_H - -#include "llvm/Support/DataTypes.h" -#include <cassert> - -namespace llvm { -class GlobalValue; -class MachineBasicBlock; - -/// MachineRelocation - This represents a target-specific relocation value, -/// produced by the code emitter. This relocation is resolved after the has -/// been emitted, either to an object file or to memory, when the target of the -/// relocation can be resolved. -/// -/// A relocation is made up of the following logical portions: -/// 1. An offset in the machine code buffer, the location to modify. -/// 2. A target specific relocation type (a number from 0 to 63). -/// 3. A symbol being referenced, either as a GlobalValue* or as a string. -/// 4. An optional constant value to be added to the reference. -/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is -/// not needed for the relocation. -/// 6. An index into the GOT, if the target uses a GOT -/// -class MachineRelocation { - enum AddressType { - isResult, // Relocation has be transformed into its result pointer. - isGV, // The Target.GV field is valid. - isIndirectSym, // Relocation of an indirect symbol. - isBB, // Relocation of BB address. - isExtSym, // The Target.ExtSym field is valid. - isConstPool, // Relocation of constant pool address. - isJumpTable, // Relocation of jump table address. - isGOTIndex // The Target.GOTIndex field is valid. - }; - - /// Offset - This is the offset from the start of the code buffer of the - /// relocation to perform. - uintptr_t Offset; - - /// ConstantVal - A field that may be used by the target relocation type. - intptr_t ConstantVal; - - union { - void *Result; // If this has been resolved to a resolved pointer - GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. - MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB - const char *ExtSym; // If this is a pointer to a named symbol - unsigned Index; // Constant pool / jump table index - unsigned GOTIndex; // Index in the GOT of this symbol/global - } Target; - - unsigned TargetReloType : 6; // The target relocation ID - AddressType AddrType : 4; // The field of Target to use - bool MayNeedFarStub : 1; // True if this relocation may require a far-stub - bool GOTRelative : 1; // Should this relocation be relative to the GOT? - bool TargetResolve : 1; // True if target should resolve the address - -public: - // Relocation types used in a generic implementation. Currently, relocation - // entries for all things use the generic VANILLA type until they are refined - // into target relocation types. - enum RelocationType { - VANILLA - }; - - /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue. - /// - static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType, - GlobalValue *GV, intptr_t cst = 0, - bool MayNeedFarStub = 0, - bool GOTrelative = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isGV; - Result.MayNeedFarStub = MayNeedFarStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.GV = GV; - return Result; - } - - /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an - /// indirect symbol. - static MachineRelocation getIndirectSymbol(uintptr_t offset, - unsigned RelocationType, - GlobalValue *GV, intptr_t cst = 0, - bool MayNeedFarStub = 0, - bool GOTrelative = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isIndirectSym; - Result.MayNeedFarStub = MayNeedFarStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.GV = GV; - return Result; - } - - /// MachineRelocation::getBB - Return a relocation entry for a BB. - /// - static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType, - MachineBasicBlock *MBB, intptr_t cst = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isBB; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = false; - Result.Target.MBB = MBB; - return Result; - } - - /// MachineRelocation::getExtSym - Return a relocation entry for an external - /// symbol, like "free". - /// - static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType, - const char *ES, intptr_t cst = 0, - bool GOTrelative = 0, - bool NeedStub = true) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isExtSym; - Result.MayNeedFarStub = NeedStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.ExtSym = ES; - return Result; - } - - /// MachineRelocation::getConstPool - Return a relocation entry for a constant - /// pool entry. - /// - static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType, - unsigned CPI, intptr_t cst = 0, - bool letTargetResolve = false) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isConstPool; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = letTargetResolve; - Result.Target.Index = CPI; - return Result; - } - - /// MachineRelocation::getJumpTable - Return a relocation entry for a jump - /// table entry. - /// - static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType, - unsigned JTI, intptr_t cst = 0, - bool letTargetResolve = false) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isJumpTable; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = letTargetResolve; - Result.Target.Index = JTI; - return Result; - } - - /// getMachineCodeOffset - Return the offset into the code buffer that the - /// relocation should be performed. - intptr_t getMachineCodeOffset() const { - return Offset; - } - - /// getRelocationType - Return the target-specific relocation ID for this - /// relocation. - unsigned getRelocationType() const { - return TargetReloType; - } - - /// getConstantVal - Get the constant value associated with this relocation. - /// This is often an offset from the symbol. - /// - intptr_t getConstantVal() const { - return ConstantVal; - } - - /// setConstantVal - Set the constant value associated with this relocation. - /// This is often an offset from the symbol. - /// - void setConstantVal(intptr_t val) { - ConstantVal = val; - } - - /// isGlobalValue - Return true if this relocation is a GlobalValue, as - /// opposed to a constant string. - bool isGlobalValue() const { - return AddrType == isGV; - } - - /// isIndirectSymbol - Return true if this relocation is the address an - /// indirect symbol - bool isIndirectSymbol() const { - return AddrType == isIndirectSym; - } - - /// isBasicBlock - Return true if this relocation is a basic block reference. - /// - bool isBasicBlock() const { - return AddrType == isBB; - } - - /// isExternalSymbol - Return true if this is a constant string. - /// - bool isExternalSymbol() const { - return AddrType == isExtSym; - } - - /// isConstantPoolIndex - Return true if this is a constant pool reference. - /// - bool isConstantPoolIndex() const { - return AddrType == isConstPool; - } - - /// isJumpTableIndex - Return true if this is a jump table reference. - /// - bool isJumpTableIndex() const { - return AddrType == isJumpTable; - } - - /// isGOTRelative - Return true the target wants the index into the GOT of - /// the symbol rather than the address of the symbol. - bool isGOTRelative() const { - return GOTRelative; - } - - /// mayNeedFarStub - This function returns true if the JIT for this target may - /// need either a stub function or an indirect global-variable load to handle - /// the relocated GlobalValue reference. For example, the x86-64 call - /// instruction can only call functions within +/-2GB of the call site. - /// Anything farther away needs a longer mov+call sequence, which can't just - /// be written on top of the existing call. - bool mayNeedFarStub() const { - return MayNeedFarStub; - } - - /// letTargetResolve - Return true if the target JITInfo is usually - /// responsible for resolving the address of this relocation. - bool letTargetResolve() const { - return TargetResolve; - } - - /// getGlobalValue - If this is a global value reference, return the - /// referenced global. - GlobalValue *getGlobalValue() const { - assert((isGlobalValue() || isIndirectSymbol()) && - "This is not a global value reference!"); - return Target.GV; - } - - MachineBasicBlock *getBasicBlock() const { - assert(isBasicBlock() && "This is not a basic block reference!"); - return Target.MBB; - } - - /// getString - If this is a string value, return the string reference. - /// - const char *getExternalSymbol() const { - assert(isExternalSymbol() && "This is not an external symbol reference!"); - return Target.ExtSym; - } - - /// getConstantPoolIndex - If this is a const pool reference, return - /// the index into the constant pool. - unsigned getConstantPoolIndex() const { - assert(isConstantPoolIndex() && "This is not a constant pool reference!"); - return Target.Index; - } - - /// getJumpTableIndex - If this is a jump table reference, return - /// the index into the jump table. - unsigned getJumpTableIndex() const { - assert(isJumpTableIndex() && "This is not a jump table reference!"); - return Target.Index; - } - - /// getResultPointer - Once this has been resolved to point to an actual - /// address, this returns the pointer. - void *getResultPointer() const { - assert(AddrType == isResult && "Result pointer isn't set yet!"); - return Target.Result; - } - - /// setResultPointer - Set the result to the specified pointer value. - /// - void setResultPointer(void *Ptr) { - Target.Result = Ptr; - AddrType = isResult; - } - - /// setGOTIndex - Set the GOT index to a specific value. - void setGOTIndex(unsigned idx) { - AddrType = isGOTIndex; - Target.GOTIndex = idx; - } - - /// getGOTIndex - Once this has been resolved to an entry in the GOT, - /// this returns that index. The index is from the lowest address entry - /// in the GOT. - unsigned getGOTIndex() const { - assert(AddrType == isGOTIndex); - return Target.GOTIndex; - } -}; -} - -#endif diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 7d85432101b5..a31940161ca5 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -80,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" - #include <memory> namespace llvm { @@ -250,7 +249,7 @@ protected: public: ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, bool IsPostRA) - : ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA, + : ScheduleDAGInstrs(*C->MF, C->MLI, IsPostRA, /*RemoveKillFlags=*/IsPostRA, C->LIS), AA(C->AA), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), CurrentTop(), CurrentBottom(), NextClusterPred(nullptr), NextClusterSucc(nullptr) { diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 323b694f3933..bfe6e945b6da 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -44,8 +44,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINE_TRACE_METRICS_H -#define LLVM_CODEGEN_MACHINE_TRACE_METRICS_H +#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H +#define LLVM_CODEGEN_MACHINETRACEMETRICS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -264,8 +264,9 @@ public: /// classes are included. For the caller to account for extra machine /// instructions, it must first resolve each instruction's scheduling class. unsigned getResourceLength( - ArrayRef<const MachineBasicBlock*> Extrablocks = None, - ArrayRef<const MCSchedClassDesc*> ExtraInstrs = None) const; + ArrayRef<const MachineBasicBlock *> Extrablocks = None, + ArrayRef<const MCSchedClassDesc *> ExtraInstrs = None, + ArrayRef<const MCSchedClassDesc *> RemoveInstrs = None) const; /// Return the length of the (data dependency) critical path through the /// trace. @@ -286,6 +287,12 @@ public: /// Return the Depth of a PHI instruction in a trace center block successor. /// The PHI does not have to be part of the trace. unsigned getPHIDepth(const MachineInstr *PHI) const; + + /// A dependence is useful if the basic block of the defining instruction + /// is part of the trace of the user instruction. It is assumed that DefMI + /// dominates UseMI (see also isUsefulDominator). + bool isDepInTrace(const MachineInstr *DefMI, + const MachineInstr *UseMI) const; }; /// A trace ensemble is a collection of traces selected using the same diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index ad215ec09843..e3fbfe89c203 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -118,6 +119,7 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + FIRST_VALUETYPE = 0, // This is always the beginning of the list. LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. @@ -165,6 +167,12 @@ namespace llvm { bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + /// isValid - Return true if this is a valid simple valuetype. + bool isValid() const { + return (SimpleTy >= MVT::FIRST_VALUETYPE && + SimpleTy < MVT::LAST_VALUETYPE); + } + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && @@ -196,21 +204,24 @@ namespace llvm { /// is32BitVector - Return true if this is a 32-bit vector type. bool is32BitVector() const { return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || - SimpleTy == MVT::v1i32); + SimpleTy == MVT::v1i32 || SimpleTy == MVT::v2f16 || + SimpleTy == MVT::v1f32); } /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); + SimpleTy == MVT::v4f16 || SimpleTy == MVT::v2f32 || + SimpleTy == MVT::v1f64); } /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || - SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); + SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 || + SimpleTy == MVT::v2f64); } /// is256BitVector - Return true if this is a 256-bit vector type. @@ -572,6 +583,52 @@ namespace llvm { /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); + private: + /// A simple iterator over the MVT::SimpleValueType enum. + struct mvt_iterator { + SimpleValueType VT; + mvt_iterator(SimpleValueType VT) : VT(VT) {} + MVT operator*() const { return VT; } + bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; } + mvt_iterator& operator++() { + VT = (MVT::SimpleValueType)((int)VT + 1); + assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE && + "MVT iterator overflowed."); + return *this; + } + }; + /// A range of the MVT::SimpleValueType enum. + typedef iterator_range<mvt_iterator> mvt_range; + + public: + /// SimpleValueType Iteration + /// @{ + static mvt_range all_valuetypes() { + return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE); + } + static mvt_range integer_valuetypes() { + return mvt_range(MVT::FIRST_INTEGER_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1)); + } + static mvt_range fp_valuetypes() { + return mvt_range(MVT::FIRST_FP_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1)); + } + static mvt_range vector_valuetypes() { + return mvt_range(MVT::FIRST_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1)); + } + static mvt_range integer_vector_valuetypes() { + return mvt_range( + MVT::FIRST_INTEGER_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1)); + } + static mvt_range fp_vector_valuetypes() { + return mvt_range( + MVT::FIRST_FP_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1)); + } + /// @} }; } // End llvm namespace diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h index ff62c0959344..02d39fe383f1 100644 --- a/include/llvm/CodeGen/PBQP/CostAllocator.h +++ b/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -15,117 +15,101 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_COSTALLOCATOR_H -#define LLVM_COSTALLOCATOR_H +#ifndef LLVM_CODEGEN_PBQP_COSTALLOCATOR_H +#define LLVM_CODEGEN_PBQP_COSTALLOCATOR_H -#include <set> +#include "llvm/ADT/DenseSet.h" +#include <memory> #include <type_traits> +namespace llvm { namespace PBQP { -template <typename CostT, - typename CostKeyTComparator> -class CostPool { +template <typename ValueT> +class ValuePool { public: + typedef std::shared_ptr<const ValueT> PoolRef; - class PoolEntry { +private: + + class PoolEntry : public std::enable_shared_from_this<PoolEntry> { public: - template <typename CostKeyT> - PoolEntry(CostPool &pool, CostKeyT cost) - : pool(pool), cost(std::move(cost)), refCount(0) {} - ~PoolEntry() { pool.removeEntry(this); } - void incRef() { ++refCount; } - bool decRef() { --refCount; return (refCount == 0); } - CostT& getCost() { return cost; } - const CostT& getCost() const { return cost; } + template <typename ValueKeyT> + PoolEntry(ValuePool &Pool, ValueKeyT Value) + : Pool(Pool), Value(std::move(Value)) {} + ~PoolEntry() { Pool.removeEntry(this); } + const ValueT& getValue() const { return Value; } private: - CostPool &pool; - CostT cost; - std::size_t refCount; + ValuePool &Pool; + ValueT Value; }; - class PoolRef { + class PoolEntryDSInfo { public: - PoolRef(PoolEntry *entry) : entry(entry) { - this->entry->incRef(); + static inline PoolEntry* getEmptyKey() { return nullptr; } + + static inline PoolEntry* getTombstoneKey() { + return reinterpret_cast<PoolEntry*>(static_cast<uintptr_t>(1)); } - PoolRef(const PoolRef &r) { - entry = r.entry; - entry->incRef(); + + template <typename ValueKeyT> + static unsigned getHashValue(const ValueKeyT &C) { + return hash_value(C); } - PoolRef& operator=(const PoolRef &r) { - assert(entry != nullptr && "entry should not be null."); - PoolEntry *temp = r.entry; - temp->incRef(); - entry->decRef(); - entry = temp; - return *this; + + static unsigned getHashValue(PoolEntry *P) { + return getHashValue(P->getValue()); } - ~PoolRef() { - if (entry->decRef()) - delete entry; + static unsigned getHashValue(const PoolEntry *P) { + return getHashValue(P->getValue()); } - void reset(PoolEntry *entry) { - entry->incRef(); - this->entry->decRef(); - this->entry = entry; + + template <typename ValueKeyT1, typename ValueKeyT2> + static + bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) { + return C1 == C2; } - CostT& operator*() { return entry->getCost(); } - const CostT& operator*() const { return entry->getCost(); } - CostT* operator->() { return &entry->getCost(); } - const CostT* operator->() const { return &entry->getCost(); } - private: - PoolEntry *entry; - }; -private: - class EntryComparator { - public: - template <typename CostKeyT> - typename std::enable_if< - !std::is_same<PoolEntry*, - typename std::remove_const<CostKeyT>::type>::value, - bool>::type - operator()(const PoolEntry* a, const CostKeyT &b) { - return compare(a->getCost(), b); + template <typename ValueKeyT> + static bool isEqual(const ValueKeyT &C, PoolEntry *P) { + if (P == getEmptyKey() || P == getTombstoneKey()) + return false; + return isEqual(C, P->getValue()); } - bool operator()(const PoolEntry* a, const PoolEntry* b) { - return compare(a->getCost(), b->getCost()); + + static bool isEqual(PoolEntry *P1, PoolEntry *P2) { + if (P1 == getEmptyKey() || P1 == getTombstoneKey()) + return P1 == P2; + return isEqual(P1->getValue(), P2); } - private: - CostKeyTComparator compare; + }; - typedef std::set<PoolEntry*, EntryComparator> EntrySet; + typedef DenseSet<PoolEntry*, PoolEntryDSInfo> EntrySetT; - EntrySet entrySet; + EntrySetT EntrySet; - void removeEntry(PoolEntry *p) { entrySet.erase(p); } + void removeEntry(PoolEntry *P) { EntrySet.erase(P); } public: + template <typename ValueKeyT> PoolRef getValue(ValueKeyT ValueKey) { + typename EntrySetT::iterator I = EntrySet.find_as(ValueKey); - template <typename CostKeyT> - PoolRef getCost(CostKeyT costKey) { - typename EntrySet::iterator itr = - std::lower_bound(entrySet.begin(), entrySet.end(), costKey, - EntryComparator()); - - if (itr != entrySet.end() && costKey == (*itr)->getCost()) - return PoolRef(*itr); + if (I != EntrySet.end()) + return PoolRef((*I)->shared_from_this(), &(*I)->getValue()); - PoolEntry *p = new PoolEntry(*this, std::move(costKey)); - entrySet.insert(itr, p); - return PoolRef(p); + auto P = std::make_shared<PoolEntry>(*this, std::move(ValueKey)); + EntrySet.insert(P.get()); + return PoolRef(std::move(P), &P->getValue()); } }; -template <typename VectorT, typename VectorTComparator, - typename MatrixT, typename MatrixTComparator> +template <typename VectorT, typename MatrixT> class PoolCostAllocator { private: - typedef CostPool<VectorT, VectorTComparator> VectorCostPool; - typedef CostPool<MatrixT, MatrixTComparator> MatrixCostPool; + typedef ValuePool<VectorT> VectorCostPool; + typedef ValuePool<MatrixT> MatrixCostPool; public: typedef VectorT Vector; typedef MatrixT Matrix; @@ -133,15 +117,16 @@ public: typedef typename MatrixCostPool::PoolRef MatrixPtr; template <typename VectorKeyT> - VectorPtr getVector(VectorKeyT v) { return vectorPool.getCost(std::move(v)); } + VectorPtr getVector(VectorKeyT v) { return VectorPool.getValue(std::move(v)); } template <typename MatrixKeyT> - MatrixPtr getMatrix(MatrixKeyT m) { return matrixPool.getCost(std::move(m)); } + MatrixPtr getMatrix(MatrixKeyT m) { return MatrixPool.getValue(std::move(m)); } private: - VectorCostPool vectorPool; - MatrixCostPool matrixPool; + VectorCostPool VectorPool; + MatrixCostPool MatrixPool; }; -} +} // namespace PBQP +} // namespace llvm -#endif // LLVM_COSTALLOCATOR_H +#endif diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index a55f0ea96c0a..4dc5674ae134 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -17,11 +17,12 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include <list> #include <map> #include <set> +namespace llvm { namespace PBQP { class GraphBase { @@ -29,12 +30,12 @@ namespace PBQP { typedef unsigned NodeId; typedef unsigned EdgeId; - /// \brief Returns a value representing an invalid (non-existent) node. + /// @brief Returns a value representing an invalid (non-existent) node. static NodeId invalidNodeId() { return std::numeric_limits<NodeId>::max(); } - /// \brief Returns a value representing an invalid (non-existent) edge. + /// @brief Returns a value representing an invalid (non-existent) edge. static EdgeId invalidEdgeId() { return std::numeric_limits<EdgeId>::max(); } @@ -56,6 +57,7 @@ namespace PBQP { typedef typename CostAllocator::MatrixPtr MatrixPtr; typedef typename SolverT::NodeMetadata NodeMetadata; typedef typename SolverT::EdgeMetadata EdgeMetadata; + typedef typename SolverT::GraphMetadata GraphMetadata; private: @@ -172,6 +174,7 @@ namespace PBQP { // ----- MEMBERS ----- + GraphMetadata Metadata; CostAllocator CostAlloc; SolverT *Solver; @@ -187,13 +190,19 @@ namespace PBQP { // ----- INTERNAL METHODS ----- - NodeEntry& getNode(NodeId NId) { return Nodes[NId]; } - const NodeEntry& getNode(NodeId NId) const { return Nodes[NId]; } + NodeEntry &getNode(NodeId NId) { + assert(NId < Nodes.size() && "Out of bound NodeId"); + return Nodes[NId]; + } + const NodeEntry &getNode(NodeId NId) const { + assert(NId < Nodes.size() && "Out of bound NodeId"); + return Nodes[NId]; + } EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; } const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; } - NodeId addConstructedNode(const NodeEntry &N) { + NodeId addConstructedNode(NodeEntry N) { NodeId NId = 0; if (!FreeNodeIds.empty()) { NId = FreeNodeIds.back(); @@ -206,7 +215,7 @@ namespace PBQP { return NId; } - EdgeId addConstructedEdge(const EdgeEntry &E) { + EdgeId addConstructedEdge(EdgeEntry E) { assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() && "Attempt to add duplicate edge."); EdgeId EId = 0; @@ -235,6 +244,12 @@ namespace PBQP { class NodeItr { public: + typedef std::forward_iterator_tag iterator_category; + typedef NodeId value_type; + typedef int difference_type; + typedef NodeId* pointer; + typedef NodeId& reference; + NodeItr(NodeId CurNId, const Graph &G) : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) { this->CurNId = findNextInUse(CurNId); // Move to first in-use node id @@ -249,7 +264,7 @@ namespace PBQP { NodeId findNextInUse(NodeId NId) const { while (NId < EndNId && std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) != - FreeNodeIds.end()) { + FreeNodeIds.end()) { ++NId; } return NId; @@ -328,10 +343,19 @@ namespace PBQP { const NodeEntry &NE; }; - /// \brief Construct an empty PBQP graph. - Graph() : Solver(nullptr) { } + /// @brief Construct an empty PBQP graph. + Graph() : Solver(nullptr) {} + + /// @brief Construct an empty PBQP graph with the given graph metadata. + Graph(GraphMetadata Metadata) : Metadata(Metadata), Solver(nullptr) {} + + /// @brief Get a reference to the graph metadata. + GraphMetadata& getMetadata() { return Metadata; } - /// \brief Lock this graph to the given solver instance in preparation + /// @brief Get a const-reference to the graph metadata. + const GraphMetadata& getMetadata() const { return Metadata; } + + /// @brief Lock this graph to the given solver instance in preparation /// for running the solver. This method will call solver.handleAddNode for /// each node in the graph, and handleAddEdge for each edge, to give the /// solver an opportunity to set up any requried metadata. @@ -344,13 +368,13 @@ namespace PBQP { Solver->handleAddEdge(EId); } - /// \brief Release from solver instance. + /// @brief Release from solver instance. void unsetSolver() { assert(Solver && "Solver not set."); Solver = nullptr; } - /// \brief Add a node with the given costs. + /// @brief Add a node with the given costs. /// @param Costs Cost vector for the new node. /// @return Node iterator for the added node. template <typename OtherVectorT> @@ -363,9 +387,29 @@ namespace PBQP { return NId; } - /// \brief Add an edge between the given nodes with the given costs. + /// @brief Add a node bypassing the cost allocator. + /// @param Costs Cost vector ptr for the new node (must be convertible to + /// VectorPtr). + /// @return Node iterator for the added node. + /// + /// This method allows for fast addition of a node whose costs don't need + /// to be passed through the cost allocator. The most common use case for + /// this is when duplicating costs from an existing node (when using a + /// pooling allocator). These have already been uniqued, so we can avoid + /// re-constructing and re-uniquing them by attaching them directly to the + /// new node. + template <typename OtherVectorPtrT> + NodeId addNodeBypassingCostAllocator(OtherVectorPtrT Costs) { + NodeId NId = addConstructedNode(NodeEntry(Costs)); + if (Solver) + Solver->handleAddNode(NId); + return NId; + } + + /// @brief Add an edge between the given nodes with the given costs. /// @param N1Id First node. /// @param N2Id Second node. + /// @param Costs Cost matrix for new edge. /// @return Edge iterator for the added edge. template <typename OtherVectorT> EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) { @@ -380,7 +424,32 @@ namespace PBQP { return EId; } - /// \brief Returns true if the graph is empty. + /// @brief Add an edge bypassing the cost allocator. + /// @param N1Id First node. + /// @param N2Id Second node. + /// @param Costs Cost matrix for new edge. + /// @return Edge iterator for the added edge. + /// + /// This method allows for fast addition of an edge whose costs don't need + /// to be passed through the cost allocator. The most common use case for + /// this is when duplicating costs from an existing edge (when using a + /// pooling allocator). These have already been uniqued, so we can avoid + /// re-constructing and re-uniquing them by attaching them directly to the + /// new edge. + template <typename OtherMatrixPtrT> + NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id, + OtherMatrixPtrT Costs) { + assert(getNodeCosts(N1Id).getLength() == Costs->getRows() && + getNodeCosts(N2Id).getLength() == Costs->getCols() && + "Matrix dimensions mismatch."); + // Get cost matrix from the problem domain. + EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, Costs)); + if (Solver) + Solver->handleAddEdge(EId); + return EId; + } + + /// @brief Returns true if the graph is empty. bool empty() const { return NodeIdSet(*this).empty(); } NodeIdSet nodeIds() const { return NodeIdSet(*this); } @@ -388,15 +457,15 @@ namespace PBQP { AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); } - /// \brief Get the number of nodes in the graph. + /// @brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. unsigned getNumNodes() const { return NodeIdSet(*this).size(); } - /// \brief Get the number of edges in the graph. + /// @brief Get the number of edges in the graph. /// @return Number of edges in the graph. unsigned getNumEdges() const { return EdgeIdSet(*this).size(); } - /// \brief Set a node's cost vector. + /// @brief Set a node's cost vector. /// @param NId Node to update. /// @param Costs New costs to set. template <typename OtherVectorT> @@ -407,11 +476,23 @@ namespace PBQP { getNode(NId).Costs = AllocatedCosts; } - /// \brief Get a node's cost vector (const version). + /// @brief Get a VectorPtr to a node's cost vector. Rarely useful - use + /// getNodeCosts where possible. + /// @param NId Node id. + /// @return VectorPtr to node cost vector. + /// + /// This method is primarily useful for duplicating costs quickly by + /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer + /// getNodeCosts when dealing with node cost values. + const VectorPtr& getNodeCostsPtr(NodeId NId) const { + return getNode(NId).Costs; + } + + /// @brief Get a node's cost vector. /// @param NId Node id. /// @return Node cost vector. const Vector& getNodeCosts(NodeId NId) const { - return *getNode(NId).Costs; + return *getNodeCostsPtr(NId); } NodeMetadata& getNodeMetadata(NodeId NId) { @@ -426,7 +507,7 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// \brief Set an edge's cost matrix. + /// @brief Set an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template <typename OtherMatrixT> @@ -437,34 +518,48 @@ namespace PBQP { getEdge(EId).Costs = AllocatedCosts; } - /// \brief Get an edge's cost matrix (const version). + /// @brief Get a MatrixPtr to a node's cost matrix. Rarely useful - use + /// getEdgeCosts where possible. + /// @param EId Edge id. + /// @return MatrixPtr to edge cost matrix. + /// + /// This method is primarily useful for duplicating costs quickly by + /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer + /// getEdgeCosts when dealing with edge cost values. + const MatrixPtr& getEdgeCostsPtr(EdgeId EId) const { + return getEdge(EId).Costs; + } + + /// @brief Get an edge's cost matrix. /// @param EId Edge id. /// @return Edge cost matrix. - const Matrix& getEdgeCosts(EdgeId EId) const { return *getEdge(EId).Costs; } + const Matrix& getEdgeCosts(EdgeId EId) const { + return *getEdge(EId).Costs; + } - EdgeMetadata& getEdgeMetadata(EdgeId NId) { - return getEdge(NId).Metadata; + EdgeMetadata& getEdgeMetadata(EdgeId EId) { + return getEdge(EId).Metadata; } - const EdgeMetadata& getEdgeMetadata(EdgeId NId) const { - return getEdge(NId).Metadata; + const EdgeMetadata& getEdgeMetadata(EdgeId EId) const { + return getEdge(EId).Metadata; } - /// \brief Get the first node connected to this edge. + /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. NodeId getEdgeNode1Id(EdgeId EId) { return getEdge(EId).getN1Id(); } - /// \brief Get the second node connected to this edge. + /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. NodeId getEdgeNode2Id(EdgeId EId) { return getEdge(EId).getN2Id(); } - /// \brief Get the "other" node connected to this edge. + /// @brief Get the "other" node connected to this edge. /// @param EId Edge id. /// @param NId Node id for the "given" node. /// @return The iterator for the "other" node connected to this edge. @@ -476,7 +571,7 @@ namespace PBQP { return E.getN1Id(); } - /// \brief Get the edge connecting two nodes. + /// @brief Get the edge connecting two nodes. /// @param N1Id First node id. /// @param N2Id Second node id. /// @return An id for edge (N1Id, N2Id) if such an edge exists, @@ -491,7 +586,7 @@ namespace PBQP { return invalidEdgeId(); } - /// \brief Remove a node from the graph. + /// @brief Remove a node from the graph. /// @param NId Node id. void removeNode(NodeId NId) { if (Solver) @@ -499,7 +594,7 @@ namespace PBQP { NodeEntry &N = getNode(NId); // TODO: Can this be for-each'd? for (AdjEdgeItr AEItr = N.adjEdgesBegin(), - AEEnd = N.adjEdgesEnd(); + AEEnd = N.adjEdgesEnd(); AEItr != AEEnd;) { EdgeId EId = *AEItr; ++AEItr; @@ -508,7 +603,7 @@ namespace PBQP { FreeNodeIds.push_back(NId); } - /// \brief Disconnect an edge from the given node. + /// @brief Disconnect an edge from the given node. /// /// Removes the given edge from the adjacency list of the given node. /// This operation leaves the edge in an 'asymmetric' state: It will no @@ -541,14 +636,14 @@ namespace PBQP { E.disconnectFrom(*this, NId); } - /// \brief Convenience method to disconnect all neighbours from the given + /// @brief Convenience method to disconnect all neighbours from the given /// node. void disconnectAllNeighborsFromNode(NodeId NId) { for (auto AEId : adjEdgeIds(NId)) disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId)); } - /// \brief Re-attach an edge to its nodes. + /// @brief Re-attach an edge to its nodes. /// /// Adds an edge that had been previously disconnected back into the /// adjacency set of the nodes that the edge connects. @@ -559,7 +654,7 @@ namespace PBQP { Solver->handleReconnectEdge(EId, NId); } - /// \brief Remove an edge from the graph. + /// @brief Remove an edge from the graph. /// @param EId Edge id. void removeEdge(EdgeId EId) { if (Solver) @@ -570,7 +665,7 @@ namespace PBQP { Edges[EId].invalidate(); } - /// \brief Remove all nodes and edges from the graph. + /// @brief Remove all nodes and edges from the graph. void clear() { Nodes.clear(); FreeNodeIds.clear(); @@ -578,9 +673,9 @@ namespace PBQP { FreeEdgeIds.clear(); } - /// \brief Dump a graph to an output stream. + /// @brief Dump a graph to an output stream. template <typename OStream> - void dump(OStream &OS) { + void dumpToStream(OStream &OS) { OS << nodeIds().size() << " " << edgeIds().size() << "\n"; for (auto NId : nodeIds()) { @@ -613,7 +708,12 @@ namespace PBQP { } } - /// \brief Print a representation of this graph in DOT format. + /// @brief Dump this graph to dbgs(). + void dump() { + dumpToStream(dbgs()); + } + + /// @brief Print a representation of this graph in DOT format. /// @param OS Output stream to print on. template <typename OStream> void printDot(OStream &OS) { @@ -637,6 +737,7 @@ namespace PBQP { } }; -} +} // namespace PBQP +} // namespace llvm #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index 69a9d83cc092..2792608e29cc 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -10,17 +10,19 @@ #ifndef LLVM_CODEGEN_PBQP_MATH_H #define LLVM_CODEGEN_PBQP_MATH_H +#include "llvm/ADT/Hashing.h" #include <algorithm> #include <cassert> #include <functional> +namespace llvm { namespace PBQP { typedef float PBQPNum; /// \brief PBQP Vector class. class Vector { - friend class VectorComparator; + friend hash_code hash_value(const Vector &); public: /// \brief Construct a PBQP vector of the given size. @@ -136,21 +138,12 @@ private: PBQPNum *Data; }; -class VectorComparator { -public: - bool operator()(const Vector &A, const Vector &B) { - if (A.Length < B.Length) - return true; - if (B.Length < A.Length) - return false; - char *AData = reinterpret_cast<char*>(A.Data); - char *BData = reinterpret_cast<char*>(B.Data); - return std::lexicographical_compare(AData, - AData + A.Length * sizeof(PBQPNum), - BData, - BData + A.Length * sizeof(PBQPNum)); - } -}; +/// \brief Return a hash_value for the given vector. +inline hash_code hash_value(const Vector &V) { + unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data); + unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data + V.Length); + return hash_combine(V.Length, hash_combine_range(VBegin, VEnd)); +} /// \brief Output a textual representation of the given vector on the given /// output stream. @@ -166,11 +159,10 @@ OStream& operator<<(OStream &OS, const Vector &V) { return OS; } - /// \brief PBQP Matrix class class Matrix { private: - friend class MatrixComparator; + friend hash_code hash_value(const Matrix &); public: /// \brief Construct a PBQP Matrix with the given dimensions. @@ -384,24 +376,12 @@ private: PBQPNum *Data; }; -class MatrixComparator { -public: - bool operator()(const Matrix &A, const Matrix &B) { - if (A.Rows < B.Rows) - return true; - if (B.Rows < A.Rows) - return false; - if (A.Cols < B.Cols) - return true; - if (B.Cols < A.Cols) - return false; - char *AData = reinterpret_cast<char*>(A.Data); - char *BData = reinterpret_cast<char*>(B.Data); - return std::lexicographical_compare( - AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)), - BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum))); - } -}; +/// \brief Return a hash_code for the given matrix. +inline hash_code hash_value(const Matrix &M) { + unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data); + unsigned *MEnd = reinterpret_cast<unsigned*>(M.Data + (M.Rows * M.Cols)); + return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd)); +} /// \brief Output a textual representation of the given matrix on the given /// output stream. @@ -409,7 +389,7 @@ template <typename OStream> OStream& operator<<(OStream &OS, const Matrix &M) { assert((M.getRows() != 0) && "Zero-row matrix badness."); for (unsigned i = 0; i < M.getRows(); ++i) - OS << M.getRowAsVector(i); + OS << M.getRowAsVector(i) << "\n"; return OS; } @@ -424,6 +404,11 @@ private: }; template <typename Metadata> +inline hash_code hash_value(const MDVector<Metadata> &V) { + return hash_value(static_cast<const Vector&>(V)); +} + +template <typename Metadata> class MDMatrix : public Matrix { public: MDMatrix(const Matrix &m) : Matrix(m), md(*this) { } @@ -433,6 +418,12 @@ private: Metadata md; }; +template <typename Metadata> +inline hash_code hash_value(const MDMatrix<Metadata> &M) { + return hash_value(static_cast<const Matrix&>(M)); } +} // namespace PBQP +} // namespace llvm + #endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index a55a06033c4e..21fde4d8a5cd 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -11,13 +11,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_REDUCTIONRULES_H -#define LLVM_REDUCTIONRULES_H +#ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H +#define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H #include "Graph.h" #include "Math.h" #include "Solution.h" +namespace llvm { namespace PBQP { /// \brief Reduce a node of degree one. @@ -186,6 +187,7 @@ namespace PBQP { return s; } -} +} // namespace PBQP +} // namespace llvm -#endif // LLVM_REDUCTIONRULES_H +#endif diff --git a/include/llvm/CodeGen/PBQP/RegAllocSolver.h b/include/llvm/CodeGen/PBQP/RegAllocSolver.h deleted file mode 100644 index 977c34843bbd..000000000000 --- a/include/llvm/CodeGen/PBQP/RegAllocSolver.h +++ /dev/null @@ -1,359 +0,0 @@ -//===-- RegAllocSolver.h - Heuristic PBQP Solver for reg alloc --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Heuristic PBQP solver for register allocation problems. This solver uses a -// graph reduction approach. Nodes of degree 0, 1 and 2 are eliminated with -// optimality-preserving rules (see ReductionRules.h). When no low-degree (<3) -// nodes are present, a heuristic derived from Brigg's graph coloring approach -// is used. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H -#define LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H - -#include "CostAllocator.h" -#include "Graph.h" -#include "ReductionRules.h" -#include "Solution.h" -#include "llvm/Support/ErrorHandling.h" -#include <limits> -#include <vector> - -namespace PBQP { - - namespace RegAlloc { - - /// \brief Metadata to speed allocatability test. - /// - /// Keeps track of the number of infinities in each row and column. - class MatrixMetadata { - private: - MatrixMetadata(const MatrixMetadata&); - void operator=(const MatrixMetadata&); - public: - MatrixMetadata(const PBQP::Matrix& M) - : WorstRow(0), WorstCol(0), - UnsafeRows(new bool[M.getRows() - 1]()), - UnsafeCols(new bool[M.getCols() - 1]()) { - - unsigned* ColCounts = new unsigned[M.getCols() - 1](); - - for (unsigned i = 1; i < M.getRows(); ++i) { - unsigned RowCount = 0; - for (unsigned j = 1; j < M.getCols(); ++j) { - if (M[i][j] == std::numeric_limits<PBQP::PBQPNum>::infinity()) { - ++RowCount; - ++ColCounts[j - 1]; - UnsafeRows[i - 1] = true; - UnsafeCols[j - 1] = true; - } - } - WorstRow = std::max(WorstRow, RowCount); - } - unsigned WorstColCountForCurRow = - *std::max_element(ColCounts, ColCounts + M.getCols() - 1); - WorstCol = std::max(WorstCol, WorstColCountForCurRow); - delete[] ColCounts; - } - - ~MatrixMetadata() { - delete[] UnsafeRows; - delete[] UnsafeCols; - } - - unsigned getWorstRow() const { return WorstRow; } - unsigned getWorstCol() const { return WorstCol; } - const bool* getUnsafeRows() const { return UnsafeRows; } - const bool* getUnsafeCols() const { return UnsafeCols; } - - private: - unsigned WorstRow, WorstCol; - bool* UnsafeRows; - bool* UnsafeCols; - }; - - class NodeMetadata { - public: - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; - - NodeMetadata() : RS(Unprocessed), DeniedOpts(0), OptUnsafeEdges(nullptr){} - ~NodeMetadata() { delete[] OptUnsafeEdges; } - - void setup(const Vector& Costs) { - NumOpts = Costs.getLength() - 1; - OptUnsafeEdges = new unsigned[NumOpts](); - } - - ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } - - void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] += UnsafeOpts[i]; - } - - void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] -= UnsafeOpts[i]; - } - - bool isConservativelyAllocatable() const { - return (DeniedOpts < NumOpts) || - (std::find(OptUnsafeEdges, OptUnsafeEdges + NumOpts, 0) != - OptUnsafeEdges + NumOpts); - } - - private: - ReductionState RS; - unsigned NumOpts; - unsigned DeniedOpts; - unsigned* OptUnsafeEdges; - }; - - class RegAllocSolverImpl { - private: - typedef PBQP::MDMatrix<MatrixMetadata> RAMatrix; - public: - typedef PBQP::Vector RawVector; - typedef PBQP::Matrix RawMatrix; - typedef PBQP::Vector Vector; - typedef RAMatrix Matrix; - typedef PBQP::PoolCostAllocator< - Vector, PBQP::VectorComparator, - Matrix, PBQP::MatrixComparator> CostAllocator; - - typedef PBQP::GraphBase::NodeId NodeId; - typedef PBQP::GraphBase::EdgeId EdgeId; - - typedef RegAlloc::NodeMetadata NodeMetadata; - - struct EdgeMetadata { }; - - typedef PBQP::Graph<RegAllocSolverImpl> Graph; - - RegAllocSolverImpl(Graph &G) : G(G) {} - - Solution solve() { - G.setSolver(*this); - Solution S; - setup(); - S = backpropagate(G, reduce()); - G.unsetSolver(); - return S; - } - - void handleAddNode(NodeId NId) { - G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); - } - void handleRemoveNode(NodeId NId) {} - void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} - - void handleAddEdge(EdgeId EId) { - handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); - handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); - } - - void handleRemoveEdge(EdgeId EId) { - handleDisconnectEdge(EId, G.getEdgeNode1Id(EId)); - handleDisconnectEdge(EId, G.getEdgeNode2Id(EId)); - } - - void handleDisconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } - } - - void handleReconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); - } - - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - - NodeId N1Id = G.getEdgeNode1Id(EId); - NodeId N2Id = G.getEdgeNode2Id(EId); - NodeMetadata& N1Md = G.getNodeMetadata(N1Id); - NodeMetadata& N2Md = G.getNodeMetadata(N2Id); - const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); - } - - private: - - void removeFromCurrentSet(NodeId NId) { - switch (G.getNodeMetadata(NId).getReductionState()) { - case NodeMetadata::Unprocessed: break; - case NodeMetadata::OptimallyReducible: - assert(OptimallyReducibleNodes.find(NId) != - OptimallyReducibleNodes.end() && - "Node not in optimally reducible set."); - OptimallyReducibleNodes.erase(NId); - break; - case NodeMetadata::ConservativelyAllocatable: - assert(ConservativelyAllocatableNodes.find(NId) != - ConservativelyAllocatableNodes.end() && - "Node not in conservatively allocatable set."); - ConservativelyAllocatableNodes.erase(NId); - break; - case NodeMetadata::NotProvablyAllocatable: - assert(NotProvablyAllocatableNodes.find(NId) != - NotProvablyAllocatableNodes.end() && - "Node not in not-provably-allocatable set."); - NotProvablyAllocatableNodes.erase(NId); - break; - } - } - - void moveToOptimallyReducibleNodes(NodeId NId) { - removeFromCurrentSet(NId); - OptimallyReducibleNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::OptimallyReducible); - } - - void moveToConservativelyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - ConservativelyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::ConservativelyAllocatable); - } - - void moveToNotProvablyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - NotProvablyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::NotProvablyAllocatable); - } - - void setup() { - // Set up worklists. - for (auto NId : G.nodeIds()) { - if (G.getNodeDegree(NId) < 3) - moveToOptimallyReducibleNodes(NId); - else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) - moveToConservativelyAllocatableNodes(NId); - else - moveToNotProvablyAllocatableNodes(NId); - } - } - - // Compute a reduction order for the graph by iteratively applying PBQP - // reduction rules. Locally optimal rules are applied whenever possible (R0, - // R1, R2). If no locally-optimal rules apply then any conservatively - // allocatable node is reduced. Finally, if no conservatively allocatable - // node exists then the node with the lowest spill-cost:degree ratio is - // selected. - std::vector<GraphBase::NodeId> reduce() { - assert(!G.empty() && "Cannot reduce empty graph."); - - typedef GraphBase::NodeId NodeId; - std::vector<NodeId> NodeStack; - - // Consume worklists. - while (true) { - if (!OptimallyReducibleNodes.empty()) { - NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); - NodeId NId = *NItr; - OptimallyReducibleNodes.erase(NItr); - NodeStack.push_back(NId); - switch (G.getNodeDegree(NId)) { - case 0: - break; - case 1: - applyR1(G, NId); - break; - case 2: - applyR2(G, NId); - break; - default: llvm_unreachable("Not an optimally reducible node."); - } - } else if (!ConservativelyAllocatableNodes.empty()) { - // Conservatively allocatable nodes will never spill. For now just - // take the first node in the set and push it on the stack. When we - // start optimizing more heavily for register preferencing, it may - // would be better to push nodes with lower 'expected' or worst-case - // register costs first (since early nodes are the most - // constrained). - NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); - NodeId NId = *NItr; - ConservativelyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - - } else if (!NotProvablyAllocatableNodes.empty()) { - NodeSet::iterator NItr = - std::min_element(NotProvablyAllocatableNodes.begin(), - NotProvablyAllocatableNodes.end(), - SpillCostComparator(G)); - NodeId NId = *NItr; - NotProvablyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - } else - break; - } - - return NodeStack; - } - - class SpillCostComparator { - public: - SpillCostComparator(const Graph& G) : G(G) {} - bool operator()(NodeId N1Id, NodeId N2Id) { - PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); - PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); - return N1SC < N2SC; - } - private: - const Graph& G; - }; - - Graph& G; - typedef std::set<NodeId> NodeSet; - NodeSet OptimallyReducibleNodes; - NodeSet ConservativelyAllocatableNodes; - NodeSet NotProvablyAllocatableNodes; - }; - - typedef Graph<RegAllocSolverImpl> Graph; - - inline Solution solve(Graph& G) { - if (G.empty()) - return Solution(); - RegAllocSolverImpl RegAllocSolver(G); - return RegAllocSolver.solve(); - } - - } -} - -#endif // LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 3556e60f3967..a3bfaeb7e6c7 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -18,6 +18,7 @@ #include "Math.h" #include <map> +namespace llvm { namespace PBQP { /// \brief Represents a solution to a PBQP problem. @@ -87,6 +88,7 @@ namespace PBQP { }; -} +} // namespace PBQP +} // namespace llvm #endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/include/llvm/CodeGen/PBQPRAConstraint.h b/include/llvm/CodeGen/PBQPRAConstraint.h new file mode 100644 index 000000000000..833b9bad613f --- /dev/null +++ b/include/llvm/CodeGen/PBQPRAConstraint.h @@ -0,0 +1,69 @@ +//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PBQPBuilder interface, for classes which build PBQP +// instances to represent register allocation problems, and the RegAllocPBQP +// interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQPRACONSTRAINT_H +#define LLVM_CODEGEN_PBQPRACONSTRAINT_H + +#include <memory> +#include <vector> + +namespace llvm { +namespace PBQP { +namespace RegAlloc { +// Forward declare PBQP graph class. +class PBQPRAGraph; +} +} + +class LiveIntervals; +class MachineBlockFrequencyInfo; +class MachineFunction; +class TargetRegisterInfo; + +typedef PBQP::RegAlloc::PBQPRAGraph PBQPRAGraph; + +/// @brief Abstract base for classes implementing PBQP register allocation +/// constraints (e.g. Spill-costs, interference, coalescing). +class PBQPRAConstraint { +public: + virtual ~PBQPRAConstraint() = 0; + virtual void apply(PBQPRAGraph &G) = 0; +private: + virtual void anchor(); +}; + +/// @brief PBQP register allocation constraint composer. +/// +/// Constraints added to this list will be applied, in the order that they are +/// added, to the PBQP graph. +class PBQPRAConstraintList : public PBQPRAConstraint { +public: + void apply(PBQPRAGraph &G) override { + for (auto &C : Constraints) + C->apply(G); + } + + void addConstraint(std::unique_ptr<PBQPRAConstraint> C) { + if (C) + Constraints.push_back(std::move(C)); + } +private: + std::vector<std::unique_ptr<PBQPRAConstraint>> Constraints; + void anchor() override; +}; + +} + +#endif /* LLVM_CODEGEN_PBQPRACONSTRAINT_H */ diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 87f55e8572fe..8ed32b8a8dd5 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -105,6 +105,7 @@ private: AnalysisID StopAfter; bool Started; bool Stopped; + bool AddingMachinePasses; protected: TargetMachine *TM; @@ -178,6 +179,10 @@ public: /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; + /// Return true if the default global register allocator is in use and + /// has not be overriden on the command line with '-regalloc=...' + bool usingDefaultRegAlloc() const; + /// Add common target configurable passes that perform LLVM IR to IR /// transforms following machine independent optimization. virtual void addIRPasses(); @@ -255,12 +260,9 @@ protected: return false; } - /// addPreRegAlloc - This method may be implemented by targets that want to - /// run passes immediately before register allocation. This should return - /// true if -print-machineinstrs should print after these passes. - virtual bool addPreRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. @@ -286,24 +288,16 @@ protected: return false; } - /// addPostRegAlloc - This method may be implemented by targets that want to - /// run passes after register allocation pass pipeline but before - /// prolog-epilog insertion. This should return true if -print-machineinstrs - /// should print after these passes. - virtual bool addPostRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); - /// addPreSched2 - This method may be implemented by targets that want to - /// run passes after prolog-epilog insertion and before the second instruction - /// scheduling pass. This should return true if -print-machineinstrs should - /// print after these passes. - virtual bool addPreSched2() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after @@ -313,24 +307,30 @@ protected: /// Add standard basic block placement passes. virtual void addBlockPlacement(); - /// addPreEmitPass - This pass may be implemented by targets that want to run - /// passes immediately before machine code is emitted. This should return - /// true if -print-machineinstrs should print out the code after the passes. - virtual bool addPreEmitPass() { - return false; - } + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - void addPass(Pass *P); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -339,13 +339,20 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner); + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); }; } // namespace llvm /// List of target independent CodeGen pass IDs. namespace llvm { - FunctionPass *createAtomicExpandLoadLinkedPass(const TargetMachine *TM); + FunctionPass *createAtomicExpandPass(const TargetMachine *TM); /// \brief Create a basic TargetTransformInfo analysis pass. /// @@ -372,8 +379,9 @@ namespace llvm { /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); - /// AtomicExpandLoadLinkedID -- FIXME - extern char &AtomicExpandLoadLinkedID; + /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg + /// load-linked/store-conditional loops. + extern char &AtomicExpandID; /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; @@ -489,6 +497,10 @@ namespace llvm { /// inserting cmov instructions. extern char &EarlyIfConverterID; + /// This pass performs instruction combining using trace metrics to estimate + /// critical-path and resource depth. + extern char &MachineCombinerID; + /// StackSlotColoring - This pass performs stack coloring and merging. /// It merges disjoint allocas to reduce the stack size. extern char &StackColoringID; @@ -551,7 +563,7 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); + FunctionPass *createMachineVerifierPass(const std::string& Banner); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. @@ -593,6 +605,10 @@ namespace llvm { /// createJumpInstrTables - This pass creates jump-instruction tables. ModulePass *createJumpInstrTablesPass(); + + /// createForwardControlFlowIntegrityPass - This pass adds control-flow + /// integrity. + ModulePass *createForwardControlFlowIntegrityPass(); } // End llvm namespace /// This initializer registers TargetMachine constructor, so the pass being diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 441b0f084e69..eceb790c547d 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -16,150 +16,505 @@ #ifndef LLVM_CODEGEN_REGALLOCPBQP_H #define LLVM_CODEGEN_REGALLOCPBQP_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQP/RegAllocSolver.h" -#include <map> -#include <set> +#include "llvm/CodeGen/PBQP/CostAllocator.h" +#include "llvm/CodeGen/PBQP/ReductionRules.h" +#include "llvm/CodeGen/PBQPRAConstraint.h" +#include "llvm/Support/ErrorHandling.h" namespace llvm { - - class LiveIntervals; - class MachineBlockFrequencyInfo; - class MachineFunction; - class TargetRegisterInfo; - - typedef PBQP::RegAlloc::Graph PBQPRAGraph; - - /// This class wraps up a PBQP instance representing a register allocation - /// problem, plus the structures necessary to map back from the PBQP solution - /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map, - /// and the PBQP option <--> storage location map). - class PBQPRAProblem { - public: - - typedef SmallVector<unsigned, 16> AllowedSet; - - PBQPRAGraph& getGraph() { return graph; } - - const PBQPRAGraph& getGraph() const { return graph; } - - /// Record the mapping between the given virtual register and PBQP node, - /// and the set of allowed pregs for the vreg. - /// - /// If you are extending - /// PBQPBuilder you are unlikely to need this: Nodes and options for all - /// vregs will already have been set up for you by the base class. - template <typename AllowedRegsItr> - void recordVReg(unsigned vreg, PBQPRAGraph::NodeId nodeId, - AllowedRegsItr arBegin, AllowedRegsItr arEnd) { - assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node."); - assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); - assert(allowedSets[vreg].empty() && "vreg already has pregs."); - - node2VReg[nodeId] = vreg; - vreg2Node[vreg] = nodeId; - std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); +namespace PBQP { +namespace RegAlloc { + +/// @brief Spill option index. +inline unsigned getSpillOptionIdx() { return 0; } + +/// \brief Metadata to speed allocatability test. +/// +/// Keeps track of the number of infinities in each row and column. +class MatrixMetadata { +private: + MatrixMetadata(const MatrixMetadata&); + void operator=(const MatrixMetadata&); +public: + MatrixMetadata(const Matrix& M) + : WorstRow(0), WorstCol(0), + UnsafeRows(new bool[M.getRows() - 1]()), + UnsafeCols(new bool[M.getCols() - 1]()) { + + unsigned* ColCounts = new unsigned[M.getCols() - 1](); + + for (unsigned i = 1; i < M.getRows(); ++i) { + unsigned RowCount = 0; + for (unsigned j = 1; j < M.getCols(); ++j) { + if (M[i][j] == std::numeric_limits<PBQPNum>::infinity()) { + ++RowCount; + ++ColCounts[j - 1]; + UnsafeRows[i - 1] = true; + UnsafeCols[j - 1] = true; + } + } + WorstRow = std::max(WorstRow, RowCount); } + unsigned WorstColCountForCurRow = + *std::max_element(ColCounts, ColCounts + M.getCols() - 1); + WorstCol = std::max(WorstCol, WorstColCountForCurRow); + delete[] ColCounts; + } + + unsigned getWorstRow() const { return WorstRow; } + unsigned getWorstCol() const { return WorstCol; } + const bool* getUnsafeRows() const { return UnsafeRows.get(); } + const bool* getUnsafeCols() const { return UnsafeCols.get(); } + +private: + unsigned WorstRow, WorstCol; + std::unique_ptr<bool[]> UnsafeRows; + std::unique_ptr<bool[]> UnsafeCols; +}; + +/// \brief Holds a vector of the allowed physical regs for a vreg. +class AllowedRegVector { + friend hash_code hash_value(const AllowedRegVector &); +public: + + AllowedRegVector() : NumOpts(0), Opts(nullptr) {} + + AllowedRegVector(const std::vector<unsigned> &OptVec) + : NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) { + std::copy(OptVec.begin(), OptVec.end(), Opts.get()); + } + + AllowedRegVector(const AllowedRegVector &Other) + : NumOpts(Other.NumOpts), Opts(new unsigned[NumOpts]) { + std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get()); + } + + AllowedRegVector(AllowedRegVector &&Other) + : NumOpts(std::move(Other.NumOpts)), Opts(std::move(Other.Opts)) {} + + AllowedRegVector& operator=(const AllowedRegVector &Other) { + NumOpts = Other.NumOpts; + Opts.reset(new unsigned[NumOpts]); + std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get()); + return *this; + } + + AllowedRegVector& operator=(AllowedRegVector &&Other) { + NumOpts = std::move(Other.NumOpts); + Opts = std::move(Other.Opts); + return *this; + } + + unsigned size() const { return NumOpts; } + unsigned operator[](size_t I) const { return Opts[I]; } + + bool operator==(const AllowedRegVector &Other) const { + if (NumOpts != Other.NumOpts) + return false; + return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get()); + } + + bool operator!=(const AllowedRegVector &Other) const { + return !(*this == Other); + } + +private: + unsigned NumOpts; + std::unique_ptr<unsigned[]> Opts; +}; + +inline hash_code hash_value(const AllowedRegVector &OptRegs) { + unsigned *OStart = OptRegs.Opts.get(); + unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts; + return hash_combine(OptRegs.NumOpts, + hash_combine_range(OStart, OEnd)); +} - /// Get the virtual register corresponding to the given PBQP node. - unsigned getVRegForNode(PBQPRAGraph::NodeId nodeId) const; - - /// Get the PBQP node corresponding to the given virtual register. - PBQPRAGraph::NodeId getNodeForVReg(unsigned vreg) const; - - /// Returns true if the given PBQP option represents a physical register, - /// false otherwise. - bool isPRegOption(unsigned vreg, unsigned option) const { - // At present we only have spills or pregs, so anything that's not a - // spill is a preg. (This might be extended one day to support remat). - return !isSpillOption(vreg, option); +/// \brief Holds graph-level metadata relevent to PBQP RA problems. +class GraphMetadata { +private: + typedef ValuePool<AllowedRegVector> AllowedRegVecPool; +public: + + typedef AllowedRegVecPool::PoolRef AllowedRegVecRef; + + GraphMetadata(MachineFunction &MF, + LiveIntervals &LIS, + MachineBlockFrequencyInfo &MBFI) + : MF(MF), LIS(LIS), MBFI(MBFI) {} + + MachineFunction &MF; + LiveIntervals &LIS; + MachineBlockFrequencyInfo &MBFI; + + void setNodeIdForVReg(unsigned VReg, GraphBase::NodeId NId) { + VRegToNodeId[VReg] = NId; + } + + GraphBase::NodeId getNodeIdForVReg(unsigned VReg) const { + auto VRegItr = VRegToNodeId.find(VReg); + if (VRegItr == VRegToNodeId.end()) + return GraphBase::invalidNodeId(); + return VRegItr->second; + } + + void eraseNodeIdForVReg(unsigned VReg) { + VRegToNodeId.erase(VReg); + } + + AllowedRegVecRef getAllowedRegs(AllowedRegVector Allowed) { + return AllowedRegVecs.getValue(std::move(Allowed)); + } + +private: + DenseMap<unsigned, GraphBase::NodeId> VRegToNodeId; + AllowedRegVecPool AllowedRegVecs; +}; + +/// \brief Holds solver state and other metadata relevant to each PBQP RA node. +class NodeMetadata { +public: + typedef RegAlloc::AllowedRegVector AllowedRegVector; + + typedef enum { Unprocessed, + OptimallyReducible, + ConservativelyAllocatable, + NotProvablyAllocatable } ReductionState; + + NodeMetadata() + : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), + VReg(0) {} + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata(const NodeMetadata &Other) + : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), + OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), + AllowedRegs(Other.AllowedRegs) { + if (NumOpts > 0) { + std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], + &OptUnsafeEdges[0]); } - - /// Returns true if the given PBQP option represents spilling, false - /// otherwise. - bool isSpillOption(unsigned vreg, unsigned option) const { - // We hardcode option zero as the spill option. - return option == 0; + } + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata(NodeMetadata &&Other) + : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), + OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), + AllowedRegs(std::move(Other.AllowedRegs)) {} + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata& operator=(const NodeMetadata &Other) { + RS = Other.RS; + NumOpts = Other.NumOpts; + DeniedOpts = Other.DeniedOpts; + OptUnsafeEdges.reset(new unsigned[NumOpts]); + std::copy(Other.OptUnsafeEdges.get(), Other.OptUnsafeEdges.get() + NumOpts, + OptUnsafeEdges.get()); + VReg = Other.VReg; + AllowedRegs = Other.AllowedRegs; + return *this; + } + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata& operator=(NodeMetadata &&Other) { + RS = Other.RS; + NumOpts = Other.NumOpts; + DeniedOpts = Other.DeniedOpts; + OptUnsafeEdges = std::move(Other.OptUnsafeEdges); + VReg = Other.VReg; + AllowedRegs = std::move(Other.AllowedRegs); + return *this; + } + + void setVReg(unsigned VReg) { this->VReg = VReg; } + unsigned getVReg() const { return VReg; } + + void setAllowedRegs(GraphMetadata::AllowedRegVecRef AllowedRegs) { + this->AllowedRegs = std::move(AllowedRegs); + } + const AllowedRegVector& getAllowedRegs() const { return *AllowedRegs; } + + void setup(const Vector& Costs) { + NumOpts = Costs.getLength() - 1; + OptUnsafeEdges = std::unique_ptr<unsigned[]>(new unsigned[NumOpts]()); + } + + ReductionState getReductionState() const { return RS; } + void setReductionState(ReductionState RS) { this->RS = RS; } + + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] += UnsafeOpts[i]; + } + + void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] -= UnsafeOpts[i]; + } + + bool isConservativelyAllocatable() const { + return (DeniedOpts < NumOpts) || + (std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) != + &OptUnsafeEdges[NumOpts]); + } + +private: + ReductionState RS; + unsigned NumOpts; + unsigned DeniedOpts; + std::unique_ptr<unsigned[]> OptUnsafeEdges; + unsigned VReg; + GraphMetadata::AllowedRegVecRef AllowedRegs; +}; + +class RegAllocSolverImpl { +private: + typedef MDMatrix<MatrixMetadata> RAMatrix; +public: + typedef PBQP::Vector RawVector; + typedef PBQP::Matrix RawMatrix; + typedef PBQP::Vector Vector; + typedef RAMatrix Matrix; + typedef PBQP::PoolCostAllocator<Vector, Matrix> CostAllocator; + + typedef GraphBase::NodeId NodeId; + typedef GraphBase::EdgeId EdgeId; + + typedef RegAlloc::NodeMetadata NodeMetadata; + struct EdgeMetadata { }; + typedef RegAlloc::GraphMetadata GraphMetadata; + + typedef PBQP::Graph<RegAllocSolverImpl> Graph; + + RegAllocSolverImpl(Graph &G) : G(G) {} + + Solution solve() { + G.setSolver(*this); + Solution S; + setup(); + S = backpropagate(G, reduce()); + G.unsetSolver(); + return S; + } + + void handleAddNode(NodeId NId) { + G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); + } + void handleRemoveNode(NodeId NId) {} + void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} + + void handleAddEdge(EdgeId EId) { + handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleRemoveEdge(EdgeId EId) { + handleDisconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleDisconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleDisconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + + void handleReconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); + } + + void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { + handleRemoveEdge(EId); + + NodeId N1Id = G.getEdgeNode1Id(EId); + NodeId N2Id = G.getEdgeNode2Id(EId); + NodeMetadata& N1Md = G.getNodeMetadata(N1Id); + NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + const MatrixMetadata& MMd = NewCosts.getMetadata(); + N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); + N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + } + +private: + + void removeFromCurrentSet(NodeId NId) { + switch (G.getNodeMetadata(NId).getReductionState()) { + case NodeMetadata::Unprocessed: break; + case NodeMetadata::OptimallyReducible: + assert(OptimallyReducibleNodes.find(NId) != + OptimallyReducibleNodes.end() && + "Node not in optimally reducible set."); + OptimallyReducibleNodes.erase(NId); + break; + case NodeMetadata::ConservativelyAllocatable: + assert(ConservativelyAllocatableNodes.find(NId) != + ConservativelyAllocatableNodes.end() && + "Node not in conservatively allocatable set."); + ConservativelyAllocatableNodes.erase(NId); + break; + case NodeMetadata::NotProvablyAllocatable: + assert(NotProvablyAllocatableNodes.find(NId) != + NotProvablyAllocatableNodes.end() && + "Node not in not-provably-allocatable set."); + NotProvablyAllocatableNodes.erase(NId); + break; + } + } + + void moveToOptimallyReducibleNodes(NodeId NId) { + removeFromCurrentSet(NId); + OptimallyReducibleNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::OptimallyReducible); + } + + void moveToConservativelyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + ConservativelyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::ConservativelyAllocatable); + } + + void moveToNotProvablyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + NotProvablyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::NotProvablyAllocatable); + } + + void setup() { + // Set up worklists. + for (auto NId : G.nodeIds()) { + if (G.getNodeDegree(NId) < 3) + moveToOptimallyReducibleNodes(NId); + else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) + moveToConservativelyAllocatableNodes(NId); + else + moveToNotProvablyAllocatableNodes(NId); + } + } + + // Compute a reduction order for the graph by iteratively applying PBQP + // reduction rules. Locally optimal rules are applied whenever possible (R0, + // R1, R2). If no locally-optimal rules apply then any conservatively + // allocatable node is reduced. Finally, if no conservatively allocatable + // node exists then the node with the lowest spill-cost:degree ratio is + // selected. + std::vector<GraphBase::NodeId> reduce() { + assert(!G.empty() && "Cannot reduce empty graph."); + + typedef GraphBase::NodeId NodeId; + std::vector<NodeId> NodeStack; + + // Consume worklists. + while (true) { + if (!OptimallyReducibleNodes.empty()) { + NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); + NodeId NId = *NItr; + OptimallyReducibleNodes.erase(NItr); + NodeStack.push_back(NId); + switch (G.getNodeDegree(NId)) { + case 0: + break; + case 1: + applyR1(G, NId); + break; + case 2: + applyR2(G, NId); + break; + default: llvm_unreachable("Not an optimally reducible node."); + } + } else if (!ConservativelyAllocatableNodes.empty()) { + // Conservatively allocatable nodes will never spill. For now just + // take the first node in the set and push it on the stack. When we + // start optimizing more heavily for register preferencing, it may + // would be better to push nodes with lower 'expected' or worst-case + // register costs first (since early nodes are the most + // constrained). + NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); + NodeId NId = *NItr; + ConservativelyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + + } else if (!NotProvablyAllocatableNodes.empty()) { + NodeSet::iterator NItr = + std::min_element(NotProvablyAllocatableNodes.begin(), + NotProvablyAllocatableNodes.end(), + SpillCostComparator(G)); + NodeId NId = *NItr; + NotProvablyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + } else + break; } - /// Returns the allowed set for the given virtual register. - const AllowedSet& getAllowedSet(unsigned vreg) const; - - /// Get PReg for option. - unsigned getPRegForOption(unsigned vreg, unsigned option) const; - - private: - - typedef std::map<PBQPRAGraph::NodeId, unsigned> Node2VReg; - typedef DenseMap<unsigned, PBQPRAGraph::NodeId> VReg2Node; - typedef DenseMap<unsigned, AllowedSet> AllowedSetMap; - - PBQPRAGraph graph; - Node2VReg node2VReg; - VReg2Node vreg2Node; - - AllowedSetMap allowedSets; - - }; + return NodeStack; + } - /// Builds PBQP instances to represent register allocation problems. Includes - /// spill, interference and coalescing costs by default. You can extend this - /// class to support additional constraints for your architecture. - class PBQPBuilder { - private: - PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION; - void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION; + class SpillCostComparator { public: - - typedef std::set<unsigned> RegSet; - - /// Default constructor. - PBQPBuilder() {} - - /// Clean up a PBQPBuilder. - virtual ~PBQPBuilder() {} - - /// Build a PBQP instance to represent the register allocation problem for - /// the given MachineFunction. - virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineBlockFrequencyInfo *mbfi, - const RegSet &vregs); + SpillCostComparator(const Graph& G) : G(G) {} + bool operator()(NodeId N1Id, NodeId N2Id) { + PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); + PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); + return N1SC < N2SC; + } private: - - void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost); - - void addInterferenceCosts(PBQP::Matrix &costMat, - const PBQPRAProblem::AllowedSet &vr1Allowed, - const PBQPRAProblem::AllowedSet &vr2Allowed, - const TargetRegisterInfo *tri); + const Graph& G; }; - /// Extended builder which adds coalescing constraints to a problem. - class PBQPBuilderWithCoalescing : public PBQPBuilder { - public: - - /// Build a PBQP instance to represent the register allocation problem for - /// the given MachineFunction. - PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineBlockFrequencyInfo *mbfi, - const RegSet &vregs) override; - - private: + Graph& G; + typedef std::set<NodeId> NodeSet; + NodeSet OptimallyReducibleNodes; + NodeSet ConservativelyAllocatableNodes; + NodeSet NotProvablyAllocatableNodes; +}; + +class PBQPRAGraph : public PBQP::Graph<RegAllocSolverImpl> { +private: + typedef PBQP::Graph<RegAllocSolverImpl> BaseT; +public: + PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} +}; + +inline Solution solve(PBQPRAGraph& G) { + if (G.empty()) + return Solution(); + RegAllocSolverImpl RegAllocSolver(G); + return RegAllocSolver.solve(); +} - void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption, - PBQP::PBQPNum benefit); +} // namespace RegAlloc +} // namespace PBQP - void addVirtRegCoalesce(PBQP::Matrix &costMat, - const PBQPRAProblem::AllowedSet &vr1Allowed, - const PBQPRAProblem::AllowedSet &vr2Allowed, - PBQP::PBQPNum benefit); - }; +/// @brief Create a PBQP register allocator instance. +FunctionPass * +createPBQPRegisterAllocator(char *customPassID = nullptr); - FunctionPass * - createPBQPRegisterAllocator(std::unique_ptr<PBQPBuilder> builder, - char *customPassID = nullptr); -} +} // namespace llvm #endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 335dd7f084c1..474861e45df1 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -34,7 +34,7 @@ class RegScavenger { MachineRegisterInfo* MRI; MachineBasicBlock *MBB; MachineBasicBlock::iterator MBBI; - unsigned NumPhysRegs; + unsigned NumRegUnits; /// Tracking - True if RegScavenger is currently tracking the liveness of /// registers. @@ -58,22 +58,19 @@ class RegScavenger { /// A vector of information on scavenged registers. SmallVector<ScavengedInfo, 2> Scavenged; - /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. - /// - BitVector CalleeSavedRegs; - - /// RegsAvailable - The current state of all the physical registers immediately - /// before MBBI. One bit per physical register. If bit is set that means it's - /// available, unset means the register is currently being used. - BitVector RegsAvailable; + /// RegUnitsAvailable - The current state of each reg unit immediatelly + /// before MBBI. One bit per register unit. If bit is not set it means any + /// register containing that register unit is currently being used. + BitVector RegUnitsAvailable; // These BitVectors are only used internally to forward(). They are members // to avoid frequent reallocations. - BitVector KillRegs, DefRegs; + BitVector KillRegUnits, DefRegUnits; + BitVector TmpRegUnits; public: RegScavenger() - : MBB(nullptr), NumPhysRegs(0), Tracking(false) {} + : MBB(nullptr), NumRegUnits(0), Tracking(false) {} /// enterBasicBlock - Start tracking liveness from the begin of the specific /// basic block. @@ -112,9 +109,9 @@ public: MachineBasicBlock::iterator getCurrentPosition() const { return MBBI; } - - /// getRegsUsed - return all registers currently in use in used. - void getRegsUsed(BitVector &used, bool includeReserved); + + /// isRegUsed - return if a specific register is currently used. + bool isRegUsed(unsigned Reg, bool includeReserved = true) const; /// getRegsAvailable - Return all available registers in the register class /// in Mask. @@ -157,40 +154,29 @@ public: return scavengeRegister(RegClass, MBBI, SPAdj); } - /// setUsed - Tell the scavenger a register is used. + /// setRegUsed - Tell the scavenger a register is used. /// - void setUsed(unsigned Reg); + void setRegUsed(unsigned Reg); private: /// isReserved - Returns true if a register is reserved. It is never "unused". bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } - /// isUsed - Test if a register is currently being used. When called by the - /// isAliasUsed function, we only check isReserved if this is the original - /// register, not an alias register. + /// setUsed / setUnused - Mark the state of one or a number of register units. /// - bool isUsed(unsigned Reg, bool CheckReserved = true) const { - return !RegsAvailable.test(Reg) || (CheckReserved && isReserved(Reg)); + void setUsed(BitVector &RegUnits) { + RegUnitsAvailable.reset(RegUnits); } - - /// isAliasUsed - Is Reg or an alias currently in use? - bool isAliasUsed(unsigned Reg) const; - - /// setUsed / setUnused - Mark the state of one or a number of registers. - /// - void setUsed(BitVector &Regs) { - RegsAvailable.reset(Regs); - } - void setUnused(BitVector &Regs) { - RegsAvailable |= Regs; + void setUnused(BitVector &RegUnits) { + RegUnitsAvailable |= RegUnits; } - /// Processes the current instruction and fill the KillRegs and DefRegs bit - /// vectors. + /// Processes the current instruction and fill the KillRegUnits and + /// DefRegUnits bit vectors. void determineKillsAndDefs(); - - /// Add Reg and all its sub-registers to BV. - void addRegWithSubRegs(BitVector &BV, unsigned Reg); - + + /// Add all Reg Units that Reg contains to BV. + void addRegUnits(BitVector &BV, unsigned Reg); + /// findSurvivorReg - Return the candidate register that is unused for the /// longest after StartMI. UseMI is set to the instruction where the search /// stopped. diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 81db8a2f79b5..64c9c4729e92 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -203,6 +203,16 @@ namespace RTLIB { COPYSIGN_F80, COPYSIGN_F128, COPYSIGN_PPCF128, + FMIN_F32, + FMIN_F64, + FMIN_F80, + FMIN_F128, + FMIN_PPCF128, + FMAX_F32, + FMAX_F64, + FMAX_F80, + FMAX_F128, + FMAX_PPCF128, // CONVERSION FPEXT_F64_F128, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 5a65d590802a..80aee8c62880 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -190,6 +190,12 @@ namespace llvm { return getKind() == Order && Contents.OrdKind == Barrier; } + /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory + /// dependence. + bool isNormalMemoryOrBarrier() const { + return (isNormalMemory() || isBarrier()); + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index e6754a2c0342..00dd8f9a633e 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -75,8 +75,7 @@ namespace llvm { /// MachineInstrs. class ScheduleDAGInstrs : public ScheduleDAG { protected: - const MachineLoopInfo &MLI; - const MachineDominatorTree &MDT; + const MachineLoopInfo *MLI; const MachineFrameInfo *MFI; /// Live Intervals provides reaching defs in preRA scheduling. @@ -154,8 +153,7 @@ namespace llvm { public: explicit ScheduleDAGInstrs(MachineFunction &mf, - const MachineLoopInfo &mli, - const MachineDominatorTree &mdt, + const MachineLoopInfo *mli, bool IsPostRAFlag, bool RemoveKillFlags = false, LiveIntervals *LIS = nullptr); diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index bb87f82d2def..4950797bb1e0 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -16,9 +16,11 @@ #define LLVM_CODEGEN_SELECTIONDAG_H #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/DAGCombine.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Support/RecyclingAllocator.h" #include "llvm/Target/TargetMachine.h" @@ -126,6 +128,10 @@ public: DbgValMap[Node].push_back(V); } + /// \brief Invalidate all DbgValues attached to the node and remove + /// it from the Node-to-DbgValues map. + void erase(const SDNode *Node); + void clear() { DbgValMap.clear(); DbgValues.clear(); @@ -166,7 +172,7 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false); /// class SelectionDAG { const TargetMachine &TM; - const TargetSelectionDAGInfo &TSI; + const TargetSelectionDAGInfo *TSI; const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; @@ -266,7 +272,7 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetLowering *TLI); + void init(MachineFunction &mf); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -275,8 +281,9 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } + const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } - const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } + const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. @@ -364,6 +371,27 @@ public: /// the graph. void Legalize(); + /// \brief Transforms a SelectionDAG node and any operands to it into a node + /// that is compatible with the target instruction selector, as indicated by + /// the TargetLowering object. + /// + /// \returns true if \c N is a valid, legal node after calling this. + /// + /// This essentially runs a single recursive walk of the \c Legalize process + /// over the given node (and its operands). This can be used to incrementally + /// legalize the DAG. All of the nodes which are directly replaced, + /// potentially including N, are added to the output parameter \c + /// UpdatedNodes so that the delta to the DAG can be understood by the + /// caller. + /// + /// When this returns false, N has been legalized in a way that make the + /// pointer passed in no longer valid. It may have even been deleted from the + /// DAG, and so it shouldn't be used further. When this returns true, the + /// N passed in is a legal node, and can be immediately processed as such. + /// This may still have done some work on the DAG, and will still populate + /// UpdatedNodes with any new nodes replacing those originally in the DAG. + bool LegalizeOp(SDNode *N, SmallSetVector<SDNode *, 16> &UpdatedNodes); + /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG /// that only uses vector math operations supported by the target. This is /// necessary as a separate step from Legalize because unrolling a vector @@ -725,7 +753,7 @@ public: SDValue SV, unsigned Align); /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two - /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces a the value loaded and a + /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, /// a success flag (initially i1), and a chain. SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, @@ -778,7 +806,8 @@ public: ArrayRef<SDValue> Ops, EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, - bool ReadMem = true, bool WriteMem = true); + bool ReadMem = true, bool WriteMem = true, + unsigned Size = 0); SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, ArrayRef<SDValue> Ops, @@ -793,15 +822,15 @@ public: SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, - bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + bool isNonTemporal, bool isInvariant, unsigned Alignment, + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO); @@ -812,7 +841,7 @@ public: SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, - unsigned Alignment, const MDNode *TBAAInfo = nullptr, + unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, SDLoc dl, @@ -824,19 +853,23 @@ public: SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); + SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + SDValue Mask, SDValue Src0, MachineMemOperand *MMO); + SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, + SDValue Ptr, SDValue Mask, MachineMemOperand *MMO); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); @@ -959,15 +992,18 @@ public: /// getDbgValue - Creates a SDDbgValue node. /// - SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, - bool IsIndirect, uint64_t Off, - DebugLoc DL, unsigned O); - /// Constant. - SDDbgValue *getConstantDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, - DebugLoc DL, unsigned O); - /// Frame index. - SDDbgValue *getFrameIndexDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, - DebugLoc DL, unsigned O); + /// SDNode + SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, + bool IsIndirect, uint64_t Off, DebugLoc DL, + unsigned O); + + /// Constant + SDDbgValue *getConstantDbgValue(MDNode *Var, MDNode *Expr, const Value *C, + uint64_t Off, DebugLoc DL, unsigned O); + + /// FrameIndex + SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI, + uint64_t Off, DebugLoc DL, unsigned O); /// RemoveDeadNode - Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener @@ -1039,7 +1075,10 @@ public: case ISD::SADDO: case ISD::UADDO: case ISD::ADDC: - case ISD::ADDE: return true; + case ISD::ADDE: + case ISD::FMINNUM: + case ISD::FMAXNUM: + return true; default: return false; } } @@ -1198,6 +1237,7 @@ public: unsigned getEVTAlignment(EVT MemoryVT) const; private: + void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 520be402cfc5..d53e66da5a71 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -19,6 +19,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/BasicBlock.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { class FastISel; @@ -50,15 +51,16 @@ public: AliasAnalysis *AA; GCFunctionInfo *GFI; CodeGenOpt::Level OptLevel; + const TargetInstrInfo *TII; + const TargetLowering *TLI; + static char ID; explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - const TargetLowering *getTargetLowering() const { - return TM.getTargetLowering(); - } + const TargetLowering *getTargetLowering() const { return TLI; } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -238,6 +240,12 @@ public: const unsigned char *MatcherTable, unsigned TableSize); + /// \brief Return true if complex patterns for this target can mutate the + /// DAG. + virtual bool ComplexPatternFuncMutatesDAG() const { + return false; + } + private: // Calls to these functions are generated by tblgen. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 223151105b0d..8e7fd547626c 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,7 +19,6 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" @@ -117,11 +117,13 @@ namespace ISD { /// of information is represented with the SDValue value type. /// class SDValue { + friend struct DenseMapInfo<SDValue>; + SDNode *Node; // The node defining the value we are using. unsigned ResNo; // Which return value of the node we are using. public: SDValue() : Node(nullptr), ResNo(0) {} - SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {} + SDValue(SDNode *node, unsigned resno); /// get the index which selects a specific result in the SDNode unsigned getResNo() const { return ResNo; } @@ -208,10 +210,14 @@ public: template<> struct DenseMapInfo<SDValue> { static inline SDValue getEmptyKey() { - return SDValue((SDNode*)-1, -1U); + SDValue V; + V.ResNo = -1U; + return V; } static inline SDValue getTombstoneKey() { - return SDValue((SDNode*)-1, 0); + SDValue V; + V.ResNo = -2U; + return V; } static unsigned getHashValue(const SDValue &Val) { return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ @@ -411,6 +417,16 @@ public: return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; } + /// Test if this node is a memory intrinsic (with valid pointer information). + /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for + /// non-memory intrinsics (with chains) that are not really instances of + /// MemSDNode. For such nodes, we need some extra state to determine the + /// proper classof relationship. + bool isMemIntrinsic() const { + return (NodeType == ISD::INTRINSIC_W_CHAIN || + NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1); + } + /// isMachineOpcode - Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } @@ -578,7 +594,7 @@ public: /// changes. /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, - SmallPtrSet<const SDNode *, 32> &Visited, + SmallPtrSetImpl<const SDNode *> &Visited, SmallVectorImpl<const SDNode *> &Worklist) const; /// getNumOperands - Return the number of values used by this operation. @@ -746,7 +762,13 @@ protected: ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), NumValues(VTs.NumVTs), debugLoc(dl), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + assert(NumOperands == Ops.size() && + "NumOperands wasn't wide enough for its operands!"); + assert(NumValues == VTs.NumVTs && + "NumValues wasn't wide enough for its operands!"); for (unsigned i = 0; i != Ops.size(); ++i) { + assert(OperandList && "no operands available"); OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -759,7 +781,11 @@ protected: : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) {} + IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + assert(NumValues == VTs.NumVTs && + "NumValues wasn't wide enough for its operands!"); + } /// InitOperands - Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { @@ -818,6 +844,8 @@ protected: Ops[i].setInitial(Vals[i]); } NumOperands = N; + assert(NumOperands == N && + "NumOperands wasn't wide enough for its operands!"); OperandList = Ops; checkForCycles(this); } @@ -877,6 +905,13 @@ public: // Define inline functions from the SDValue class. +inline SDValue::SDValue(SDNode *node, unsigned resno) + : Node(node), ResNo(resno) { + assert((!Node || ResNo < Node->getNumValues()) && + "Invalid result number for the given node!"); + assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps."); +} + inline unsigned SDValue::getOpcode() const { return Node->getOpcode(); } @@ -1088,8 +1123,8 @@ public: // Returns the offset from the location of the access. int64_t getSrcValueOffset() const { return MMO->getOffset(); } - /// Returns the TBAAInfo that describes the dereference. - const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); } + /// Returns the AA info that describes the dereference. + AAMDNodes getAAInfo() const { return MMO->getAAInfo(); } /// Returns the Ranges that describes the dereference. const MDNode *getRanges() const { return MMO->getRanges(); } @@ -1145,6 +1180,9 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || + N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE || + N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } }; @@ -1273,14 +1311,14 @@ public: ArrayRef<SDValue> Ops, EVT MemoryVT, MachineMemOperand *MMO) : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) { + SubclassData |= 1u << 13; } // Methods to support isa and dyn_cast static bool classof(const SDNode *N) { // We lower some target intrinsics to their target opcode // early a node with a target opcode can be of this class - return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || - N->getOpcode() == ISD::INTRINSIC_VOID || + return N->isMemIntrinsic() || N->getOpcode() == ISD::PREFETCH || N->isTargetMemoryOpcode(); } @@ -1380,6 +1418,12 @@ public: /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } + /// isInfinity - Return true if the value is an infinity + bool isInfinity() const { return Value->isInfinity(); } + + /// isNegative - Return true if the value is negative. + bool isNegative() const { return Value->isNegative(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1893,6 +1937,72 @@ public: } }; +/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and +/// MSTORE nodes +/// +class MaskedLoadStoreSDNode : public MemSDNode { + // Operands + SDUse Ops[4]; +public: + friend class SelectionDAG; + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + InitOperands(Ops, Operands, numOperands); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value + // MaskedStoreSDNode (Chain, ptr, mask, data) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE; + } +}; + +/// MaskedLoadSDNode - This class is used to represent an MLOAD node +/// +class MaskedLoadSDNode : public MaskedLoadStoreSDNode { +public: + friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) + {} + + const SDValue &getSrc0() const { return getOperand(3); } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD; + } +}; + +/// MaskedStoreSDNode - This class is used to represent an MSTORE node +/// +class MaskedStoreSDNode : public MaskedLoadStoreSDNode { + +public: + friend class SelectionDAG; + MaskedStoreSDNode(unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) + {} + + const SDValue &getData() const { return getOperand(3); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSTORE; + } +}; + /// MachineSDNode - An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h index 6f0754616206..f67a6e95191d 100644 --- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h +++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H -#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H +#ifndef LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H +#define LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -61,4 +61,4 @@ private: } // llvm namespace -#endif // LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H +#endif diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 5eddbb65259e..4e48afe14004 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_STACKMAPS -#define LLVM_STACKMAPS +#ifndef LLVM_CODEGEN_STACKMAPS_H +#define LLVM_CODEGEN_STACKMAPS_H #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" @@ -81,6 +81,52 @@ public: unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; +/// MI-level Statepoint operands +/// +/// Statepoint operands take the form: +/// <num call arguments>, <call target>, [call arguments], +/// <StackMaps::ConstantOp>, <flags>, +/// <StackMaps::ConstantOp>, <num other args>, [other args], +/// [gc values] +class StatepointOpers { +private: + enum { + NCallArgsPos = 0, + CallTargetPos = 1 + }; + +public: + explicit StatepointOpers(const MachineInstr *MI): + MI(MI) { } + + /// Get starting index of non call related arguments + /// (statepoint flags, vm state and gc state). + unsigned getVarIdx() const { + return MI->getOperand(NCallArgsPos).getImm() + 2; + } + + /// Returns the index of the operand containing the number of non-gc non-call + /// arguments. + unsigned getNumVMSArgsIdx() const { + return getVarIdx() + 3; + } + + /// Returns the number of non-gc non-call arguments attached to the + /// statepoint. Note that this is the number of arguments, not the number of + /// operands required to represent those arguments. + unsigned getNumVMSArgs() const { + return MI->getOperand(getNumVMSArgsIdx()).getImm(); + } + + /// Returns the target of the underlying call. + const MachineOperand &getCallTarget() const { + return MI->getOperand(CallTargetPos); + } + +private: + const MachineInstr *MI; +}; + class StackMaps { public: struct Location { @@ -118,6 +164,12 @@ public: StackMaps(AsmPrinter &AP); + void reset() { + CSInfos.clear(); + ConstPool.clear(); + FnStackSize.clear(); + } + /// \brief Generate a stackmap record for a stackmap instruction. /// /// MI must be a raw STACKMAP, not a PATCHPOINT. @@ -126,6 +178,9 @@ public: /// \brief Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); + /// \brief Generate a stackmap record for a statepoint instruction. + void recordStatepoint(const MachineInstr &MI); + /// If there is any stack map data, create a stack map section and serialize /// the map info into it. This clears the stack map data structures /// afterwards. @@ -133,10 +188,9 @@ public: private: static const char *WSMP; - typedef SmallVector<Location, 8> LocationVec; typedef SmallVector<LiveOutReg, 8> LiveOutVec; - typedef MapVector<int64_t, int64_t> ConstantPool; + typedef MapVector<uint64_t, uint64_t> ConstantPool; typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap; struct CallsiteInfo { @@ -146,9 +200,9 @@ private: LiveOutVec LiveOuts; CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, - LocationVec &Locations, LiveOutVec &LiveOuts) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations), - LiveOuts(LiveOuts) {} + LocationVec &&Locations, LiveOutVec &&LiveOuts) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), + LiveOuts(std::move(LiveOuts)) {} }; typedef std::vector<CallsiteInfo> CallsiteInfoList; @@ -196,4 +250,4 @@ private: } -#endif // LLVM_STACKMAPS +#endif diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 87f140190a75..9209e1c67c1b 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -89,8 +89,6 @@ public: ArrayRef<Module::ModuleFlagEntry> ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - bool isSectionAtomizableBySymbols(const MCSection &Section) const override; - const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 690b70fad89b..b6136665b968 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -41,7 +41,7 @@ class TargetSchedModel { unsigned MicroOpFactor; // Multiply to normalize microops to resource units. unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. public: - TargetSchedModel(): STI(nullptr), TII(nullptr) {} + TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {} /// \brief Initialize the machine model for instruction scheduling. /// @@ -167,6 +167,7 @@ public: /// if converter after moving it to TargetSchedModel). unsigned computeInstrLatency(const MachineInstr *MI, bool UseDefaultDefLatency = true) const; + unsigned computeInstrLatency(unsigned Opcode) const; /// \brief Output dependency latency of a pair of defs of the same register. /// diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 996f9ba29a12..d154135e25b2 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -18,6 +18,9 @@ /* Define to enable crash overrides */ #cmakedefine ENABLE_CRASH_OVERRIDES +/* Define to disable C++ atexit */ +#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -188,6 +191,9 @@ /* Define to 1 if you have the <limits.h> header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} +/* Define to 1 if you have the <link.h> header file. */ +#cmakedefine HAVE_LINK_H ${HAVE_LINK_H} + /* Define if you can use -rdynamic. */ #define HAVE_LINK_EXPORT_DYNAMIC 1 @@ -456,9 +462,6 @@ /* Have host's ___chkstk */ #cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} -/* Linker version detected at compile time. */ -#undef HOST_LINK_VERSION - /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS @@ -518,9 +521,6 @@ /* Type of 1st arg on ELM Callback */ #cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR} -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - /* Define to `int' if <sys/types.h> does not define. */ #undef pid_t @@ -542,7 +542,4 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Maximum path length */ -#cmakedefine MAXPATHLEN ${MAXPATHLEN} - #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index beed1182c3f6..ec09c84c5b71 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -9,6 +9,9 @@ /* Define if we have libxml2 */ #undef CLANG_HAVE_LIBXML +/* Multilib suffix for libdir. */ +#undef CLANG_LIBDIR_SUFFIX + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR @@ -543,6 +546,9 @@ /* Patch version of the LLVM API */ #undef LLVM_VERSION_PATCH +/* LLVM version string */ +#undef LLVM_VERSION_STRING + /* The shared library extension */ #undef LTDL_SHLIB_EXT diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 58111644ffa9..77201e6330bb 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -92,6 +92,9 @@ /* Minor version of the LLVM API */ #cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +/* LLVM version string */ +#define LLVM_VERSION_STRING "${PACKAGE_VERSION}" + /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 5656240eb127..2d6add71a4e0 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -92,4 +92,7 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR +/* LLVM version string */ +#undef LLVM_VERSION_STRING + #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index c1aba01fbf75..622aa699c435 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -21,7 +21,6 @@ #include "llvm/Object/RelocVisitor.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" - #include <string> namespace llvm { @@ -66,11 +65,15 @@ class DIInliningInfo { } }; +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + /// DILineInfoSpecifier - controls which fields of DILineInfo container /// should be filled with data. struct DILineInfoSpecifier { enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; - enum class FunctionNameKind { None, ShortName, LinkageName }; + typedef DINameKind FunctionNameKind; FileLineInfoKind FLIKind; FunctionNameKind FNKind; @@ -103,7 +106,11 @@ enum DIDumpType { DIDT_GnuPubtypes, DIDT_Str, DIDT_StrDwo, - DIDT_StrOffsetsDwo + DIDT_StrOffsetsDwo, + DIDT_AppleNames, + DIDT_AppleTypes, + DIDT_AppleNamespaces, + DIDT_AppleObjC }; // In place of applying the relocations to the data we've read from disk we use @@ -124,7 +131,7 @@ public: virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(object::ObjectFile *); + static DIContext *getDWARFContext(const object::ObjectFile &Obj); virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; diff --git a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h new file mode 100644 index 000000000000..bb05c302be9a --- /dev/null +++ b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h @@ -0,0 +1,60 @@ +//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclaration { + uint32_t Code; + uint32_t Tag; + bool HasChildren; + + struct AttributeSpec { + AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} + uint16_t Attr; + uint16_t Form; + }; + typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; + AttributeSpecVector AttributeSpecs; +public: + DWARFAbbreviationDeclaration(); + + uint32_t getCode() const { return Code; } + uint32_t getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + + typedef iterator_range<AttributeSpecVector::const_iterator> + attr_iterator_range; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); + } + + uint16_t getFormByIndex(uint32_t idx) const { + return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; + } + + uint32_t findAttributeIndex(uint16_t attr) const; + bool extract(DataExtractor Data, uint32_t* OffsetPtr); + void dump(raw_ostream &OS) const; + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARFAcceleratorTable.h new file mode 100644 index 000000000000..3fbc1c3b3c79 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFAcceleratorTable.h @@ -0,0 +1,49 @@ +//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include <cstdint> + +namespace llvm { + +class DWARFAcceleratorTable { + + struct Header { + uint32_t Magic; + uint16_t Version; + uint16_t HashFunction; + uint32_t NumBuckets; + uint32_t NumHashes; + uint32_t HeaderDataLength; + }; + + struct HeaderData { + typedef uint16_t AtomType; + typedef uint16_t Form; + uint32_t DIEOffsetBase; + SmallVector<std::pair<AtomType, Form>, 3> Atoms; + }; + + struct Header Hdr; + struct HeaderData HdrData; + DataExtractor AccelSection; + DataExtractor StringSection; + const RelocAddrMap& Relocs; +public: + DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection, + const RelocAddrMap &Relocs) + : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} + + bool extract(); + void dump(raw_ostream &OS) const; +}; + +} diff --git a/include/llvm/DebugInfo/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARFCompileUnit.h new file mode 100644 index 000000000000..dbf777cc71aa --- /dev/null +++ b/include/llvm/DebugInfo/DWARFCompileUnit.h @@ -0,0 +1,31 @@ +//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "llvm/DebugInfo/DWARFUnit.h" + +namespace llvm { + +class DWARFCompileUnit : public DWARFUnit { +public: + DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + void dump(raw_ostream &OS); + // VTable anchor. + ~DWARFCompileUnit() override; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFContext.h b/include/llvm/DebugInfo/DWARFContext.h new file mode 100644 index 000000000000..82b5bb088477 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFContext.h @@ -0,0 +1,292 @@ +//===-- DWARFContext.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H +#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARFSection.h" +#include "llvm/DebugInfo/DWARFTypeUnit.h" +#include <vector> + +namespace llvm { + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through pure virtual +/// methods that a concrete implementation provides. +class DWARFContext : public DIContext { + + DWARFUnitSection<DWARFCompileUnit> CUs; + std::vector<DWARFUnitSection<DWARFTypeUnit>> TUs; + std::unique_ptr<DWARFDebugAbbrev> Abbrev; + std::unique_ptr<DWARFDebugLoc> Loc; + std::unique_ptr<DWARFDebugAranges> Aranges; + std::unique_ptr<DWARFDebugLine> Line; + std::unique_ptr<DWARFDebugFrame> DebugFrame; + + DWARFUnitSection<DWARFCompileUnit> DWOCUs; + std::vector<DWARFUnitSection<DWARFTypeUnit>> DWOTUs; + std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; + std::unique_ptr<DWARFDebugLocDWO> LocDWO; + + DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; + DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; + + /// Read compile units from the debug_info section (if necessary) + /// and store them in CUs. + void parseCompileUnits(); + + /// Read type units from the debug_types sections (if necessary) + /// and store them in TUs. + void parseTypeUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and store them in DWOCUs. + void parseDWOCompileUnits(); + + /// Read type units from the debug_types.dwo section (if necessary) + /// and store them in DWOTUs. + void parseDWOTypeUnits(); + +public: + DWARFContext() : DIContext(CK_DWARF) {} + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_DWARF; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range; + typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range; + typedef iterator_range<std::vector<DWARFUnitSection<DWARFTypeUnit>>::iterator> tu_section_iterator_range; + + /// Get compile units in this context. + cu_iterator_range compile_units() { + parseCompileUnits(); + return cu_iterator_range(CUs.begin(), CUs.end()); + } + + /// Get type units in this context. + tu_section_iterator_range type_unit_sections() { + parseTypeUnits(); + return tu_section_iterator_range(TUs.begin(), TUs.end()); + } + + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { + parseDWOCompileUnits(); + return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + } + + /// Get type units in the DWO context. + tu_section_iterator_range dwo_type_unit_sections() { + parseDWOTypeUnits(); + return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseCompileUnits(); + return CUs.size(); + } + + /// Get the number of compile units in this context. + unsigned getNumTypeUnits() { + parseTypeUnits(); + return TUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOCompileUnits(); + return DWOCUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOTypeUnits(); + return DWOTUs.size(); + } + + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + parseCompileUnits(); + return CUs[index].get(); + } + + /// Get the compile unit at the specified index for the DWO compile units. + DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { + parseDWOCompileUnits(); + return DWOCUs[index].get(); + } + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLocDWO *getDebugLocDWO(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to the parsed frame information object. + const DWARFDebugFrame *getDebugFrame(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const = 0; + virtual const DWARFSection &getInfoSection() = 0; + typedef MapVector<object::SectionRef, DWARFSection, + std::map<object::SectionRef, unsigned>> TypeSectionMap; + virtual const TypeSectionMap &getTypesSections() = 0; + virtual StringRef getAbbrevSection() = 0; + virtual const DWARFSection &getLocSection() = 0; + virtual StringRef getARangeSection() = 0; + virtual StringRef getDebugFrameSection() = 0; + virtual const DWARFSection &getLineSection() = 0; + virtual StringRef getStringSection() = 0; + virtual StringRef getRangeSection() = 0; + virtual StringRef getPubNamesSection() = 0; + virtual StringRef getPubTypesSection() = 0; + virtual StringRef getGnuPubNamesSection() = 0; + virtual StringRef getGnuPubTypesSection() = 0; + + // Sections for DWARF5 split dwarf proposal. + virtual const DWARFSection &getInfoDWOSection() = 0; + virtual const TypeSectionMap &getTypesDWOSections() = 0; + virtual StringRef getAbbrevDWOSection() = 0; + virtual const DWARFSection &getLineDWOSection() = 0; + virtual const DWARFSection &getLocDWOSection() = 0; + virtual StringRef getStringDWOSection() = 0; + virtual StringRef getStringOffsetDWOSection() = 0; + virtual StringRef getRangeDWOSection() = 0; + virtual StringRef getAddrSection() = 0; + virtual const DWARFSection& getAppleNamesSection() = 0; + virtual const DWARFSection& getAppleTypesSection() = 0; + virtual const DWARFSection& getAppleNamespacesSection() = 0; + virtual const DWARFSection& getAppleObjCSection() = 0; + + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3 || version == 4; + } +private: + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + + /// Return the compile unit which contains instruction with provided + /// address. + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); +}; + +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { + virtual void anchor(); + bool IsLittleEndian; + uint8_t AddressSize; + DWARFSection InfoSection; + TypeSectionMap TypesSections; + StringRef AbbrevSection; + DWARFSection LocSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + DWARFSection LineSection; + StringRef StringSection; + StringRef RangeSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef GnuPubTypesSection; + + // Sections for DWARF5 split dwarf proposal. + DWARFSection InfoDWOSection; + TypeSectionMap TypesDWOSections; + StringRef AbbrevDWOSection; + DWARFSection LineDWOSection; + DWARFSection LocDWOSection; + StringRef StringDWOSection; + StringRef StringOffsetDWOSection; + StringRef RangeDWOSection; + StringRef AddrSection; + DWARFSection AppleNamesSection; + DWARFSection AppleTypesSection; + DWARFSection AppleNamespacesSection; + DWARFSection AppleObjCSection; + + SmallVector<SmallString<32>, 4> UncompressedSections; + +public: + DWARFContextInMemory(const object::ObjectFile &Obj); + bool isLittleEndian() const override { return IsLittleEndian; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() override { return InfoSection; } + const TypeSectionMap &getTypesSections() override { return TypesSections; } + StringRef getAbbrevSection() override { return AbbrevSection; } + const DWARFSection &getLocSection() override { return LocSection; } + StringRef getARangeSection() override { return ARangeSection; } + StringRef getDebugFrameSection() override { return DebugFrameSection; } + const DWARFSection &getLineSection() override { return LineSection; } + StringRef getStringSection() override { return StringSection; } + StringRef getRangeSection() override { return RangeSection; } + StringRef getPubNamesSection() override { return PubNamesSection; } + StringRef getPubTypesSection() override { return PubTypesSection; } + StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } + StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } + const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } + const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } + const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } + const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } + const TypeSectionMap &getTypesDWOSections() override { + return TypesDWOSections; + } + StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() override { return LineDWOSection; } + const DWARFSection &getLocDWOSection() override { return LocDWOSection; } + StringRef getStringDWOSection() override { return StringDWOSection; } + StringRef getStringOffsetDWOSection() override { + return StringOffsetDWOSection; + } + StringRef getRangeDWOSection() override { return RangeDWOSection; } + StringRef getAddrSection() override { + return AddrSection; + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARFDebugAbbrev.h new file mode 100644 index 000000000000..6752df9cd728 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugAbbrev.h @@ -0,0 +1,63 @@ +//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" +#include <list> +#include <map> +#include <vector> + +namespace llvm { + +class DWARFAbbreviationDeclarationSet { + uint32_t Offset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; + std::vector<DWARFAbbreviationDeclaration> Decls; + +public: + DWARFAbbreviationDeclarationSet(); + + uint32_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor Data, uint32_t *OffsetPtr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); +}; + +class DWARFDebugAbbrev { + typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet> + DWARFAbbreviationDeclarationSetMap; + + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; + +public: + DWARFDebugAbbrev(); + + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + + void dump(raw_ostream &OS) const; + void extract(DataExtractor Data); + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARFDebugArangeSet.h new file mode 100644 index 000000000000..837a8e63469e --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugArangeSet.h @@ -0,0 +1,70 @@ +//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" +#include <vector> + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + // The total length of the entries for that set, not including the length + // field itself. + uint32_t Length; + // The offset from the beginning of the .debug_info section of the + // compilation unit entry referenced by the table. + uint32_t CuOffset; + // The DWARF version number. + uint16_t Version; + // The size in bytes of an address on the target architecture. For segmented + // addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + // The size in bytes of a segment descriptor on the target architecture. + // If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + uint64_t getEndAddress() const { return Address + Length; } + }; + +private: + typedef std::vector<Descriptor> DescriptorColl; + typedef iterator_range<DescriptorColl::const_iterator> desc_iterator_range; + + uint32_t Offset; + Header HeaderData; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + void clear(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARFDebugAranges.h new file mode 100644 index 000000000000..791f010a8892 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugAranges.h @@ -0,0 +1,87 @@ +//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataExtractor.h" +#include <vector> + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + void generate(DWARFContext *CTX); + uint32_t findAddress(uint64_t Address) const; + +private: + void clear(); + void extract(DataExtractor DebugArangesData); + + // Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); + + struct Range { + explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, + uint32_t CUOffset = -1U) + : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} + + void setHighPC(uint64_t HighPC) { + if (HighPC == -1ULL || HighPC <= LowPC) + Length = 0; + else + Length = HighPC - LowPC; + } + uint64_t HighPC() const { + if (Length) + return LowPC + Length; + return -1ULL; + } + + bool containsAddress(uint64_t Address) const { + return LowPC <= Address && Address < HighPC(); + } + bool operator<(const Range &other) const { + return LowPC < other.LowPC; + } + + uint64_t LowPC; // Start of address range. + uint32_t Length; // End of address range (not including this address). + uint32_t CUOffset; // Offset of the compile unit or die. + }; + + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + + typedef std::vector<Range> RangeColl; + typedef RangeColl::const_iterator RangeCollIterator; + + std::vector<RangeEndpoint> Endpoints; + RangeColl Aranges; + DenseSet<uint32_t> ParsedCUOffsets; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARFDebugFrame.h new file mode 100644 index 000000000000..be925cbe7519 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugFrame.h @@ -0,0 +1,43 @@ +//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> +#include <vector> + +namespace llvm { + +class FrameEntry; + +/// \brief A parsed .debug_frame section +/// +class DWARFDebugFrame { +public: + DWARFDebugFrame(); + ~DWARFDebugFrame(); + + /// \brief Dump the section data into the given stream. + void dump(raw_ostream &OS) const; + + /// \brief Parse the section from raw data. + /// data is assumed to be pointing to the beginning of the section. + void parse(DataExtractor Data); + +private: + std::vector<std::unique_ptr<FrameEntry>> Entries; +}; + + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h new file mode 100644 index 000000000000..f05d64b6f34b --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h @@ -0,0 +1,160 @@ +//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFDebugAranges; +class DWARFCompileUnit; +class DWARFUnit; +class DWARFContext; +class DWARFFormValue; +struct DWARFDebugInfoEntryInlinedChain; + +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. +class DWARFDebugInfoEntryMinimal { + /// Offset within the .debug_info of the start of this entry. + uint32_t Offset; + + /// How many to add to "this" to get the sibling. + uint32_t SiblingIdx; + + const DWARFAbbreviationDeclaration *AbbrevDecl; +public: + DWARFDebugInfoEntryMinimal() + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} + + void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, + unsigned indent = 0) const; + void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, + uint16_t attr, uint16_t form, unsigned indent = 0) const; + + /// Extracts a debug info entry, which is a child of a given unit, + /// starting at a given offset. If DIE can't be extracted, returns false and + /// doesn't change OffsetPtr. + bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); + + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } + + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + /// Returns true if DIE represents a subprogram or an inlined + /// subroutine. + bool isSubroutineDIE() const; + + uint32_t getOffset() const { return Offset; } + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + const DWARFDebugInfoEntryMinimal *getSibling() const { + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; + } + + // We know we are kept in a vector of contiguous entries, so we know + // we don't need to store our child pointer, if we have a child it will + // be the next entry in the list... + const DWARFDebugInfoEntryMinimal *getFirstChild() const { + return hasChildren() ? this + 1 : nullptr; + } + + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + SiblingIdx = Sibling - this; + } else + SiblingIdx = 0; + } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } + + bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, + DWARFFormValue &FormValue) const; + + const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, + const char *FailValue) const; + + uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, + uint64_t &HighPC) const; + + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const DWARFUnit *U, + const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), + /// returns its mangled name (or short name, if mangled is missing). + /// This name may be fetched from specification or abstract origin + /// for this subprogram. Returns null if no name is found. + const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or + /// DW_AT_abstract_origin references if necessary. + /// Returns null if no name is found. + const char *getName(const DWARFUnit *U, DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and + /// DW_AT_call_column from DIE (or zeroes if they are missing). + void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, + uint32_t &CallLine, uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + DWARFDebugInfoEntryInlinedChain + getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; +}; + +/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine +/// DIEs, (possibly ending with subprogram DIE), all of which are contained +/// in some concrete inlined instance tree. Address range for each DIE +/// (except the last DIE) in this chain is contained in address +/// range for next DIE in the chain. +struct DWARFDebugInfoEntryInlinedChain { + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} + SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs; + const DWARFUnit *U; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARFDebugLine.h new file mode 100644 index 000000000000..c5ee76e39682 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugLine.h @@ -0,0 +1,238 @@ +//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" +#include <map> +#include <string> +#include <vector> + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLine { +public: + DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} + struct FileNameEntry { + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} + + const char *Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; + }; + + struct Prologue { + Prologue(); + + // The size in bytes of the statement information for this compilation unit + // (not including the total_length field itself). + uint32_t TotalLength; + // Version identifier for the statement information format. + uint16_t Version; + // The number of bytes following the prologue_length field to the beginning + // of the first byte of the statement program itself. + uint32_t PrologueLength; + // The size in bytes of the smallest target machine instruction. Statement + // program opcodes that alter the address register first multiply their + // operands by this value. + uint8_t MinInstLength; + // The maximum number of individual operations that may be encoded in an + // instruction. + uint8_t MaxOpsPerInst; + // The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + // This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + // This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + // The number assigned to the first special opcode. + uint8_t OpcodeBase; + std::vector<uint8_t> StandardOpcodeLengths; + std::vector<const char*> IncludeDirectories; + std::vector<FileNameEntry> FileNames; + + // Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeof(TotalLength) + sizeof(Version) + + sizeof(PrologueLength); + } + // Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeof(TotalLength) - getLength(); + } + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + + void clear(); + void dump(raw_ostream &OS) const; + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); + }; + + // Standard .debug_line state machine structure. + struct Row { + explicit Row(bool default_is_stmt = false); + + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool default_is_stmt); + void dump(raw_ostream &OS) const; + + static bool orderByAddress(const Row& LHS, const Row& RHS) { + return LHS.Address < RHS.Address; + } + + // The program-counter value corresponding to a machine instruction + // generated by the compiler. + uint64_t Address; + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + uint32_t Line; + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the 'left edge' of the line. + uint16_t Column; + // An unsigned integer indicating the identity of the source file + // corresponding to a machine instruction. + uint16_t File; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; + // An unsigned integer representing the DWARF path discriminator value + // for this location. + uint32_t Discriminator; + // A boolean indicating that the current instruction is the beginning of a + // statement. + uint8_t IsStmt:1, + // A boolean indicating that the current instruction is the + // beginning of a basic block. + BasicBlock:1, + // A boolean indicating that the current address is that of the + // first byte after the end of a sequence of target machine + // instructions. + EndSequence:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an entry breakpoint + // of a function. + PrologueEnd:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an exit breakpoint + // of a function. + EpilogueBegin:1; + }; + + // Represents a series of contiguous machine instructions. Line table for each + // compilation unit may consist of multiple sequences, which are not + // guaranteed to be in the order of ascending instruction address. + struct Sequence { + // Sequence describes instructions at address range [LowPC, HighPC) + // and is described by line table rows [FirstRowIndex, LastRowIndex). + uint64_t LowPC; + uint64_t HighPC; + unsigned FirstRowIndex; + unsigned LastRowIndex; + bool Empty; + + Sequence(); + void reset(); + + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { + return LHS.LowPC < RHS.LowPC; + } + bool isValid() const { + return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); + } + bool containsPC(uint64_t pc) const { + return (LowPC <= pc && pc < HighPC); + } + }; + + struct LineTable { + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); + } + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); + } + + // Returns the index of the row with file/line info for a given address, + // or -1 if there is no such row. + uint32_t lookupAddress(uint64_t address) const; + + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector<uint32_t> &result) const; + + // Extracts filename by its index in filename table in prologue. + // Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + + // Fills the Result argument with the file and line information + // corresponding to Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; + + void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); + + struct Prologue Prologue; + typedef std::vector<Row> RowVector; + typedef RowVector::const_iterator RowIter; + typedef std::vector<Sequence> SequenceVector; + typedef SequenceVector::const_iterator SequenceIter; + RowVector Rows; + SequenceVector Sequences; + }; + + const LineTable *getLineTable(uint32_t offset) const; + const LineTable *getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset); + +private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + + typedef std::map<uint32_t, LineTable> LineTableMapTy; + typedef LineTableMapTy::iterator LineTableIter; + typedef LineTableMapTy::const_iterator LineTableConstIter; + + const RelocAddrMap *RelocMap; + LineTableMapTy LineTableMap; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARFDebugLoc.h new file mode 100644 index 000000000000..a6135a0c9291 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugLoc.h @@ -0,0 +1,81 @@ +//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLoc { + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector<unsigned char, 4> Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector<Entry, 2> Entries; + }; + + typedef SmallVector<LocationList, 4> LocationLists; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + /// A map used to resolve binary relocations. + const RelocAddrMap &RelocMap; + +public: + DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS) const; + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// specified address size to interpret the address ranges. + void parse(DataExtractor data, unsigned AddressSize); +}; + +class DWARFDebugLocDWO { + struct Entry { + uint64_t Start; + uint32_t Length; + SmallVector<unsigned char, 4> Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector<Entry, 2> Entries; + }; + + typedef SmallVector<LocationList, 4> LocationLists; + + LocationLists Locations; + +public: + void parse(DataExtractor data); + void dump(raw_ostream &OS) const; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARFDebugRangeList.h new file mode 100644 index 000000000000..4ee3bdad3299 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugRangeList.h @@ -0,0 +1,77 @@ +//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H + +#include "llvm/Support/DataExtractor.h" +#include <vector> + +namespace llvm { + +class raw_ostream; + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + // A beginning address offset. This address offset has the size of an + // address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the beginning + // of an address range. + uint64_t StartAddress; + // An ending address offset. This address offset again has the size of + // an address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the first + // address past the end of the address range. The ending address must + // be greater than or equal to the beginning address. + uint64_t EndAddress; + // The end of any given range list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset + // and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + // A base address selection entry consists of: + // 1. The value of the largest representable address offset + // (for example, 0xffffffff when the size of an address is 32 bits). + // 2. An address, which defines the appropriate base address for + // use in interpreting the beginning and ending address offsets of + // subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + // Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector<RangeListEntry> Entries; + +public: + DWARFDebugRangeList() { clear(); } + void clear(); + void dump(raw_ostream &OS) const; + bool extract(DataExtractor data, uint32_t *offset_ptr); + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index d517a72d62e0..5bb6d1b9ddb0 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -57,6 +57,13 @@ public: bool isFormClass(FormClass FC) const; void dump(raw_ostream &OS, const DWARFUnit *U) const; + + /// \brief extracts a value in data at offset *offset_ptr. + /// + /// The passed DWARFUnit is allowed to be nullptr, in which + /// case no relocation processing will be performed and some + /// kind of forms that depend on Unit information are disallowed. + /// \returns wether the extraction succeeded. bool extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *u); bool isInlinedCStr() const { @@ -70,6 +77,7 @@ public: Optional<const char *> getAsCString(const DWARFUnit *U) const; Optional<uint64_t> getAsAddress(const DWARFUnit *U) const; Optional<uint64_t> getAsSectionOffset() const; + Optional<ArrayRef<uint8_t>> getAsBlock() const; bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFUnit *u) const; diff --git a/include/llvm/DebugInfo/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARFRelocMap.h new file mode 100644 index 000000000000..d7fe3032e505 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFRelocMap.h @@ -0,0 +1,22 @@ +//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H +#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; + +} // namespace llvm + +#endif + diff --git a/include/llvm/DebugInfo/DWARFSection.h b/include/llvm/DebugInfo/DWARFSection.h new file mode 100644 index 000000000000..5f09d9e37d81 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFSection.h @@ -0,0 +1,24 @@ +//===-- DWARFSection.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H +#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H + +#include "llvm/DebugInfo/DWARFRelocMap.h" + +namespace llvm { + +struct DWARFSection { + StringRef Data; + RelocAddrMap Relocs; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARFTypeUnit.h new file mode 100644 index 000000000000..213b54139e04 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFTypeUnit.h @@ -0,0 +1,38 @@ +//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H + +#include "llvm/DebugInfo/DWARFUnit.h" + +namespace llvm { + +class DWARFTypeUnit : public DWARFUnit { +private: + uint64_t TypeHash; + uint32_t TypeOffset; +public: + DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } + void dump(raw_ostream &OS); +protected: + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; +}; + +} + +#endif + diff --git a/include/llvm/DebugInfo/DWARFUnit.h b/include/llvm/DebugInfo/DWARFUnit.h new file mode 100644 index 000000000000..d71a1b60b731 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFUnit.h @@ -0,0 +1,245 @@ +//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H + +#include "llvm/DebugInfo/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARFSection.h" +#include <vector> + +namespace llvm { + +namespace object { +class ObjectFile; +} + +class DWARFContext; +class DWARFDebugAbbrev; +class DWARFUnit; +class StringRef; +class raw_ostream; + +/// Base class for all DWARFUnitSection classes. This provides the +/// functionality common to all unit types. +class DWARFUnitSectionBase { +public: + /// Returns the Unit that contains the given section offset in the + /// same section this Unit originated from. + virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + + void parse(DWARFContext &C, const DWARFSection &Section); + void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); + +protected: + virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; + + ~DWARFUnitSectionBase() {} +}; + +/// Concrete instance of DWARFUnitSection, specialized for one Unit type. +template<typename UnitType> +class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>, + public DWARFUnitSectionBase { + + struct UnitOffsetComparator { + bool operator()(uint32_t LHS, + const std::unique_ptr<UnitType> &RHS) const { + return LHS < RHS->getNextUnitOffset(); + } + }; + + bool Parsed; + +public: + DWARFUnitSection() : Parsed(false) {} + DWARFUnitSection(DWARFUnitSection &&DUS) : + SmallVector<std::unique_ptr<UnitType>, 1>(std::move(DUS)), Parsed(DUS.Parsed) {} + + typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector; + typedef typename UnitVector::iterator iterator; + typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range; + + UnitType *getUnitForOffset(uint32_t Offset) const override { + auto *CU = std::upper_bound(this->begin(), this->end(), Offset, + UnitOffsetComparator()); + if (CU != this->end()) + return CU->get(); + return nullptr; + } + +private: + void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE) override { + if (Parsed) + return; + DataExtractor Data(Section.Data, LE, 0); + uint32_t Offset = 0; + while (Data.isValidOffset(Offset)) { + auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS, + AOS, LE, *this); + if (!U->extract(Data, &Offset)) + break; + this->push_back(std::move(U)); + Offset = this->back()->getNextUnitOffset(); + } + Parsed = true; + } +}; + +class DWARFUnit { + DWARFContext &Context; + // Section containing this DWARFUnit. + const DWARFSection &InfoSection; + + const DWARFDebugAbbrev *Abbrev; + StringRef RangeSection; + uint32_t RangeSectionBase; + StringRef StringSection; + StringRef StringOffsetSection; + StringRef AddrOffsetSection; + uint32_t AddrOffsetSectionBase; + bool isLittleEndian; + const DWARFUnitSectionBase &UnitSection; + + uint32_t Offset; + uint32_t Length; + uint16_t Version; + const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t AddrSize; + uint64_t BaseAddr; + // The compile unit debug information entry items. + std::vector<DWARFDebugInfoEntryMinimal> DieArray; + + class DWOHolder { + object::OwningBinary<object::ObjectFile> DWOFile; + std::unique_ptr<DWARFContext> DWOContext; + DWARFUnit *DWOU; + public: + DWOHolder(StringRef DWOPath); + DWARFUnit *getUnit() const { return DWOU; } + }; + std::unique_ptr<DWOHolder> DWO; + +protected: + virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } + +public: + DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection); + + virtual ~DWARFUnit(); + + DWARFContext& getContext() const { return Context; } + + StringRef getStringSection() const { return StringSection; } + StringRef getStringOffsetSection() const { return StringOffsetSection; } + void setAddrOffsetSection(StringRef AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + void setRangesSection(StringRef RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + // FIXME: Result should be uint64_t in DWARF64. + bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; + + DataExtractor getDebugInfoExtractor() const { + return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); + } + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + + const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } + + bool extract(DataExtractor debug_info, uint32_t* offset_ptr); + + /// extractRangeList - extracts the range list referenced by this compile + /// unit from .debug_ranges section. Returns true on success. + /// Requires that compile unit is already extracted. + bool extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; + void clear(); + uint32_t getOffset() const { return Offset; } + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getLength() const { return Length; } + uint16_t getVersion() const { return Version; } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const { + return Abbrevs; + } + uint8_t getAddressByteSize() const { return AddrSize; } + uint64_t getBaseAddress() const { return BaseAddr; } + + void setBaseAddress(uint64_t base_addr) { + BaseAddr = base_addr; + } + + const DWARFDebugInfoEntryMinimal * + getCompileUnitDIE(bool extract_cu_die_only = true) { + extractDIEsIfNeeded(extract_cu_die_only); + return DieArray.empty() ? nullptr : &DieArray[0]; + } + + const char *getCompilationDir(); + uint64_t getDWOId(); + + void collectAddressRanges(DWARFAddressRangesVector &CURanges); + + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. + DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + + /// getUnitSection - Return the DWARFUnitSection containing this unit. + const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + +private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. Returns the number of DIEs parsed at this call. + size_t extractDIEsIfNeeded(bool CUDieOnly); + /// extractDIEsToVector - Appends all parsed DIEs to a vector. + void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, + std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const; + /// setDIERelations - We read in all of the DIE entries into our flat list + /// of DIE entries and now we need to go back through all of them and set the + /// parent, sibling and child pointers for quick DIE navigation. + void setDIERelations(); + /// clearDIEs - Clear parsed DIEs to keep memory usage low. + void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); + + /// getSubprogramForAddress - Returns subprogram DIE with address range + /// encompassing the provided address. The pointer is alive as long as parsed + /// compile unit DIEs are not cleared. + const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index e5dab6191ab6..d79bd3c4dfc8 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -18,9 +18,11 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueMap.h" #include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" #include "llvm/Target/TargetMachine.h" @@ -39,9 +41,7 @@ class Function; class GlobalVariable; class GlobalValue; class JITEventListener; -class JITMemoryManager; class MachineCodeInfo; -class Module; class MutexGuard; class ObjectCache; class RTDyldMemoryManager; @@ -131,29 +131,20 @@ class ExecutionEngine { protected: /// The list of Modules that we are JIT'ing from. We use a SmallVector to /// optimize for the case where there is only one module. - SmallVector<Module*, 1> Modules; + SmallVector<std::unique_ptr<Module>, 1> Modules; void setDataLayout(const DataLayout *Val) { DL = Val; } /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); - // To avoid having libexecutionengine depend on the JIT and interpreter - // libraries, the execution engine implementations set these functions to ctor - // pointers at startup time if they are linked in. - static ExecutionEngine *(*JITCtor)( - Module *M, - std::string *ErrorStr, - JITMemoryManager *JMM, - bool GVsWithCode, - TargetMachine *TM); static ExecutionEngine *(*MCJITCtor)( - Module *M, - std::string *ErrorStr, - RTDyldMemoryManager *MCJMM, - bool GVsWithCode, - TargetMachine *TM); - static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); + std::unique_ptr<Module> M, + std::string *ErrorStr, + std::unique_ptr<RTDyldMemoryManager> MCJMM, + std::unique_ptr<TargetMachine> TM); + static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M, + std::string *ErrorStr); /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will @@ -161,9 +152,8 @@ protected: void *(*LazyFunctionCreator)(const std::string &); public: - /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and - /// JITEmitter classes. It must be held while changing the internal state of - /// any of those classes. + /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must + /// be held while changing the internal state of any of those classes. sys::Mutex lock; //===--------------------------------------------------------------------===// @@ -172,44 +162,9 @@ public: virtual ~ExecutionEngine(); - /// create - This is the factory method for creating an execution engine which - /// is appropriate for the current machine. This takes ownership of the - /// module. - /// - /// \param GVsWithCode - Allocating globals with code breaks - /// freeMachineCodeForFunction and is probably unsafe and bad for performance. - /// However, we have clients who depend on this behavior, so we must support - /// it. Eventually, when we're willing to break some backwards compatibility, - /// this flag should be flipped to false, so that by default - /// freeMachineCodeForFunction works. - static ExecutionEngine *create(Module *M, - bool ForceInterpreter = false, - std::string *ErrorStr = nullptr, - CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, - bool GVsWithCode = true); - - /// createJIT - This is the factory method for creating a JIT for the current - /// machine, it does not fall back to the interpreter. This takes ownership - /// of the Module and JITMemoryManager if successful. - /// - /// Clients should make sure to initialize targets prior to calling this - /// function. - static ExecutionEngine *createJIT(Module *M, - std::string *ErrorStr = nullptr, - JITMemoryManager *JMM = nullptr, - CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, - bool GVsWithCode = true, - Reloc::Model RM = Reloc::Default, - CodeModel::Model CMM = - CodeModel::JITDefault); - - /// addModule - Add a Module to the list of modules that we can JIT from. - /// Note that this takes ownership of the Module: when the ExecutionEngine is - /// destroyed, it destroys the Module as well. - virtual void addModule(Module *M) { - Modules.push_back(M); + /// Add a Module to the list of modules that we can JIT from. + virtual void addModule(std::unique_ptr<Module> M) { + Modules.push_back(std::move(M)); } /// addObjectFile - Add an ObjectFile to the execution engine. @@ -223,6 +178,7 @@ public: /// /// MCJIT will take ownership of the ObjectFile. virtual void addObjectFile(std::unique_ptr<object::ObjectFile> O); + virtual void addObjectFile(object::OwningBinary<object::ObjectFile> O); /// addArchive - Add an Archive to the execution engine. /// @@ -230,11 +186,7 @@ public: /// resolve external symbols in objects it is loading. If a symbol is found /// in the Archive the contained object file will be extracted (in memory) /// and loaded for possible execution. - /// - /// MCJIT will take ownership of the Archive. - virtual void addArchive(object::Archive *A) { - llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive."); - } + virtual void addArchive(object::OwningBinary<object::Archive> A); //===--------------------------------------------------------------------===// @@ -263,11 +215,7 @@ public: /// it prints a message to stderr and aborts. /// /// This function is deprecated for the MCJIT execution engine. - /// - /// FIXME: the JIT and MCJIT interfaces should be disentangled or united - /// again, if possible. - /// - virtual void *getPointerToNamedFunction(const std::string &Name, + virtual void *getPointerToNamedFunction(StringRef Name, bool AbortOnFailure = true) = 0; /// mapSectionAddress - map a section to its target address space value. @@ -279,7 +227,7 @@ public: "EE!"); } - /// generateCodeForModule - Run code generationen for the specified module and + /// generateCodeForModule - Run code generation for the specified module and /// load it into memory. /// /// When this function has completed, all code and data for the specified @@ -293,7 +241,7 @@ public: /// locally can use the getFunctionAddress call, which will generate code /// and apply final preparations all in one step. /// - /// This method has no effect for the legacy JIT engine or the interpeter. + /// This method has no effect for the interpeter. virtual void generateCodeForModule(Module *M) {} /// finalizeObject - ensure the module is fully processed and is usable. @@ -302,8 +250,7 @@ public: /// object usable for execution. It should be called after sections within an /// object have been relocated using mapSectionAddress. When this method is /// called the MCJIT execution engine will reapply relocations for a loaded - /// object. This method has no effect for the legacy JIT engine or the - /// interpeter. + /// object. This method has no effect for the interpeter. virtual void finalizeObject() {} /// runStaticConstructorsDestructors - This method is used to execute all of @@ -312,11 +259,11 @@ public: /// \param isDtors - Run the destructors instead of constructors. virtual void runStaticConstructorsDestructors(bool isDtors); - /// runStaticConstructorsDestructors - This method is used to execute all of - /// the static constructors or destructors for a particular module. + /// This method is used to execute all of the static constructors or + /// destructors for a particular module. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(Module *module, bool isDtors); + void runStaticConstructorsDestructors(Module &module, bool isDtors); /// runFunctionAsMain - This is a helper function which wraps runFunction to @@ -373,13 +320,6 @@ public: /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; - /// getPointerToBasicBlock - The different EE's represent basic blocks in - /// different ways. Return the representation for a blockaddress of the - /// specified block. - /// - /// This function will not be implemented for the MCJIT execution engine. - virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; - /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See @@ -395,9 +335,9 @@ public: /// getGlobalValueAddress - Return the address of the specified global /// value. This may involve code generation. /// - /// This function should not be called with the JIT or interpreter engines. + /// This function should not be called with the interpreter engine. virtual uint64_t getGlobalValueAddress(const std::string &Name) { - // Default implementation for JIT and interpreter. MCJIT will override this. + // Default implementation for the interpreter. MCJIT will override this. // JIT and interpreter clients should use getPointerToGlobal instead. return 0; } @@ -405,14 +345,11 @@ public: /// getFunctionAddress - Return the address of the specified function. /// This may involve code generation. virtual uint64_t getFunctionAddress(const std::string &Name) { - // Default implementation for JIT and interpreter. MCJIT will override this. - // JIT and interpreter clients should use getPointerToFunction instead. + // Default implementation for the interpreter. MCJIT will override this. + // Interpreter clients should use getPointerToFunction instead. return 0; } - // The JIT overrides a version that actually does this. - virtual void runJITOnFunction(Function *, MachineCodeInfo * = nullptr) { } - /// getGlobalValueAtAddress - Return the LLVM global value object that starts /// at the specified address. /// @@ -427,18 +364,6 @@ public: void InitializeMemory(const Constant *Init, void *Addr); - /// recompileAndRelinkFunction - This method is used to force a function which - /// has already been compiled to be compiled again, possibly after it has been - /// modified. Then the entry to the old copy is overwritten with a branch to - /// the new copy. If there was no old copy, this acts just like - /// VM::getPointerToFunction(). - virtual void *recompileAndRelinkFunction(Function *F) = 0; - - /// freeMachineCodeForFunction - Release memory in the ExecutionEngine - /// corresponding to the machine code emitted to execute this function, useful - /// for garbage-collecting generated code. - virtual void freeMachineCodeForFunction(Function *F) = 0; - /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. @@ -457,7 +382,7 @@ public: virtual void UnregisterJITEventListener(JITEventListener *) {} /// Sets the pre-compiled object cache. The ownership of the ObjectCache is - /// not changed. Supported by MCJIT but not JIT. + /// not changed. Supported by MCJIT but not the interpreter. virtual void setObjectCache(ObjectCache *) { llvm_unreachable("No support for an object cache"); } @@ -499,11 +424,6 @@ public: bool isCompilingLazily() const { return CompilingLazily; } - // Deprecated in favor of isCompilingLazily (to reduce double-negatives). - // Remove this in LLVM 2.8. - bool isLazyCompilationDisabled() const { - return !CompilingLazily; - } /// DisableGVCompilation - If called, the JIT will abort if it's asked to /// allocate space and populate a GlobalVariable that is not internal to @@ -544,7 +464,7 @@ public: } protected: - explicit ExecutionEngine(Module *M); + explicit ExecutionEngine(std::unique_ptr<Module> M); void emitGlobals(); @@ -564,36 +484,33 @@ namespace EngineKind { const static Kind Either = (Kind)(JIT | Interpreter); } -/// EngineBuilder - Builder class for ExecutionEngines. Use this by -/// stack-allocating a builder, chaining the various set* methods, and -/// terminating it with a .create() call. +/// Builder class for ExecutionEngines. Use this by stack-allocating a builder, +/// chaining the various set* methods, and terminating it with a .create() +/// call. class EngineBuilder { private: - Module *M; + std::unique_ptr<Module> M; EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - RTDyldMemoryManager *MCJMM; - JITMemoryManager *JMM; - bool AllocateGVsWithCode; + std::unique_ptr<RTDyldMemoryManager> MCJMM; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; std::string MArch; std::string MCPU; SmallVector<std::string, 4> MAttrs; - bool UseMCJIT; bool VerifyModules; /// InitEngine - Does the common initialization of default options. void InitEngine(); public: - /// EngineBuilder - Constructor for EngineBuilder. If create() is called and - /// is successful, the created engine takes ownership of the module. - EngineBuilder(Module *m) : M(m) { - InitEngine(); - } + /// Constructor for EngineBuilder. + EngineBuilder(std::unique_ptr<Module> M); + + // Out-of-line since we don't have the def'n of RTDyldMemoryManager here. + ~EngineBuilder(); /// setEngineKind - Controls whether the user wants the interpreter, the JIT, /// or whichever engine works. This option defaults to EngineKind::Either. @@ -607,26 +524,8 @@ public: /// is only appropriate for the MCJIT; setting this and configuring the builder /// to create anything other than MCJIT will cause a runtime error. If create() /// is called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. Using this option nullifies - /// the setJITMemoryManager() option. - EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { - MCJMM = mcjmm; - JMM = nullptr; - return *this; - } - - /// setJITMemoryManager - Sets the JIT memory manager to use. This allows - /// clients to customize their memory allocation policies. This is only - /// appropriate for either JIT or MCJIT; setting this and configuring the - /// builder to create an interpreter will cause a runtime error. If create() - /// is called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. This option overrides - /// setMCJITMemoryManager() as well. - EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { - MCJMM = nullptr; - JMM = jmm; - return *this; - } + /// memory manager. This option defaults to NULL. + EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. @@ -664,18 +563,6 @@ public: return *this; } - /// setAllocateGVsWithCode - Sets whether global values should be allocated - /// into the same buffer as code. For most applications this should be set - /// to false. Allocating globals with code breaks freeMachineCodeForFunction - /// and is probably unsafe and bad for performance. However, we have clients - /// who depend on this behavior, so we must support it. This option defaults - /// to false so that users of the new API can safely use the new memory - /// manager and free machine code. - EngineBuilder &setAllocateGVsWithCode(bool a) { - AllocateGVsWithCode = a; - return *this; - } - /// setMArch - Override the architecture set by the Module's triple. EngineBuilder &setMArch(StringRef march) { MArch.assign(march.begin(), march.end()); @@ -688,13 +575,6 @@ public: return *this; } - /// setUseMCJIT - Set whether the MC-JIT implementation should be used - /// (experimental). - EngineBuilder &setUseMCJIT(bool Value) { - UseMCJIT = Value; - return *this; - } - /// setVerifyModules - Set whether the JIT implementation should verify /// IR modules during compilation. EngineBuilder &setVerifyModules(bool Verify) { diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h deleted file mode 100644 index 581d6e6c35eb..000000000000 --- a/include/llvm/ExecutionEngine/JIT.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file forces the JIT to link in on certain operating systems. -// (Windows). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_JIT_H -#define LLVM_EXECUTIONENGINE_JIT_H - -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include <cstdlib> - -extern "C" void LLVMLinkInJIT(); - -namespace { - struct ForceJITLinking { - ForceJITLinking() { - // We must reference JIT in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - if (std::getenv("bar") != (char*) -1) - return; - - LLVMLinkInJIT(); - } - } ForceJITLinking; -} - -#endif diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index 99fe36c6b5f6..c3edec868783 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "RuntimeDyld.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" @@ -25,7 +26,10 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; -class ObjectImage; + +namespace object { + class ObjectFile; +} /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -57,24 +61,7 @@ public: public: JITEventListener() {} - virtual ~JITEventListener(); - - /// NotifyFunctionEmitted - Called after a function has been successfully - /// emitted to memory. The function still has its MachineFunction attached, - /// if you should happen to need that. - virtual void NotifyFunctionEmitted(const Function &, - void *, size_t, - const EmittedFunctionDetails &) {} - - /// NotifyFreeingMachineCode - Called from freeMachineCodeForFunction(), after - /// the global mapping is removed, but before the machine code is returned to - /// the allocator. - /// - /// OldPtr is the address of the machine code and will be the same as the Code - /// parameter to a previous NotifyFunctionEmitted call. The Function passed - /// to NotifyFunctionEmitted may have been destroyed by the time of the - /// matching NotifyFreeingMachineCode call. - virtual void NotifyFreeingMachineCode(void *) {} + virtual ~JITEventListener() {} /// NotifyObjectEmitted - Called after an object has been successfully /// emitted to memory. NotifyFunctionEmitted will not be called for @@ -84,11 +71,15 @@ public: /// The ObjectImage contains the generated object image /// with section headers updated to reflect the address at which sections /// were loaded and with relocations performed in-place on debug sections. - virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} /// NotifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + + // Get a pointe to the GDB debugger registration listener. + static JITEventListener *createGDBRegistrationListener(); #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener @@ -122,7 +113,8 @@ public: return nullptr; } #endif // USE_OPROFILE - +private: + virtual void anchor(); }; } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h deleted file mode 100644 index b22d899c9fec..000000000000 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ /dev/null @@ -1,164 +0,0 @@ -//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H -#define LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H - -#include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Support/DataTypes.h" -#include <string> - -namespace llvm { - - class Function; - class GlobalValue; - -/// JITMemoryManager - This interface is used by the JIT to allocate and manage -/// memory for the code generated by the JIT. This can be reimplemented by -/// clients that have a strong desire to control how the layout of JIT'd memory -/// works. -class JITMemoryManager : public RTDyldMemoryManager { -protected: - bool HasGOT; - -public: - JITMemoryManager() : HasGOT(false) {} - virtual ~JITMemoryManager(); - - /// CreateDefaultMemManager - This is used to create the default - /// JIT Memory Manager if the client does not provide one to the JIT. - static JITMemoryManager *CreateDefaultMemManager(); - - /// setMemoryWritable - When code generation is in progress, - /// the code pages may need permissions changed. - virtual void setMemoryWritable() = 0; - - /// setMemoryExecutable - When code generation is done and we're ready to - /// start execution, the code pages may need permissions changed. - virtual void setMemoryExecutable() = 0; - - /// setPoisonMemory - Setting this flag to true makes the memory manager - /// garbage values over freed memory. This is useful for testing and - /// debugging, and may be turned on by default in debug mode. - virtual void setPoisonMemory(bool poison) = 0; - - //===--------------------------------------------------------------------===// - // Global Offset Table Management - //===--------------------------------------------------------------------===// - - /// AllocateGOT - If the current table requires a Global Offset Table, this - /// method is invoked to allocate it. This method is required to set HasGOT - /// to true. - virtual void AllocateGOT() = 0; - - /// isManagingGOT - Return true if the AllocateGOT method is called. - bool isManagingGOT() const { - return HasGOT; - } - - /// getGOTBase - If this is managing a Global Offset Table, this method should - /// return a pointer to its base. - virtual uint8_t *getGOTBase() const = 0; - - //===--------------------------------------------------------------------===// - // Main Allocation Functions - //===--------------------------------------------------------------------===// - - /// startFunctionBody - When we start JITing a function, the JIT calls this - /// method to allocate a block of free RWX memory, which returns a pointer to - /// it. If the JIT wants to request a block of memory of at least a certain - /// size, it passes that value as ActualSize, and this method returns a block - /// with at least that much space. If the JIT doesn't know ahead of time how - /// much space it will need to emit the function, it passes 0 for the - /// ActualSize. In either case, this method is required to pass back the size - /// of the allocated block through ActualSize. The JIT will be careful to - /// not write more than the returned ActualSize bytes of memory. - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) = 0; - - /// allocateStub - This method is called by the JIT to allocate space for a - /// function stub (used to handle limited branch displacements) while it is - /// JIT compiling a function. For example, if foo calls bar, and if bar - /// either needs to be lazily compiled or is a native function that exists too - /// far away from the call site to work, this method will be used to make a - /// thunk for it. The stub should be "close" to the current function body, - /// but should not be included in the 'actualsize' returned by - /// startFunctionBody. - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) = 0; - - /// endFunctionBody - This method is called when the JIT is done codegen'ing - /// the specified function. At this point we know the size of the JIT - /// compiled function. This passes in FunctionStart (which was returned by - /// the startFunctionBody method) and FunctionEnd which is a pointer to the - /// actual end of the function. This method should mark the space allocated - /// and remember where it is in case the client wants to deallocate it. - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) = 0; - - /// allocateSpace - Allocate a memory block of the given size. This method - /// cannot be called between calls to startFunctionBody and endFunctionBody. - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; - - /// allocateGlobal - Allocate memory for a global. - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; - - /// deallocateFunctionBody - Free the specified function body. The argument - /// must be the return value from a call to startFunctionBody() that hasn't - /// been deallocated yet. This is never called when the JIT is currently - /// emitting a function. - virtual void deallocateFunctionBody(void *Body) = 0; - - /// CheckInvariants - For testing only. Return true if all internal - /// invariants are preserved, or return false and set ErrorStr to a helpful - /// error message. - virtual bool CheckInvariants(std::string &) { - return true; - } - - /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultCodeSlabSize() { - return 0; - } - - /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultDataSlabSize() { - return 0; - } - - /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultStubSlabSize() { - return 0; - } - - /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for code. - virtual unsigned GetNumCodeSlabs() { - return 0; - } - - /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for data. - virtual unsigned GetNumDataSlabs() { - return 0; - } - - /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for function stubs. - virtual unsigned GetNumStubSlabs() { - return 0; - } -}; - -} // end namespace llvm. - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h deleted file mode 100644 index 6221d3b335df..000000000000 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ /dev/null @@ -1,83 +0,0 @@ -//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a wrapper class to hold the memory into which an -// object will be generated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// ObjectBuffer - This class acts as a container for the memory buffer used during -/// generation and loading of executable objects using MCJIT and RuntimeDyld. The -/// underlying memory for the object will be owned by the ObjectBuffer instance -/// throughout its lifetime. The getMemBuffer() method provides a way to create a -/// MemoryBuffer wrapper object instance to be owned by other classes (such as -/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the -/// actual memory it points to. -class ObjectBuffer { - virtual void anchor(); -public: - ObjectBuffer() {} - ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} - virtual ~ObjectBuffer() {} - - /// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function - /// returns a pointer to an object that is owned by the caller. However, - /// the caller does not take ownership of the underlying memory. - MemoryBuffer *getMemBuffer() const { - return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), - Buffer->getBufferIdentifier(), false); - } - - const char *getBufferStart() const { return Buffer->getBufferStart(); } - size_t getBufferSize() const { return Buffer->getBufferSize(); } - StringRef getBuffer() const { return Buffer->getBuffer(); } - -protected: - // The memory contained in an ObjectBuffer - std::unique_ptr<MemoryBuffer> Buffer; -}; - -/// ObjectBufferStream - This class encapsulates the SmallVector and -/// raw_svector_ostream needed to generate an object using MC code emission -/// while providing a common ObjectBuffer interface for access to the -/// memory once the object has been generated. -class ObjectBufferStream : public ObjectBuffer { - void anchor() override; -public: - ObjectBufferStream() : OS(SV) {} - virtual ~ObjectBufferStream() {} - - raw_ostream &getOStream() { return OS; } - void flush() - { - OS.flush(); - - // Make the data accessible via the ObjectBuffer::Buffer - Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), - "", - false)); - } - -protected: - SmallVector<char, 4096> SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index d1849dfc3bf6..cc01a4e58999 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -27,13 +27,12 @@ public: virtual ~ObjectCache() { } /// notifyObjectCompiled - Provides a pointer to compiled code for Module M. - virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) = 0; + virtual void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) = 0; - /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that - /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns both the MemoryBuffer returned by this - /// and the memory it references. - virtual MemoryBuffer* getObject(const Module* M) = 0; + /// Returns a pointer to a newly allocated MemoryBuffer that contains the + /// object which corresponds with Module M, or 0 if an object is not + /// available. + virtual std::unique_ptr<MemoryBuffer> getObject(const Module* M) = 0; }; } diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h deleted file mode 100644 index 1fcedd8d6a92..000000000000 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ /dev/null @@ -1,71 +0,0 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H -#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - - -/// ObjectImage - A container class that represents an ObjectFile that has been -/// or is in the process of being loaded into memory for execution. -class ObjectImage { - ObjectImage() LLVM_DELETED_FUNCTION; - ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; - virtual void anchor(); - -protected: - std::unique_ptr<ObjectBuffer> Buffer; - -public: - ObjectImage(ObjectBuffer *Input) : Buffer(Input) {} - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const = 0; - virtual object::symbol_iterator end_symbols() const = 0; - iterator_range<object::symbol_iterator> symbols() const { - return iterator_range<object::symbol_iterator>(begin_symbols(), - end_symbols()); - } - - virtual object::section_iterator begin_sections() const = 0; - virtual object::section_iterator end_sections() const = 0; - iterator_range<object::section_iterator> sections() const { - return iterator_range<object::section_iterator>(begin_sections(), - end_sections()); - } - - virtual /* Triple::ArchType */ unsigned getArch() const = 0; - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; - virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; - - virtual StringRef getData() const = 0; - - virtual object::ObjectFile* getObjectFile() const = 0; - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() = 0; - virtual void deregisterWithDebugger() = 0; -}; - -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index b1d6810f374b..ef81cd328bdb 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H -#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" @@ -22,7 +22,10 @@ namespace llvm { class ExecutionEngine; -class ObjectImage; + + namespace object { + class ObjectFile; + } // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of @@ -76,9 +79,15 @@ public: virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + /// This method returns the address of the specified function or variable in + /// the current process. + static uint64_t getSymbolAddressInProcess(const std::string &Name); + /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. - virtual uint64_t getSymbolAddress(const std::string &Name); + virtual uint64_t getSymbolAddress(const std::string &Name) { + return getSymbolAddressInProcess(Name); + } /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. @@ -103,7 +112,7 @@ public: /// address space can use this call to remap the section addresses for the /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *) {} + const object::ObjectFile &) {} /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation @@ -123,4 +132,4 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS( } // namespace llvm -#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#endif diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index f123ffb803bd..799fc34eb659 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,58 +15,75 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include <memory> namespace llvm { namespace object { class ObjectFile; + template <typename T> class OwningBinary; } class RuntimeDyldImpl; -class ObjectImage; +class RuntimeDyldCheckerImpl; class RuntimeDyld { - friend class RuntimeDyldChecker; + friend class RuntimeDyldCheckerImpl; RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public // interface. - RuntimeDyldImpl *Dyld; + std::unique_ptr<RuntimeDyldImpl> Dyld; RTDyldMemoryManager *MM; bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + + /// \brief Information about the loaded object. + class LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual ~LoadedObjectInfo() {} + + virtual object::OwningBinary<object::ObjectFile> + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t getSectionLoadAddress(StringRef Name) const; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + unsigned BeginIdx, EndIdx; + }; + RuntimeDyld(RTDyldMemoryManager *); ~RuntimeDyld(); - /// Prepare the object contained in the input buffer for execution. - /// Ownership of the input buffer is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input buffer will be deleted. - ObjectImage *loadObject(ObjectBuffer *InputBuffer); - - /// Prepare the referenced object file for execution. - /// Ownership of the input object is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input object will be deleted. - ObjectImage *loadObject(std::unique_ptr<object::ObjectFile> InputObject); + /// Add the referenced object file to the list of objects to be loaded and + /// relocated. + std::unique_ptr<LoadedObjectInfo> loadObject(const object::ObjectFile &O); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). - void *getSymbolAddress(StringRef Name); + void *getSymbolAddress(StringRef Name) const; /// Get the address of the target copy of the symbol. This is the address /// used for relocation. - uint64_t getSymbolLoadAddress(StringRef Name); + uint64_t getSymbolLoadAddress(StringRef Name) const; /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 8dd891e83648..35ceba27596c 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -7,18 +7,19 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDCHECKER_H -#define LLVM_RUNTIMEDYLDCHECKER_H +#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H +#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H -#include "RuntimeDyld.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <map> +#include "llvm/ADT/StringRef.h" namespace llvm { class MCDisassembler; +class MemoryBuffer; class MCInstPrinter; +class RuntimeDyld; +class RuntimeDyldCheckerImpl; +class raw_ostream; /// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has /// correctly applied relocations. @@ -61,14 +62,16 @@ class MCInstPrinter; /// | expr '>>' expr /// class RuntimeDyldChecker { - friend class RuntimeDyldCheckerExprEval; public: - RuntimeDyldChecker(RuntimeDyld &RTDyld, - MCDisassembler *Disassembler, - MCInstPrinter *InstPrinter, - llvm::raw_ostream &ErrStream) - : RTDyld(*RTDyld.Dyld), Disassembler(Disassembler), - InstPrinter(InstPrinter), ErrStream(ErrStream) {} + RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, raw_ostream &ErrStream); + ~RuntimeDyldChecker(); + + // \brief Get the associated RTDyld instance. + RuntimeDyld& getRTDyld(); + + // \brief Get the associated RTDyld instance. + const RuntimeDyld& getRTDyld() const; /// \brief Check a single expression against the attached RuntimeDyld /// instance. @@ -79,20 +82,20 @@ public: /// method to be evaluated as an expression. bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; -private: + /// \brief Returns the address of the requested section (or an error message + /// in the second element of the pair if the address cannot be found). + /// + /// if 'LinkerAddress' is true, this returns the address of the section + /// within the linker's memory. If 'LinkerAddress' is false it returns the + /// address within the target process (i.e. the load address). + std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName, + StringRef SectionName, + bool LinkerAddress); - bool isSymbolValid(StringRef Symbol) const; - uint64_t getSymbolAddress(StringRef Symbol) const; - uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset, - unsigned Size) const; - StringRef getSubsectionStartingAt(StringRef Name) const; - - RuntimeDyldImpl &RTDyld; - MCDisassembler *Disassembler; - MCInstPrinter *InstPrinter; - llvm::raw_ostream &ErrStream; +private: + std::unique_ptr<RuntimeDyldCheckerImpl> Impl; }; } // end namespace llvm -#endif // LLVM_RUNTIMEDYLDCHECKER_H +#endif diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 7c398a5e5530..dd76a90aa5ea 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -105,6 +105,14 @@ public: /// its containing function. bool hasInAllocaAttr() const; + /// \brief Return true if this argument has the zext attribute on it in its + /// containing function. + bool hasZExtAttr() const; + + /// \brief Return true if this argument has the sext attribute on it in its + /// containing function. + bool hasSExtAttr() const; + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/IR/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h index a8d52f68176c..19e32a2dcdcc 100644 --- a/include/llvm/IR/AssemblyAnnotationWriter.h +++ b/include/llvm/IR/AssemblyAnnotationWriter.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_ASMANNOTATIONWRITER_H -#define LLVM_IR_ASMANNOTATIONWRITER_H +#ifndef LLVM_IR_ASSEMBLYANNOTATIONWRITER_H +#define LLVM_IR_ASSEMBLYANNOTATIONWRITER_H namespace llvm { diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index a19489aa49b1..7c7dd2ca5643 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -23,6 +23,7 @@ namespace llvm { +class CallInst; class LandingPadInst; class TerminatorInst; class LLVMContext; @@ -125,6 +126,14 @@ public: TerminatorInst *getTerminator(); const TerminatorInst *getTerminator() const; + /// \brief Returns the call instruction marked 'musttail' prior to the + /// terminating return instruction of this basic block, if such a call is + /// present. Otherwise, returns null. + CallInst *getTerminatingMustTailCall(); + const CallInst *getTerminatingMustTailCall() const { + return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall(); + } + /// \brief Returns a pointer to the first instruction in this block that is /// not a PHINode instruction. /// @@ -173,6 +182,13 @@ public: /// right after \p MovePos in the function \p MovePos lives in. void moveAfter(BasicBlock *MovePos); + /// \brief Insert unlinked basic block into a function. + /// + /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is + /// provided, inserts before that basic block, otherwise inserts at the end. + /// + /// \pre \a getParent() is \c nullptr. + void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); /// \brief Return the predecessor of this block if it has a single predecessor /// block. Otherwise return a null pointer. diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index c8be8bd1f2a7..5400d2384868 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -93,6 +93,9 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } +inline bool pred_empty(const BasicBlock *BB) { + return pred_begin(BB) == pred_end(BB); +} @@ -257,6 +260,9 @@ inline succ_iterator succ_end(BasicBlock *BB) { inline succ_const_iterator succ_end(const BasicBlock *BB) { return succ_const_iterator(BB->getTerminator(), true); } +inline bool succ_empty(const BasicBlock *BB) { + return succ_begin(BB) == succ_end(BB); +} template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > { static const bool value = isPodLike<T>::value; diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 1eaf4f7f469f..9872e6ec794d 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -20,10 +20,13 @@ namespace llvm { /// the well-known calling conventions. /// namespace CallingConv { + /// LLVM IR allows to use arbitrary numbers as calling convention identifiers. + typedef unsigned ID; + /// A set of enums which specify the assigned numeric values for known llvm /// calling conventions. /// @brief LLVM Calling Convention Representation - enum ID { + enum { /// C - The default llvm calling convention, compatible with C. This /// convention is the only calling convention that supports varargs calls. /// As with typical C calling conventions, the callee/caller have to @@ -137,7 +140,11 @@ namespace CallingConv { /// convention differs from the more common \c X86_64_SysV convention /// in a number of ways, most notably in that XMM registers used to pass /// arguments are shadowed by GPRs, and vice versa. - X86_64_Win64 = 79 + X86_64_Win64 = 79, + + /// \brief MSVC calling convention that passes vectors and vector aggregates + /// in SSE registers. + X86_VectorCall = 80 }; } // End CallingConv namespace diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 82ad9fc2f407..d26991eaab75 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -48,11 +48,16 @@ protected: : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); + void replaceUsesOfWithOnConstantImpl(Constant *Replacement); + public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. bool isNullValue() const; + /// \brief Returns true if the value is one. + bool isOneValue() const; + /// isAllOnesValue - Return true if this is the value that would be returned by /// getAllOnesValue. bool isAllOnesValue() const; @@ -64,6 +69,9 @@ public: /// Return true if the value is negative zero or null value. bool isZeroValue() const; + /// \brief Return true if the value is not the smallest signed value. + bool isNotMinSignedValue() const; + /// \brief Return true if the value is the smallest signed value. bool isMinSignedValue() const; diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 342422cbe25f..5e8cd34c4d69 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -29,15 +29,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CONSTANTRANGE_H -#define LLVM_SUPPORT_CONSTANTRANGE_H +#ifndef LLVM_IR_CONSTANTRANGE_H +#define LLVM_IR_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" #include "llvm/Support/DataTypes.h" namespace llvm { -/// ConstantRange - This class represents an range of values. +/// This class represents a range of values. /// class ConstantRange { APInt Lower, Upper; @@ -59,7 +59,7 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// makeICmpRegion - Produce the smallest range that contains all values that + /// Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value /// contained within Other. /// @@ -69,47 +69,46 @@ public: static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); - /// getLower - Return the lower value for this range... + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } - /// getUpper - Return the upper value for this range... + /// Return the upper value for this range. /// const APInt &getUpper() const { return Upper; } - /// getBitWidth - get the bit width of this ConstantRange + /// Get the bit width of this ConstantRange. /// uint32_t getBitWidth() const { return Lower.getBitWidth(); } - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type + /// Return true if this set contains all of the elements possible + /// for this data-type. /// bool isFullSet() const; - /// isEmptySet - Return true if this set contains no members. + /// Return true if this set contains no members. /// bool isEmptySet() const; - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) + /// Return true if this set wraps around the top of the range. + /// For example: [100, 8). /// bool isWrappedSet() const; - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). + /// Return true if this set wraps around the INT_MIN of + /// its bitwidth. For example: i8 [120, 140). /// bool isSignWrappedSet() const; - /// contains - Return true if the specified value is in the set. + /// Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; - /// contains - Return true if the other range is a subset of this one. + /// Return true if the other range is a subset of this one. /// bool contains(const ConstantRange &CR) const; - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. + /// If this set contains a single element, return it, otherwise return null. /// const APInt *getSingleElement() const { if (Upper == Lower + 1) @@ -117,35 +116,31 @@ public: return nullptr; } - /// isSingleElement - Return true if this set contains exactly one member. + /// Return true if this set contains exactly one member. /// bool isSingleElement() const { return getSingleElement() != nullptr; } - /// getSetSize - Return the number of elements in this set. + /// Return the number of elements in this set. /// APInt getSetSize() const; - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. + /// Return the largest unsigned value contained in the ConstantRange. /// APInt getUnsignedMax() const; - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. + /// Return the smallest unsigned value contained in the ConstantRange. /// APInt getUnsignedMin() const; - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. + /// Return the largest signed value contained in the ConstantRange. /// APInt getSignedMax() const; - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. + /// Return the smallest signed value contained in the ConstantRange. /// APInt getSignedMin() const; - /// operator== - Return true if this range is equal to another range. + /// Return true if this range is equal to another range. /// bool operator==(const ConstantRange &CR) const { return Lower == CR.Lower && Upper == CR.Upper; @@ -154,15 +149,14 @@ public: return !operator==(CR); } - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; /// \brief Subtract the specified range from this range (aka relative /// complement of the sets). ConstantRange difference(const ConstantRange &CR) const; - /// intersectWith - Return the range that results from the intersection of + /// Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the /// smallest possible set size that does so. Because there may be two @@ -171,7 +165,7 @@ public: /// ConstantRange intersectWith(const ConstantRange &CR) const; - /// unionWith - Return the range that results from the union of this range + /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included @@ -179,85 +173,84 @@ public: /// ConstantRange unionWith(const ConstantRange &CR) const; - /// zeroExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// zero extended to BitWidth. ConstantRange zeroExtend(uint32_t BitWidth) const; - /// signExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// sign extended to BitWidth. ConstantRange signExtend(uint32_t BitWidth) const; - /// truncate - Return a new range in the specified integer type, which must be + /// Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// truncated to the specified type. ConstantRange truncate(uint32_t BitWidth) const; - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is zero extended, truncated, or left alone to make it that width. ConstantRange zextOrTrunc(uint32_t BitWidth) const; - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is sign extended, truncated, or left alone to make it that width. ConstantRange sextOrTrunc(uint32_t BitWidth) const; - /// add - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an addition of a value in this range and a value in \p Other. ConstantRange add(const ConstantRange &Other) const; - /// sub - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a subtraction of a value in this range and a value in \p Other. ConstantRange sub(const ConstantRange &Other) const; - /// multiply - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a multiplication of a value in this range and a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange multiply(const ConstantRange &Other) const; - /// smax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a signed maximum of a value in this range and a value in \p Other. ConstantRange smax(const ConstantRange &Other) const; - /// umax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned maximum of a value in this range and a value in \p Other. ConstantRange umax(const ConstantRange &Other) const; - /// udiv - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; - /// binaryAnd - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; - /// binaryOr - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-or of a value in this range by a value in \p Other. ConstantRange binaryOr(const ConstantRange &Other) const; - /// shl - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange shl(const ConstantRange &Other) const; - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. + /// Return a new range representing the possible values resulting from a + /// logical right shift of a value in this range and a value in \p Other. ConstantRange lshr(const ConstantRange &Other) const; - /// inverse - Return a new range that is the logical not of the current set. + /// Return a new range that is the logical not of the current set. /// ConstantRange inverse() const; - /// print - Print out the bounds to a stream... + /// Print out the bounds to a stream. /// void print(raw_ostream &OS) const; - /// dump - Allow printing from a debugger easily... + /// Allow printing from a debugger easily. /// void dump() const; }; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 0e72f040d3e0..1b0e1b7e7b77 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -37,12 +37,8 @@ class PointerType; class VectorType; class SequentialType; -template<class ConstantClass, class TypeClass, class ValType> -struct ConstantCreator; -template<class ConstantClass, class TypeClass> -struct ConstantArrayCreator; -template<class ConstantClass, class TypeClass> -struct ConvertConstantType; +struct ConstantExprKeyType; +template <class ConstantClass> struct ConstantAggrKeyType; //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class @@ -268,6 +264,9 @@ public: /// isNegative - Return true if the sign bit is set. bool isNegative() const { return Val.isNegative(); } + /// isInfinity - Return true if the value is infinity + bool isInfinity() const { return Val.isInfinity(); } + /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Val.isNaN(); } @@ -338,7 +337,7 @@ public: /// ConstantArray - Constant Array Declarations /// class ConstantArray : public Constant { - friend struct ConstantArrayCreator<ConstantArray, ArrayType>; + friend struct ConstantAggrKeyType<ConstantArray>; ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; protected: ConstantArray(ArrayType *T, ArrayRef<Constant *> Val); @@ -346,6 +345,10 @@ public: // ConstantArray accessors static Constant *get(ArrayType *T, ArrayRef<Constant*> V); +private: + static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V); + +public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -376,14 +379,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // ConstantStruct - Constant Struct Declarations // class ConstantStruct : public Constant { - friend struct ConstantArrayCreator<ConstantStruct, StructType>; + friend struct ConstantAggrKeyType<ConstantStruct>; ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; protected: ConstantStruct(StructType *T, ArrayRef<Constant *> Val); public: // ConstantStruct accessors static Constant *get(StructType *T, ArrayRef<Constant*> V); - static Constant *get(StructType *T, ...) END_WITH_NULL; + static Constant *get(StructType *T, ...) LLVM_END_WITH_NULL; /// getAnon - Return an anonymous struct that has the specified /// elements. If the struct is possibly empty, then you must specify a @@ -435,7 +438,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// ConstantVector - Constant Vector Declarations /// class ConstantVector : public Constant { - friend struct ConstantArrayCreator<ConstantVector, VectorType>; + friend struct ConstantAggrKeyType<ConstantVector>; ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; protected: ConstantVector(VectorType *T, ArrayRef<Constant *> Val); @@ -443,6 +446,10 @@ public: // ConstantVector accessors static Constant *get(ArrayRef<Constant*> V); +private: + static Constant *getImpl(ArrayRef<Constant *> V); + +public: /// getSplat - Return a ConstantVector with the specified constant in each /// element. static Constant *getSplat(unsigned NumElts, Constant *Elt); @@ -794,9 +801,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) /// constant expressions. The Opcode field for the ConstantExpr class is /// maintained in the Value::SubclassData field. class ConstantExpr : public Constant { - friend struct ConstantCreator<ConstantExpr,Type, - std::pair<unsigned, std::vector<Constant*> > >; - friend struct ConvertConstantType<ConstantExpr, Type>; + friend struct ConstantExprKeyType; protected: ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) @@ -856,19 +861,25 @@ public: bool HasNUW = false, bool HasNSW = false); static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getTrunc (Constant *C, Type *Ty); - static Constant *getSExt (Constant *C, Type *Ty); - static Constant *getZExt (Constant *C, Type *Ty); - static Constant *getFPTrunc (Constant *C, Type *Ty); - static Constant *getFPExtend(Constant *C, Type *Ty); - static Constant *getUIToFP (Constant *C, Type *Ty); - static Constant *getSIToFP (Constant *C, Type *Ty); - static Constant *getFPToUI (Constant *C, Type *Ty); - static Constant *getFPToSI (Constant *C, Type *Ty); - static Constant *getPtrToInt(Constant *C, Type *Ty); - static Constant *getIntToPtr(Constant *C, Type *Ty); - static Constant *getBitCast (Constant *C, Type *Ty); - static Constant *getAddrSpaceCast(Constant *C, Type *Ty); + static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getSExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getZExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPTrunc(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getFPExtend(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getPtrToInt(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getIntToPtr(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getBitCast(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getAddrSpaceCast(Constant *C, Type *Ty, + bool OnlyIfReduced = false); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -923,13 +934,14 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - // @brief Convenience function for getting one of the casting operations - // using a CastOps opcode. - static Constant *getCast( - unsigned ops, ///< The opcode for the conversion - Constant *C, ///< The constant to be converted - Type *Ty ///< The type to which the constant is converted - ); + /// \brief Convenience function for getting a Cast operation. + /// + /// \param ops The opcode for the conversion + /// \param C The constant to be converted + /// \param Ty The type to which the constant is converted + /// \param OnlyIfReduced see \a getWithOperands() docs. + static Constant *getCast(unsigned ops, Constant *C, Type *Ty, + bool OnlyIfReduced = false); // @brief Create a ZExt or BitCast cast constant expression static Constant *getZExtOrBitCast( @@ -995,44 +1007,53 @@ public: /// Select constant expr /// - static Constant *getSelect(Constant *C, Constant *V1, Constant *V2); + /// \param OnlyIfReducedTy see \a getWithOperands() docs. + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2, + Type *OnlyIfReducedTy = nullptr); /// get - Return a binary or shift operator constant expression, /// folding if possible. /// + /// \param OnlyIfReducedTy see \a getWithOperands() docs. static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags = 0); + unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr); - /// @brief Return an ICmp or FCmp comparison operator constant expression. - static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + /// \brief Return an ICmp or FCmp comparison operator constant expression. + /// + /// \param OnlyIfReduced see \a getWithOperands() docs. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2, + bool OnlyIfReduced = false); /// get* - Return some common constants without having to /// specify the full Instruction::OPCODE identifier. /// - static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); - static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); + static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS, + bool OnlyIfReduced = false); + static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS, + bool OnlyIfReduced = false); /// Getelementptr form. Value* is only accepted for convenience; /// all elements must be Constant's. /// - static Constant *getGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList, - bool InBounds = false) { - return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(), - IdxList.size()), - InBounds); - } - static Constant *getGetElementPtr(Constant *C, - Constant *Idx, - bool InBounds = false) { + /// \param OnlyIfReducedTy see \a getWithOperands() docs. + static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr) { + return getGetElementPtr( + C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + InBounds, OnlyIfReducedTy); + } + static Constant *getGetElementPtr(Constant *C, Constant *Idx, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, cast<Value>(Idx), InBounds); + return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList, - bool InBounds = false); + static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. @@ -1052,12 +1073,17 @@ public: return getGetElementPtr(C, IdxList, true); } - static Constant *getExtractElement(Constant *Vec, Constant *Idx); - static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); - static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); - static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs); + static Constant *getExtractElement(Constant *Vec, Constant *Idx, + Type *OnlyIfReducedTy = nullptr); + static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx, + Type *OnlyIfReducedTy = nullptr); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask, + Type *OnlyIfReducedTy = nullptr); + static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs, + Type *OnlyIfReducedTy = nullptr); static Constant *getInsertValue(Constant *Agg, Constant *Val, - ArrayRef<unsigned> Idxs); + ArrayRef<unsigned> Idxs, + Type *OnlyIfReducedTy = nullptr); /// getOpcode - Return the opcode at the root of this constant expression unsigned getOpcode() const { return getSubclassDataFromValue(); } @@ -1084,11 +1110,17 @@ public: return getWithOperands(Ops, getType()); } - /// getWithOperands - This returns the current constant expression with the - /// operands replaced with the specified values and with the specified result - /// type. The specified array must have the same number of operands as our - /// current one. - Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const; + /// \brief Get the current expression with the operands replaced. + /// + /// Return the current constant expression with the operands replaced with \c + /// Ops and the type with \c Ty. The new operands must have the same number + /// as the current ones. + /// + /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something + /// gets constant-folded, the type changes, or the expression is otherwise + /// canonicalized. This parameter should almost always be \c false. + Constant *getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, + bool OnlyIfReduced = false) const; /// getAsInstruction - Returns an Instruction which implements the same operation /// as this ConstantExpr. The instruction is not linked to any basic block. diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 267350409604..ae1ac650a9ec 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" @@ -27,6 +28,7 @@ namespace llvm { class Function; class Module; class Value; + class Constant; class LLVMContext; class MDNode; class StringRef; @@ -38,7 +40,6 @@ namespace llvm { class DIFile; class DIEnumerator; class DIType; - class DIArray; class DIGlobalVariable; class DIImportedEntity; class DINameSpace; @@ -53,7 +54,6 @@ namespace llvm { class DIObjCProperty; class DIBuilder { - private: Module &M; LLVMContext &VMContext; @@ -66,27 +66,34 @@ namespace llvm { Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value - SmallVector<Value *, 4> AllEnumTypes; - /// Use TrackingVH to collect RetainTypes, since they can be updated - /// later on. - SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes; - SmallVector<Value *, 4> AllSubprograms; - SmallVector<Value *, 4> AllGVs; - SmallVector<TrackingVH<MDNode>, 4> AllImportedModules; + SmallVector<Metadata *, 4> AllEnumTypes; + /// Track the RetainTypes, since they can be updated later on. + SmallVector<TrackingMDNodeRef, 4> AllRetainTypes; + SmallVector<Metadata *, 4> AllSubprograms; + SmallVector<Metadata *, 4> AllGVs; + SmallVector<TrackingMDNodeRef, 4> AllImportedModules; - // Private use for multiple types of template parameters. - DITemplateValueParameter - createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIType Ty, Value *Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + /// \brief Track nodes that may be unresolved. + SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes; + bool AllowUnresolvedNodes; + + /// Each subprogram's preserved local variables. + DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables; DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; - public: - explicit DIBuilder(Module &M); - enum ComplexAddrKind { OpPlus=1, OpDeref }; + /// \brief Create a temporary. + /// + /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes. + void trackIfUnresolved(MDNode *N); + + public: + /// \brief Construct a builder for a module. + /// + /// If \c AllowUnresolved, collect unresolved nodes attached to the module + /// in order to resolve cycles during \a finalize(). + explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. @@ -165,8 +172,12 @@ namespace llvm { /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. @@ -218,36 +229,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType - createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, DIType Ty, - unsigned Flags, llvm::Value *Val); - - /// createObjCIVar - Create debugging information entry for Objective-C - /// instance variable. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. - /// @param PropertyName Name of the Objective C property associated with - /// this ivar. - /// @param PropertyGetterName Name of the Objective C property getter - /// selector. - /// @param PropertySetterName Name of the Objective C property setter - /// selector. - /// @param PropertyAttributes Objective C property attributes. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - StringRef PropertyName = StringRef(), - StringRef PropertyGetterName = StringRef(), - StringRef PropertySetterName = StringRef(), - unsigned PropertyAttributes = 0); + DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo, + DIType Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -366,8 +351,8 @@ namespace llvm { /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, Value *Val, MDNode *File = nullptr, + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + Constant *Val, MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); /// \brief Create debugging information for a template template parameter. @@ -435,8 +420,9 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes, - unsigned Flags = 0); + DISubroutineType createSubroutineType(DIFile File, + DITypeArray ParameterTypes, + unsigned Flags = 0); /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); @@ -463,44 +449,22 @@ namespace llvm { /// through debug info anchors. void retainType(DIType T); - /// createUnspecifiedParameter - Create unspecified type descriptor + /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIDescriptor createUnspecifiedParameter(); + DIBasicType createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef<Value *> Elements); + DIArray getOrCreateArray(ArrayRef<Metadata *> Elements); + + /// getOrCreateTypeArray - Get a DITypeArray, create one if required. + DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - /// createGlobalVariable - Create a new descriptor for the specified global. - /// @param Name Name of the variable. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is - /// externally visible or not. - /// @param Val llvm::Value of the variable. - DIGlobalVariable - createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, - DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val); - /// \brief Create a new descriptor for the specified global. - /// @param Name Name of the variable. - /// @param LinkageName Mangled variable name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is - /// externally visible or not. - /// @param Val llvm::Value of the variable. - DIGlobalVariable - createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Value *Val); - - /// createStaticVariable - Create a new descriptor for the specified + /// createGlobalVariable - Create a new descriptor for the specified /// variable. /// @param Context Variable scope. /// @param Name Name of the variable. @@ -512,12 +476,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable - createStaticVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, unsigned LineNo, - DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val, - MDNode *Decl = nullptr); - + DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, + unsigned LineNo, DITypeRef Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); + + /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable + /// except that the resulting DbgNode is temporary and meant to be RAUWed. + DIGlobalVariable createTempGlobalVariableFwdDecl( + DIDescriptor Context, StringRef Name, StringRef LinkageName, + DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, + llvm::Constant *Val, MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -540,23 +511,18 @@ namespace llvm { unsigned Flags = 0, unsigned ArgNo = 0); - - /// createComplexVariable - Create a new descriptor for the specified + /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. - /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or - /// DW_TAG_arg_variable. - /// @param Scope Variable scope. - /// @param Name Variable name. - /// @param F File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type /// @param Addr An array of complex address operations. - /// @param ArgNo If this variable is an argument then this argument's - /// number. 1 indicates 1st argument. - DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIFile F, unsigned LineNo, - DITypeRef Ty, ArrayRef<Value *> Addr, - unsigned ArgNo = 0); + DIExpression createExpression(ArrayRef<int64_t> Addr = None); + + /// createPieceExpression - Create a descriptor to describe one part + /// of aggregate variable that is fragmented across multiple Values. + /// + /// @param OffsetInBytes Offset of the piece in bytes. + /// @param SizeInBytes Size of the piece in bytes. + DIExpression createPieceExpression(unsigned OffsetInBytes, + unsigned SizeInBytes); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -586,6 +552,21 @@ namespace llvm { MDNode *TParam = nullptr, MDNode *Decl = nullptr); + /// createTempFunctionFwdDecl - Identical to createFunction, + /// except that the resulting DbgNode is meant to be RAUWed. + DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = nullptr, + MDNode *TParam = nullptr, + MDNode *Decl = nullptr); + + /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. DISubprogram createFunction(DIScopeRef Scope, StringRef Name, @@ -646,8 +627,9 @@ namespace llvm { /// lexical block as it crosses a file. /// @param Scope Lexical block. /// @param File Source file. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, - DIFile File); + /// @param Discriminator DWARF path discriminator value. + DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -655,10 +637,8 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - /// @param Discriminator DWARF path discriminator value. DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col, - unsigned Discriminator); + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into @@ -679,7 +659,7 @@ namespace llvm { /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIScope Decl, + DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, unsigned Line, StringRef Name = StringRef()); DIImportedEntity createImportedDeclaration(DIScope Context, @@ -690,36 +670,52 @@ namespace llvm { /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - BasicBlock *InsertAtEnd); + DIExpression Expr, BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - Instruction *InsertBefore); - + DIExpression Expr, Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, DIExpression Expr, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 877029f92f0b..a9e75955ce74 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -27,7 +27,8 @@ #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" -// this needs to be outside of the namespace, to avoid conflict with llvm-c decl +// This needs to be outside of the namespace, to avoid conflict with llvm-c +// decl. typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; namespace llvm { @@ -45,79 +46,71 @@ class ArrayRef; /// Enum used to categorize the alignment types stored by LayoutAlignElem enum AlignTypeEnum { - INVALID_ALIGN = 0, ///< An invalid alignment - INTEGER_ALIGN = 'i', ///< Integer type alignment - VECTOR_ALIGN = 'v', ///< Vector type alignment - FLOAT_ALIGN = 'f', ///< Floating point type alignment - AGGREGATE_ALIGN = 'a' ///< Aggregate alignment + INVALID_ALIGN = 0, + INTEGER_ALIGN = 'i', + VECTOR_ALIGN = 'v', + FLOAT_ALIGN = 'f', + AGGREGATE_ALIGN = 'a' }; -/// Layout alignment element. +/// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, /// vector, float) and type bit width. /// -/// @note The unusual order of elements in the structure attempts to reduce +/// \note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct LayoutAlignElem { - unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum) - unsigned TypeBitWidth : 24; ///< Type bit width - unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw - unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw + /// \brief Alignment type from \c AlignTypeEnum + unsigned AlignType : 8; + unsigned TypeBitWidth : 24; + unsigned ABIAlign : 16; + unsigned PrefAlign : 16; - /// Initializer static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width); - /// Equality predicate bool operator==(const LayoutAlignElem &rhs) const; }; -/// Layout pointer alignment element. +/// \brief Layout pointer alignment element. /// /// Stores the alignment data associated with a given pointer and address space. /// -/// @note The unusual order of elements in the structure attempts to reduce +/// \note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct PointerAlignElem { - unsigned ABIAlign; ///< ABI alignment for this type/bitw - unsigned PrefAlign; ///< Pref. alignment for this type/bitw - uint32_t TypeByteWidth; ///< Type byte width - uint32_t AddressSpace; ///< Address space for the pointer type + unsigned ABIAlign; + unsigned PrefAlign; + uint32_t TypeByteWidth; + uint32_t AddressSpace; /// Initializer static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth); - /// Equality predicate + unsigned PrefAlign, uint32_t TypeByteWidth); bool operator==(const PointerAlignElem &rhs) const; }; -/// This class holds a parsed version of the target data layout string in a -/// module and provides methods for querying it. The target data layout string -/// is specified *by the target* - a frontend generating LLVM IR is required to -/// generate the right target data for the target being codegen'd to. +/// \brief A parsed version of the target data layout string in and methods for +/// querying it. +/// +/// The target data layout string is specified *by the target* - a frontend +/// generating LLVM IR is required to generate the right target data for the +/// target being codegen'd to. class DataLayout { private: - bool LittleEndian; ///< Defaults to false - unsigned StackNaturalAlign; ///< Stack natural alignment - - enum ManglingModeT { - MM_None, - MM_ELF, - MM_MachO, - MM_WINCOFF, - MM_Mips - }; + /// Defaults to false. + bool BigEndian; + + unsigned StackNaturalAlign; + + enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips }; ManglingModeT ManglingMode; - SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. + SmallVector<unsigned char, 8> LegalIntWidths; - /// Alignments - Where the primitive type alignment data is stored. - /// - /// @sa reset(). - /// @note Could support multiple size pointer alignments, e.g., 32-bit - /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now, - /// we don't. + /// \brief Primitive type alignment data. SmallVector<LayoutAlignElem, 16> Alignments; + typedef SmallVector<PointerAlignElem, 8> PointersTy; PointersTy Pointers; @@ -128,31 +121,28 @@ private: PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace); - /// InvalidAlignmentElem - This member is a signal that a requested alignment - /// type and bit width were not found in the SmallVector. + /// This member is a signal that a requested alignment type and bit width were + /// not found in the SmallVector. static const LayoutAlignElem InvalidAlignmentElem; - /// InvalidPointerElem - This member is a signal that a requested pointer - /// type and bit width were not found in the DenseSet. + /// This member is a signal that a requested pointer type and bit width were + /// not found in the DenseSet. static const PointerAlignElem InvalidPointerElem; // The StructType -> StructLayout map. mutable void *LayoutMap; - //! Set/initialize target alignments void setAlignment(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width); unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, bool ABIAlign, Type *Ty) const; - - //! Set/initialize pointer alignments void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, unsigned PrefAlign, uint32_t TypeByteWidth); - //! Internal helper method that returns requested alignment for type. + /// Internal helper method that returns requested alignment for type. unsigned getAlignment(Type *Ty, bool abi_or_pref) const; - /// Valid alignment predicate. + /// \brief Valid alignment predicate. /// /// Predicate that tests a LayoutAlignElem reference returned by get() against /// InvalidAlignmentElem. @@ -160,10 +150,10 @@ private: return &align != &InvalidAlignmentElem; } - /// Valid pointer predicate. + /// \brief Valid pointer predicate. /// - /// Predicate that tests a PointerAlignElem reference returned by get() against - /// InvalidPointerElem. + /// Predicate that tests a PointerAlignElem reference returned by get() + /// against \c InvalidPointerElem. bool validPointer(const PointerAlignElem &align) const { return &align != &InvalidPointerElem; } @@ -184,11 +174,13 @@ public: /// Initialize target data from properties stored in the module. explicit DataLayout(const Module *M); + void init(const Module *M); + DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; } DataLayout &operator=(const DataLayout &DL) { clear(); - LittleEndian = DL.isLittleEndian(); + BigEndian = DL.isBigEndian(); StackNaturalAlign = DL.StackNaturalAlign; ManglingMode = DL.ManglingMode; LegalIntWidths = DL.LegalIntWidths; @@ -200,27 +192,28 @@ public: bool operator==(const DataLayout &Other) const; bool operator!=(const DataLayout &Other) const { return !(*this == Other); } - ~DataLayout(); // Not virtual, do not subclass this class + ~DataLayout(); // Not virtual, do not subclass this class /// Parse a data layout string (with fallback to default values). void reset(StringRef LayoutDescription); /// Layout endianness... - bool isLittleEndian() const { return LittleEndian; } - bool isBigEndian() const { return !LittleEndian; } + bool isLittleEndian() const { return !BigEndian; } + bool isBigEndian() const { return BigEndian; } - /// getStringRepresentation - Return the string representation of the - /// DataLayout. This representation is in the same format accepted by the - /// string constructor above. + /// \brief Returns the string representation of the DataLayout. + /// + /// This representation is in the same format accepted by the string + /// constructor above. std::string getStringRepresentation() const; - /// isLegalInteger - This function returns true if the specified type is - /// known to be a native integer type supported by the CPU. For example, - /// i64 is not native on most 32-bit CPUs and i37 is not native on any known - /// one. This returns false if the integer width is not legal. + /// \brief Returns true if the specified type is known to be a native integer + /// type supported by the CPU. /// - /// The width is specified in bits. + /// For example, i64 is not native on most 32-bit CPUs and i37 is not native + /// on any known one. This returns false if the integer width is not legal. /// + /// The width is specified in bits. bool isLegalInteger(unsigned Width) const { for (unsigned LegalIntWidth : LegalIntWidths) if (LegalIntWidth == Width) @@ -228,22 +221,20 @@ public: return false; } - bool isIllegalInteger(unsigned Width) const { - return !isLegalInteger(Width); - } + bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); } /// Returns true if the given alignment exceeds the natural stack alignment. bool exceedsNaturalStackAlignment(unsigned Align) const { return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + unsigned getStackAlignment() const { return StackNaturalAlign; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WINCOFF; } - bool hasLinkerPrivateGlobalPrefix() const { - return ManglingMode == MM_MachO; - } + bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } const char *getLinkerPrivateGlobalPrefix() const { if (ManglingMode == MM_MachO) @@ -281,10 +272,11 @@ public: static const char *getManglingComponent(const Triple &T); - /// fitsInLegalInteger - This function returns true if the specified type fits - /// in a native integer type supported by the CPU. For example, if the CPU - /// only supports i32 as a native integer type, then i27 fits in a legal - /// integer type but i45 does not. + /// \brief Returns true if the specified type fits in a native integer type + /// supported by the CPU. + /// + /// For example, if the CPU only supports i32 as a native integer type, then + /// i27 fits in a legal integer type but i45 does not. bool fitsInLegalInteger(unsigned Width) const { for (unsigned LegalIntWidth : LegalIntWidths) if (Width <= LegalIntWidth) @@ -342,118 +334,116 @@ public: /// [*] The alloc size depends on the alignment, and thus on the target. /// These values are for x86-32 linux. - /// getTypeSizeInBits - Return the number of bits necessary to hold the - /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. - /// The type passed must have a size (Type::isSized() must return true). + /// \brief Returns the number of bits necessary to hold the specified type. + /// + /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must + /// have a size (Type::isSized() must return true). uint64_t getTypeSizeInBits(Type *Ty) const; - /// getTypeStoreSize - Return the maximum number of bytes that may be - /// overwritten by storing the specified type. For example, returns 5 - /// for i36 and 10 for x86_fp80. + /// \brief Returns the maximum number of bytes that may be overwritten by + /// storing the specified type. + /// + /// For example, returns 5 for i36 and 10 for x86_fp80. uint64_t getTypeStoreSize(Type *Ty) const { - return (getTypeSizeInBits(Ty)+7)/8; + return (getTypeSizeInBits(Ty) + 7) / 8; } - /// getTypeStoreSizeInBits - Return the maximum number of bits that may be - /// overwritten by storing the specified type; always a multiple of 8. For - /// example, returns 40 for i36 and 80 for x86_fp80. + /// \brief Returns the maximum number of bits that may be overwritten by + /// storing the specified type; always a multiple of 8. + /// + /// For example, returns 40 for i36 and 80 for x86_fp80. uint64_t getTypeStoreSizeInBits(Type *Ty) const { - return 8*getTypeStoreSize(Ty); + return 8 * getTypeStoreSize(Ty); } - /// getTypeAllocSize - Return the offset in bytes between successive objects - /// of the specified type, including alignment padding. This is the amount - /// that alloca reserves for this type. For example, returns 12 or 16 for - /// x86_fp80, depending on alignment. + /// \brief Returns the offset in bytes between successive objects of the + /// specified type, including alignment padding. + /// + /// This is the amount that alloca reserves for this type. For example, + /// returns 12 or 16 for x86_fp80, depending on alignment. uint64_t getTypeAllocSize(Type *Ty) const { // Round up to the next alignment boundary. - return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); + return RoundUpToAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); } - /// getTypeAllocSizeInBits - Return the offset in bits between successive - /// objects of the specified type, including alignment padding; always a - /// multiple of 8. This is the amount that alloca reserves for this type. - /// For example, returns 96 or 128 for x86_fp80, depending on alignment. + /// \brief Returns the offset in bits between successive objects of the + /// specified type, including alignment padding; always a multiple of 8. + /// + /// This is the amount that alloca reserves for this type. For example, + /// returns 96 or 128 for x86_fp80, depending on alignment. uint64_t getTypeAllocSizeInBits(Type *Ty) const { - return 8*getTypeAllocSize(Ty); + return 8 * getTypeAllocSize(Ty); } - /// getABITypeAlignment - Return the minimum ABI-required alignment for the - /// specified type. + /// \brief Returns the minimum ABI-required alignment for the specified type. unsigned getABITypeAlignment(Type *Ty) const; - /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for - /// an integer type of the specified bitwidth. + /// \brief Returns the minimum ABI-required alignment for an integer type of + /// the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - /// getPrefTypeAlignment - Return the preferred stack/global alignment for - /// the specified type. This is always at least as good as the ABI alignment. + /// \brief Returns the preferred stack/global alignment for the specified + /// type. + /// + /// This is always at least as good as the ABI alignment. unsigned getPrefTypeAlignment(Type *Ty) const; - /// getPreferredTypeAlignmentShift - Return the preferred alignment for the - /// specified type, returned as log2 of the value (a shift amount). + /// \brief Returns the preferred alignment for the specified type, returned as + /// log2 of the value (a shift amount). unsigned getPreferredTypeAlignmentShift(Type *Ty) const; - /// getIntPtrType - Return an integer type with size at least as big as that - /// of a pointer in the given address space. + /// \brief Returns an integer type with size at least as big as that of a + /// pointer in the given address space. IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; - /// getIntPtrType - Return an integer (vector of integer) type with size at - /// least as big as that of a pointer of the given pointer (vector of pointer) - /// type. + /// \brief Returns an integer (vector of integer) type with size at least as + /// big as that of a pointer of the given pointer (vector of pointer) type. Type *getIntPtrType(Type *) const; - /// getSmallestLegalIntType - Return the smallest integer type with size at - /// least as big as Width bits. + /// \brief Returns the smallest integer type with size at least as big as + /// Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; - /// getLargestLegalIntType - Return the largest legal integer type, or null if - /// none are set. + /// \brief Returns the largest legal integer type, or null if none are set. Type *getLargestLegalIntType(LLVMContext &C) const { unsigned LargestSize = getLargestLegalIntTypeSize(); return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); } - /// getLargestLegalIntTypeSize - Return the size of largest legal integer - /// type size, or 0 if none are set. + /// \brief Returns the size of largest legal integer type size, or 0 if none + /// are set. unsigned getLargestLegalIntTypeSize() const; - /// getIndexedOffset - return the offset from the beginning of the type for - /// the specified indices. This is used to implement getelementptr. + /// \brief Returns the offset from the beginning of the type for the specified + /// indices. + /// + /// This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const; - /// getStructLayout - Return a StructLayout object, indicating the alignment - /// of the struct, its size, and the offsets of its fields. Note that this - /// information is lazily cached. + /// \brief Returns a StructLayout object, indicating the alignment of the + /// struct, its size, and the offsets of its fields. + /// + /// Note that this information is lazily cached. const StructLayout *getStructLayout(StructType *Ty) const; - /// getPreferredAlignment - Return the preferred alignment of the specified - /// global. This includes an explicitly requested alignment (if the global - /// has one). + /// \brief Returns the preferred alignment of the specified global. + /// + /// This includes an explicitly requested alignment (if the global has one). unsigned getPreferredAlignment(const GlobalVariable *GV) const; - /// getPreferredAlignmentLog - Return the preferred alignment of the - /// specified global, returned in log form. This includes an explicitly - /// requested alignment (if the global has one). + /// \brief Returns the preferred alignment of the specified global, returned + /// in log form. + /// + /// This includes an explicitly requested alignment (if the global has one). unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; - - /// RoundUpAlignment - Round the specified value up to the next alignment - /// boundary specified by Alignment. For example, 7 rounded up to an - /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4 - /// is 8 because it is already aligned. - template <typename UIntTy> - static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) { - assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); - return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); - } }; inline DataLayout *unwrap(LLVMTargetDataRef P) { - return reinterpret_cast<DataLayout*>(P); + return reinterpret_cast<DataLayout *>(P); } inline LLVMTargetDataRef wrap(const DataLayout *P) { - return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P)); + return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P)); } class DataLayoutPass : public ImmutablePass { @@ -466,40 +456,28 @@ public: const DataLayout &getDataLayout() const { return DL; } - // For use with the C API. C++ code should always use the constructor that - // takes a module. - explicit DataLayoutPass(const DataLayout &DL); - - explicit DataLayoutPass(const Module *M); - static char ID; // Pass identification, replacement for typeid + + bool doFinalization(Module &M) override; + bool doInitialization(Module &M) override; }; -/// StructLayout - used to lazily calculate structure layout information for a -/// target machine, based on the DataLayout structure. -/// +/// Used to lazily calculate structure layout information for a target machine, +/// based on the DataLayout structure. class StructLayout { uint64_t StructSize; unsigned StructAlignment; unsigned NumElements; - uint64_t MemberOffsets[1]; // variable sized array! + uint64_t MemberOffsets[1]; // variable sized array! public: + uint64_t getSizeInBytes() const { return StructSize; } - uint64_t getSizeInBytes() const { - return StructSize; - } + uint64_t getSizeInBits() const { return 8 * StructSize; } - uint64_t getSizeInBits() const { - return 8*StructSize; - } + unsigned getAlignment() const { return StructAlignment; } - unsigned getAlignment() const { - return StructAlignment; - } - - /// getElementContainingOffset - Given a valid byte offset into the structure, - /// return the structure index that contains it. - /// + /// \brief Given a valid byte offset into the structure, returns the structure + /// index that contains it. unsigned getElementContainingOffset(uint64_t Offset) const; uint64_t getElementOffset(unsigned Idx) const { @@ -508,15 +486,14 @@ public: } uint64_t getElementOffsetInBits(unsigned Idx) const { - return getElementOffset(Idx)*8; + return getElementOffset(Idx) * 8; } private: - friend class DataLayout; // Only DataLayout can create this class + friend class DataLayout; // Only DataLayout can create this class StructLayout(StructType *ST, const DataLayout &DL); }; - // The implementation of this method is provided inline as it is particularly // well suited to constant folding when called on a specific Type subclass. inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { @@ -546,7 +523,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { case Type::PPC_FP128TyID: case Type::FP128TyID: return 128; - // In memory objects this is always aligned to a higher boundary, but + // In memory objects this is always aligned to a higher boundary, but // only 80 bits contain information. case Type::X86_FP80TyID: return 80; diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 088eb9f01049..5c85d6d52824 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,13 +18,15 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include <iterator> namespace llvm { class BasicBlock; @@ -37,6 +39,7 @@ class Value; class DbgDeclareInst; class DbgValueInst; class Instruction; +class Metadata; class MDNode; class MDString; class NamedMDNode; @@ -52,21 +55,78 @@ class DIType; class DIScope; class DIObjCProperty; -/// Maps from type identifier to the actual MDNode. +/// \brief Maps from type identifier to the actual MDNode. typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; -/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. -/// This should not be stored in a container, because the underlying MDNode -/// may change in certain situations. +class DIHeaderFieldIterator + : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, + const StringRef *, StringRef> { + StringRef Header; + StringRef Current; + +public: + DIHeaderFieldIterator() {} + DIHeaderFieldIterator(StringRef Header) + : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} + StringRef operator*() const { return Current; } + const StringRef * operator->() const { return &Current; } + DIHeaderFieldIterator &operator++() { + increment(); + return *this; + } + DIHeaderFieldIterator operator++(int) { + DIHeaderFieldIterator X(*this); + increment(); + return X; + } + bool operator==(const DIHeaderFieldIterator &X) const { + return Current.data() == X.Current.data(); + } + bool operator!=(const DIHeaderFieldIterator &X) const { + return !(*this == X); + } + + StringRef getHeader() const { return Header; } + StringRef getCurrent() const { return Current; } + StringRef getPrefix() const { + if (Current.begin() == Header.begin()) + return StringRef(); + return Header.slice(0, Current.begin() - Header.begin() - 1); + } + StringRef getSuffix() const { + if (Current.end() == Header.end()) + return StringRef(); + return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); + } + +private: + void increment() { + assert(Current.data() != nullptr && "Cannot increment past the end"); + StringRef Suffix = getSuffix(); + Current = Suffix.slice(0, Suffix.find('\0')); + } +}; + +/// \brief A thin wraper around MDNode to access encoded debug info. +/// +/// This should not be stored in a container, because the underlying MDNode may +/// change in certain situations. class DIDescriptor { // Befriends DIRef so DIRef can befriend the protected member // function: getFieldAs<DIRef>. template <typename T> friend class DIRef; public: + /// \brief Accessibility flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, + FlagAccessibility = 1 << 0 | 1 << 1, + FlagPrivate = 1, + FlagProtected = 2, + FlagPublic = 3, + FlagFwdDecl = 1 << 2, FlagAppleBlock = 1 << 3, FlagBlockByrefStruct = 1 << 4, @@ -108,8 +168,9 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast<MDNode *>(DbgNode); } - MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); } + MDNode *get() const { return const_cast<MDNode *>(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // An explicit operator bool so that we can do testing of DI values // easily. @@ -121,12 +182,36 @@ public: bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - uint16_t getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; + StringRef getHeader() const { + return getStringField(0); + } + + size_t getNumHeaderFields() const { + return std::distance(DIHeaderFieldIterator(getHeader()), + DIHeaderFieldIterator()); } + StringRef getHeaderField(unsigned Index) const { + // Since callers expect an empty string for out-of-range accesses, we can't + // use std::advance() here. + for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + if (!Index) + return *I; + return StringRef(); + } + + template <class T> T getHeaderFieldAs(unsigned Index) const { + T Int; + if (getHeaderField(Index).getAsInteger(0, Int)) + return 0; + return Int; + } + + uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } + bool isDerivedType() const; bool isCompositeType() const; + bool isSubroutineType() const; bool isBasicType() const; bool isVariable() const; bool isSubprogram() const; @@ -140,20 +225,21 @@ public: bool isSubrange() const; bool isEnumerator() const; bool isType() const; - bool isUnspecifiedParameter() const; bool isTemplateTypeParameter() const; bool isTemplateValueParameter() const; bool isObjCProperty() const; bool isImportedEntity() const; + bool isExpression() const; - /// print - print descriptor. void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. void dump() const; + + /// \brief Replace all uses of debug info referenced by this descriptor. + void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); + void replaceAllUsesWith(MDNode *D); }; -/// DISubrange - This is used to represent ranges, for array bounds. +/// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -161,23 +247,27 @@ class DISubrange : public DIDescriptor { public: explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } + int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); } + int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); } bool Verify() const; }; -/// DIArray - This descriptor holds an array of descriptors. -class DIArray : public DIDescriptor { +/// \brief This descriptor holds an array of nodes with type T. +template <typename T> class DITypedArray : public DIDescriptor { public: - explicit DIArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - - unsigned getNumElements() const; - DIDescriptor getElement(unsigned Idx) const { - return getDescriptorField(Idx); + explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} + unsigned getNumElements() const { + return DbgNode ? DbgNode->getNumOperands() : 0; + } + T getElement(unsigned Idx) const { + return getFieldAs<T>(Idx); } }; -/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +typedef DITypedArray<DIDescriptor> DIArray; + +/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// /// FIXME: it seems strange that this doesn't have either a reference to the /// type/precision or a file/line pair for location info. class DIEnumerator : public DIDescriptor { @@ -187,16 +277,17 @@ class DIEnumerator : public DIDescriptor { public: explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - StringRef getName() const { return getStringField(1); } - int64_t getEnumValue() const { return getInt64Field(2); } + StringRef getName() const { return getHeaderField(1); } + int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); } bool Verify() const; }; template <typename T> class DIRef; typedef DIRef<DIScope> DIScopeRef; typedef DIRef<DIType> DITypeRef; +typedef DITypedArray<DITypeRef> DITypeArray; -/// DIScope - A base class for various scopes. +/// \brief A base class for various scopes. /// /// Although, implementation-wise, DIScope is the parent class of most /// other DIxxx classes, including DIType and its descendants, most of @@ -212,21 +303,28 @@ protected: public: explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - /// Gets the parent scope for this scope node or returns a - /// default constructed scope. + /// \brief Get the parent scope. + /// + /// Gets the parent scope for this scope node or returns a default + /// constructed scope. DIScopeRef getContext() const; + /// \brief Get the scope name. + /// /// If the scope node has a name, return that, else return an empty string. StringRef getName() const; StringRef getFilename() const; StringRef getDirectory() const; - /// Generate a reference to this DIScope. Uses the type identifier instead - /// of the actual MDNode if possible, to help type uniquing. + /// \brief Generate a reference to this DIScope. + /// + /// Uses the type identifier instead of the actual MDNode if possible, to + /// help type uniquing. DIScopeRef getRef() const; }; -/// Represents reference to a DIDescriptor, abstracts over direct and -/// identifier-based metadata references. +/// \brief Represents reference to a DIDescriptor. +/// +/// Abstracts over direct and identifier-based metadata references. template <typename T> class DIRef { template <typename DescTy> friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; @@ -234,15 +332,16 @@ template <typename T> class DIRef { friend DIScopeRef DIScope::getRef() const; friend class DIType; - /// Val can be either a MDNode or a MDString, in the latter, - /// MDString specifies the type identifier. - const Value *Val; - explicit DIRef(const Value *V); + /// \brief Val can be either a MDNode or a MDString. + /// + /// In the latter, MDString specifies the type identifier. + const Metadata *Val; + explicit DIRef(const Metadata *V); public: T resolve(const DITypeIdentifierMap &Map) const; StringRef getName() const; - operator Value *() const { return const_cast<Value *>(Val); } + operator Metadata *() const { return const_cast<Metadata *>(Val); } }; template <typename T> @@ -273,17 +372,18 @@ template <typename T> StringRef DIRef<T>::getName() const { return MS->getString(); } -/// Specialize getFieldAs to handle fields that are references to DIScopes. +/// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DIScopeRef. +template <> DIRef<DIScope>::DIRef(const Metadata *V); -/// Specialize getFieldAs to handle fields that are references to DITypes. +/// \brief Handle fields that are references to DITypes. template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DITypeRef. +template <> DIRef<DIType>::DIRef(const Metadata *V); -/// DIType - This is a wrapper for a type. +/// \briefThis is a wrapper for a type. +/// /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. class DIType : public DIScope { @@ -299,22 +399,35 @@ public: return DITypeRef(&*getRef()); } - /// Verify - Verify that a type descriptor is well formed. bool Verify() const; DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - uint64_t getSizeInBits() const { return getUInt64Field(5); } - uint64_t getAlignInBits() const { return getUInt64Field(6); } + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { + return getHeaderFieldAs<unsigned>(2); + } + uint64_t getSizeInBits() const { + return getHeaderFieldAs<unsigned>(3); + } + uint64_t getAlignInBits() const { + return getHeaderFieldAs<unsigned>(4); + } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { return getUInt64Field(7); } - unsigned getFlags() const { return getUnsignedField(8); } - bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; } - bool isProtected() const { return (getFlags() & FlagProtected) != 0; } + uint64_t getOffsetInBits() const { + return getHeaderFieldAs<unsigned>(5); + } + unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - // isAppleBlock - Return true if this is the Apple Blocks extension. bool isAppleBlockExtension() const { return (getFlags() & FlagAppleBlock) != 0; } @@ -336,27 +449,22 @@ public: return (getFlags() & FlagRValueReference) != 0; } bool isValid() const { return DbgNode && isType(); } - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); }; -/// DIBasicType - A basic type, like 'int' or 'float'. +/// \brief A basic type, like 'int' or 'float'. class DIBasicType : public DIType { public: explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - unsigned getEncoding() const { return getUnsignedField(9); } + unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); } - /// Verify - Verify that a basic type descriptor is well formed. bool Verify() const; }; -/// DIDerivedType - A simple derived type, like a const qualified type, -/// a typedef, a pointer or reference, et cetera. Or, a data member of -/// a class/struct/union. +/// \brief A simple derived type +/// +/// Like a const qualified type, a typedef, a pointer or reference, et cetera. +/// Or, a data member of a class/struct/union. class DIDerivedType : public DIType { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -364,62 +472,96 @@ class DIDerivedType : public DIType { public: explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); } + DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); } - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. + /// \brief Return property node, if this ivar is associated with one. MDNode *getObjCProperty() const; DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DITypeRef>(10); + return getFieldAs<DITypeRef>(4); } Constant *getConstant() const { assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); + return getConstantField(4); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; -/// DICompositeType - This descriptor holds a type that can refer to multiple -/// other types, like a function or struct. +/// \brief Types that refer to multiple other types. +/// +/// This descriptor holds a type that can refer to multiple other types, like a +/// function or struct. +/// /// DICompositeType is derived from DIDerivedType because some /// composite types (such as enums) can be derived from basic types // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; + /// \brief Set the array of member DITypes. + void setArraysHelper(MDNode *Elements, MDNode *TParams); + public: explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } - void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - unsigned getRunTimeLang() const { return getUnsignedField(11); } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } + DIArray getElements() const { + assert(!isSubroutineType() && "no elements for DISubroutineType"); + return getFieldAs<DIArray>(4); + } + +private: + template <typename T> + void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { + assert((!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); + setArraysHelper(Elements, TParams); + } + +public: + unsigned getRunTimeLang() const { + return getHeaderFieldAs<unsigned>(7); + } + DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); } + +private: + /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } + +public: + DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } MDString *getIdentifier() const; - /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; }; -/// DIFile - This is a wrapper for a file. +class DISubroutineType : public DICompositeType { +public: + explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} + DITypedArray<DITypeRef> getTypeArray() const { + return getFieldAs<DITypedArray<DITypeRef>>(4); + } +}; + +/// \brief This is a wrapper for a file. class DIFile : public DIScope { friend class DIDescriptor; public: explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} + + /// \brief Retrieve the MDNode for the directory/file pair. MDNode *getFileNode() const; bool Verify() const; }; -/// DICompileUnit - A wrapper for a compile unit. +/// \brief A wrapper for a compile unit. class DICompileUnit : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -428,13 +570,13 @@ public: explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} dwarf::SourceLanguage getLanguage() const { - return static_cast<dwarf::SourceLanguage>(getUnsignedField(2)); + return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1)); } - StringRef getProducer() const { return getStringField(3); } + StringRef getProducer() const { return getHeaderField(2); } - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } + bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; } + StringRef getFlags() const { return getHeaderField(4); } + unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); } DIArray getEnumTypes() const; DIArray getRetainedTypes() const; @@ -442,14 +584,16 @@ public: DIArray getGlobalVariables() const; DIArray getImportedEntities() const; - StringRef getSplitDebugFilename() const { return getStringField(12); } - unsigned getEmissionKind() const { return getUnsignedField(13); } + void replaceSubprograms(DIArray Subprograms); + void replaceGlobalVariables(DIArray GlobalVariables); + + StringRef getSplitDebugFilename() const { return getHeaderField(6); } + unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); } - /// Verify - Verify that a compile unit is well formed. bool Verify() const; }; -/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +/// \brief This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -457,93 +601,95 @@ class DISubprogram : public DIScope { public: explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DICompositeType getType() const { return getFieldAs<DICompositeType>(7); } - - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(8); } - unsigned isDefinition() const { return getUnsignedField(9); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } + /// \brief Check if this is local (like 'static' in C). + unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); } + unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } + unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); } + unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); } - unsigned getFlags() const { return getUnsignedField(13); } + unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); } - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getUnsignedField(13) & FlagProtected) != 0; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } + unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); } - /// Return true if this subprogram is a C++11 reference-qualified - /// non-static member function (void foo() &). - unsigned isLValueReference() const { - return (getUnsignedField(13) & FlagLValueReference) != 0; - } + /// \brief Get the beginning of the scope of the function (not the name). + unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); } - /// Return true if this subprogram is a C++11 - /// rvalue-reference-qualified non-static member function - /// (void foo() &&). - unsigned isRValueReference() const { - return (getUnsignedField(13) & FlagRValueReference) != 0; - } + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } + DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); } - unsigned isOptimized() const; + DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); } - /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; - /// describes - Return true if this subprogram provides debugging - /// information for the function F. + /// \brief Check if this provides debugging information for the function F. bool describes(const Function *F); - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); } + Function *getFunction() const { return getFunctionField(5); } + void replaceFunction(Function *F) { replaceFunctionField(5, F); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(17); + return getFieldAs<DISubprogram>(7); } MDNode *getVariablesNodes() const; DIArray getVariables() const; - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } + unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + /// \brief Check for the "private" access specifier. + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + /// \brief Check for the "protected" access specifier. + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + /// \brief Check for the "public" access specifier. + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + /// \brief Check for "explicit". + bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } + /// \brief Check if this is prototyped. + bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return (getFlags() & FlagLValueReference) != 0; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return (getFlags() & FlagRValueReference) != 0; + } + }; -/// DILexicalBlock - This is a wrapper for a lexical block. +/// \brief This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - unsigned getDiscriminator() const { return getUnsignedField(5); } + unsigned getLineNumber() const { + return getHeaderFieldAs<unsigned>(1); + } + unsigned getColumnNumber() const { + return getHeaderFieldAs<unsigned>(2); + } bool Verify() const; }; -/// DILexicalBlockFile - This is a wrapper for a lexical block with -/// a filename change. +/// \brief This is a wrapper for a lexical block with a filename change. class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} @@ -555,68 +701,63 @@ public: unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } + unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); } bool Verify() const; }; -/// DINameSpace - A wrapper for a C++ style name space. +/// \brief A wrapper for a C++ style name space. class DINameSpace : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; -}; - -/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters. -class DIUnspecifiedParameter : public DIDescriptor { -public: - explicit DIUnspecifiedParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} bool Verify() const; }; -/// DITemplateTypeParameter - This is a wrapper for template type parameter. +/// \brief This is a wrapper for template type parameter. class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } + unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } + StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); } StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); + return getFieldAs<DIFile>(3).getDirectory(); } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } bool Verify() const; }; -/// DITemplateValueParameter - This is a wrapper for template value parameter. +/// \brief This is a wrapper for template value parameter. class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } + unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } + Metadata *getValue() const; + StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } StringRef getDirectory() const { - return getFieldAs<DIFile>(5).getDirectory(); + return getFieldAs<DIFile>(4).getDirectory(); } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } bool Verify() const; }; -/// DIGlobalVariable - This is a wrapper for a global variable. +/// \brief This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -624,32 +765,30 @@ class DIGlobalVariable : public DIDescriptor { public: explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { return getFieldAs<DIFile>(6).getFilename(); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } + unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } + unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } StringRef getDirectory() const { - return getFieldAs<DIFile>(6).getDirectory(); + return getFieldAs<DIFile>(2).getDirectory(); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - unsigned getLineNumber() const { return getUnsignedField(7); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } + GlobalVariable *getGlobal() const { return getGlobalVariableField(4); } + Constant *getConstant() const { return getConstantField(4); } DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs<DIDerivedType>(12); + return getFieldAs<DIDerivedType>(5); } - /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; }; -/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, -/// global etc). +/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). class DIVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -657,73 +796,107 @@ class DIVariable : public DIDescriptor { public: explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs<DIFile>(3); } - unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { + // FIXME: Line number and arg number shouldn't be merged together like this. + return (getHeaderFieldAs<unsigned>(2) << 8) >> 8; } - DITypeRef getType() const { return getFieldAs<DITypeRef>(5); } + unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; } + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + DIFile getFile() const { return getFieldAs<DIFile>(2); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - /// isArtificial - Return true if this variable is marked as "artificial". + /// \brief Return true if this variable is marked as "artificial". bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; + return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0; } bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; + return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; } /// \brief Return true if this variable is represented as a pointer. bool isIndirect() const { - return (getUnsignedField(6) & FlagIndirectVariable) != 0; + return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0; } - /// getInlinedAt - If this variable is inlined then return inline location. + /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; - /// Verify - Verify that a variable descriptor is well formed. bool Verify() const; - /// HasComplexAddr - Return true if the variable has a complex address. - bool hasComplexAddress() const { return getNumAddrElements() > 0; } - - /// \brief Return the size of this variable's complex address or - /// zero if there is none. - unsigned getNumAddrElements() const { - if (DbgNode->getNumOperands() < 9) - return 0; - return getDescriptorField(8)->getNumOperands(); - } - - /// \brief return the Idx'th complex address element. - uint64_t getAddrElement(unsigned Idx) const; - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). + /// \brief Check if this is a "__block" variable (Apple Blocks). bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { return (getType().resolve(Map)).isBlockByrefStruct(); } - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. + /// \brief Check if this is an inlined function argument. bool isInlinedFnArgument(const Function *CurFn); + /// \brief Return the size reported by the variable's type. + unsigned getSizeInBits(const DITypeIdentifierMap &Map); + void printExtendedName(raw_ostream &OS) const; }; -/// DILocation - This object holds location information. This object -/// is not associated with any DWARF tag. +/// \brief A complex location expression. +class DIExpression : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} + + bool Verify() const; + + /// \brief Return the number of elements in the complex expression. + unsigned getNumElements() const { + if (!DbgNode) + return 0; + unsigned N = getNumHeaderFields(); + assert(N > 0 && "missing tag"); + return N - 1; + } + + /// \brief return the Idx'th complex address element. + uint64_t getElement(unsigned Idx) const; + + /// \brief Return whether this is a piece of an aggregate variable. + bool isVariablePiece() const; + /// \brief Return the offset of this piece in bytes. + uint64_t getPieceOffset() const; + /// \brief Return the size of this piece in bytes. + uint64_t getPieceSize() const; +}; + +/// \brief This object holds location information. +/// +/// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { public: explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs<DIScope>(2); } - DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); } + unsigned getLineNumber() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return L->getLine(); + return 0; + } + unsigned getColumnNumber() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return L->getColumn(); + return 0; + } + DIScope getScope() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return DIScope(dyn_cast_or_null<MDNode>(L->getScope())); + return DIScope(nullptr); + } + DILocation getOrigLocation() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt())); + return DILocation(nullptr); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -731,23 +904,30 @@ public: return (getLineNumber() == Other.getLineNumber() && getFilename() == Other.getFilename()); } - /// getDiscriminator - DWARF discriminators are used to distinguish - /// identical file locations for instructions that are on different - /// basic blocks. If two instructions are inside the same lexical block - /// and are in different basic blocks, we create a new lexical block - /// with identical location as the original but with a different - /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp - /// for details). + /// \brief Get the DWAF discriminator. + /// + /// DWARF discriminators are used to distinguish identical file locations for + /// instructions that are on different basic blocks. If two instructions are + /// inside the same lexical block and are in different basic blocks, we + /// create a new lexical block with identical location as the original but + /// with a different discriminator value + /// (lib/Transforms/Util/AddDiscriminators.cpp for details). unsigned getDiscriminator() const { // Since discriminators are associated with lexical blocks, make // sure this location is a lexical block before retrieving its // value. - return getScope().isLexicalBlock() - ? getFieldAs<DILexicalBlock>(2).getDiscriminator() + return getScope().isLexicalBlockFile() + ? DILexicalBlockFile( + cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) + .getDiscriminator() : 0; } + + /// \brief Generate a new discriminator value for this location. unsigned computeNewDiscriminator(LLVMContext &Ctx); - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlock NewScope); + + /// \brief Return a copy of this location with a different scope. + DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); }; class DIObjCProperty : public DIDescriptor { @@ -757,36 +937,38 @@ class DIObjCProperty : public DIDescriptor { public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getObjCPropertyName() const { return getHeaderField(1); } + DIFile getFile() const { return getFieldAs<DIFile>(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - StringRef getObjCPropertyGetterName() const { return getStringField(4); } - StringRef getObjCPropertySetterName() const { return getStringField(5); } + StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } + StringRef getObjCPropertySetterName() const { return getHeaderField(4); } + unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); } bool isReadOnlyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; } bool isReadWriteObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; } bool isAssignObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; } bool isRetainObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; } bool isCopyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; } bool isNonAtomicObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; } - /// Objective-C doesn't have an ODR, so there is no benefit in storing + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing /// the type as a DITypeRef here. - DIType getType() const { return getFieldAs<DIType>(7); } + DIType getType() const { return getFieldAs<DIType>(2); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; @@ -799,47 +981,47 @@ public: explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - StringRef getName() const { return getStringField(4); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } + StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; -/// getDISubprogram - Find subprogram that is enclosing this scope. +/// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); -/// getDICompositeType - Find underlying composite type. -DICompositeType getDICompositeType(DIType T); - -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); +/// \brief Find debug info for a given function. +/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty +/// DISubprogram. +DISubprogram getDISubprogram(const Function *F); -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); +/// \brief Find underlying composite type. +DICompositeType getDICompositeType(DIType T); -/// createInlinedVariable - Create a new inlined variable based on current -/// variable. +/// \brief Create a new inlined variable based on current variable. +/// /// @param DV Current Variable. /// @param InlinedScope Location at current variable is inlined. DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, LLVMContext &VMContext); -/// cleanseInlinedVariable - Remove inlined scope from the variable. +/// \brief Remove inlined scope from the variable. DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); -/// Construct DITypeIdentifierMap by going through retained types of each CU. +/// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); -/// Strip debug info in the module if it exists. +/// \brief Strip debug info in the module if it exists. +/// /// To do this, we remove all calls to the debugger intrinsics and any named /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); -/// Return Debug Info Metadata Version by checking module flags. +/// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); +/// \brief Utility to find all debug info in a module. +/// /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To /// list debug info MDNodes used by an instruction, DebugInfoFinder uses /// processDeclare, processValue and processLocation to handle DbgDeclareInst, @@ -850,44 +1032,29 @@ class DebugInfoFinder { public: DebugInfoFinder() : TypeMapInitialized(false) {} - /// processModule - Process entire module and collect debug info - /// anchors. + /// \brief Process entire module and collect debug info anchors. void processModule(const Module &M); - /// processDeclare - Process DbgDeclareInst. + /// \brief Process DbgDeclareInst. void processDeclare(const Module &M, const DbgDeclareInst *DDI); - /// Process DbgValueInst. + /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// processLocation - Process DILocation. + /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); - /// Clear all lists. + /// \brief Clear all lists. void reset(); private: - /// Initialize TypeIdentifierMap. void InitializeTypeMap(const Module &M); - /// processType - Process DIType. void processType(DIType DT); - - /// processSubprogram - Process DISubprogram. void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - - /// addCompileUnit - Add compile unit into CUs. bool addCompileUnit(DICompileUnit CU); - - /// addGlobalVariable - Add global variable into GVs. bool addGlobalVariable(DIGlobalVariable DIG); - - // addSubprogram - Add subprogram into SPs. bool addSubprogram(DISubprogram SP); - - /// addType - Add type into Tys. bool addType(DIType DT); - bool addScope(DIScope Scope); public: @@ -924,14 +1091,15 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector<DICompileUnit, 8> CUs; // Compile Units - SmallVector<DISubprogram, 8> SPs; // Subprograms - SmallVector<DIGlobalVariable, 8> GVs; // Global Variables; - SmallVector<DIType, 8> TYs; // Types - SmallVector<DIScope, 8> Scopes; // Scopes + SmallVector<DICompileUnit, 8> CUs; + SmallVector<DISubprogram, 8> SPs; + SmallVector<DIGlobalVariable, 8> GVs; + SmallVector<DIType, 8> TYs; + SmallVector<DIScope, 8> Scopes; SmallPtrSet<MDNode *, 64> NodesSeen; DITypeIdentifierMap TypeIdentifierMap; - /// Specify if TypeIdentifierMap is initialized. + + /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 3d969a8b7532..86e64417099d 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -15,51 +15,41 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { - template <typename T> struct DenseMapInfo; - class MDNode; + class LLVMContext; class raw_ostream; + class MDNode; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { - friend struct DenseMapInfo<DebugLoc>; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } + TrackingMDNodeRef Loc; - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; } - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = nullptr); + static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, + MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -68,56 +58,54 @@ namespace llvm { static DebugLoc getFromDILexicalBlock(MDNode *N); /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } + bool isUnknown() const { return !Loc; } - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } + unsigned getLine() const; + unsigned getCol() const; /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; + MDNode *getScope() const; + MDNode *getScope(const LLVMContext &) const { return getScope(); } /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; + MDNode *getInlinedAt() const; + MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; + const LLVMContext &) const { + return getScopeAndInlinedAt(Scope, IA); + } /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode(const LLVMContext &Ctx) const; + MDNode *getScopeNode() const; + MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; + DebugLoc getFnDebugLoc() const; + DebugLoc getFnDebugLoc(const LLVMContext &) const { + return getFnDebugLoc(); + } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; + MDNode *getAsMDNode() const; + MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - void dump(const LLVMContext &Ctx) const; + void dump() const; + void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(const LLVMContext &Ctx, raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; - template <> - struct DenseMapInfo<DebugLoc> { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; } // end namespace llvm #endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index ff150872a4e1..182015c98aa2 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -123,6 +123,9 @@ public: typedef Type::subtype_iterator param_iterator; param_iterator param_begin() const { return ContainedTys + 1; } param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef<Type *> params() const { + return makeArrayRef(param_begin(), param_end()); + } /// Parameter type accessors. Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } @@ -204,9 +207,6 @@ class StructType : public CompositeType { /// void *SymbolTableEntry; public: - ~StructType() { - delete [] ContainedTys; // Delete the body. - } /// StructType::create - This creates an identified struct. static StructType *create(LLVMContext &Context, StringRef Name); @@ -221,7 +221,7 @@ public: StringRef Name, bool isPacked = false); static StructType *create(LLVMContext &Context, ArrayRef<Type*> Elements); - static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL; + static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL; /// StructType::get - This static method is the primary way to create a /// literal StructType. @@ -236,7 +236,7 @@ public: /// structure types by specifying the elements as arguments. Note that this /// method always returns a non-packed struct, and requires at least one /// element type. - static StructType *get(Type *elt1, ...) END_WITH_NULL; + static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL; bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } @@ -249,7 +249,7 @@ public: bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } /// isSized - Return true if this is a sized type. - bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const; + bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const; /// hasName - Return true if this is a named struct that has a non-empty name. bool hasName() const { return SymbolTableEntry != nullptr; } @@ -266,7 +266,7 @@ public: /// setBody - Specify a body for an opaque identified type. void setBody(ArrayRef<Type*> Elements, bool isPacked = false); - void setBody(Type *elt1, ...) END_WITH_NULL; + void setBody(Type *elt1, ...) LLVM_END_WITH_NULL; /// isValidElementType - Return true if the specified type is valid as a /// element type. @@ -277,6 +277,9 @@ public: typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef<Type *> const elements() const { + return makeArrayRef(element_begin(), element_end()); + } /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 9c9f236180ce..c6a8854e0774 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -12,12 +12,13 @@ // Diagnostics reporting is still done as part of the LLVMContext. //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H -#define LLVM_SUPPORT_DIAGNOSTICINFO_H +#ifndef LLVM_IR_DIAGNOSTICINFO_H +#define LLVM_IR_DIAGNOSTICINFO_H #include "llvm-c/Core.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" namespace llvm { @@ -44,8 +45,10 @@ enum DiagnosticSeverity { /// \brief Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Bitcode, DK_InlineAsm, DK_StackSize, + DK_Linker, DK_DebugMetadataVersion, DK_SampleProfile, DK_OptimizationRemark, @@ -95,6 +98,8 @@ public: virtual void print(DiagnosticPrinter &DP) const = 0; }; +typedef std::function<void(const DiagnosticInfo &)> DiagnosticHandlerFunction; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { @@ -324,7 +329,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Diagnostic information for missed-optimization remarks. @@ -350,7 +355,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Diagnostic information for optimization analysis remarks. @@ -377,7 +382,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; // Create wrappers for C Binding types (see CBindingWrapping.h). @@ -432,7 +437,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Emit a warning when loop vectorization is specified but fails. \p Fn is the diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h index 411c781e01c5..db5779a8a8a5 100644 --- a/include/llvm/IR/DiagnosticPrinter.h +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -13,8 +13,8 @@ // on their needs. //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H -#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H +#ifndef LLVM_IR_DIAGNOSTICPRINTER_H +#define LLVM_IR_DIAGNOSTICPRINTER_H #include <string> diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e2d1ccc8a3ca..c1f208e3d72f 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -31,6 +31,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>); EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); @@ -69,6 +74,13 @@ public: DominatorTree() : DominatorTreeBase<BasicBlock>(false) {} + DominatorTree(DominatorTree &&Arg) + : Base(std::move(static_cast<Base &>(Arg))) {} + DominatorTree &operator=(DominatorTree &&RHS) { + Base::operator=(std::move(static_cast<Base &>(RHS))); + return *this; + } + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { @@ -155,6 +167,43 @@ template <> struct GraphTraits<DominatorTree*> }; /// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeAnalysis { +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DominatorTree Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Run the analysis pass over a function and produce a dominator tree. + DominatorTree run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "DominatorTreeAnalysis"; } + +private: + static char PassID; +}; + +/// \brief Printer pass for the \c DominatorTree. +class DominatorTreePrinterPass { + raw_ostream &OS; + +public: + explicit DominatorTreePrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "DominatorTreePrinterPass"; } +}; + +/// \brief Verifier pass for the \c DominatorTree. +struct DominatorTreeVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "DominatorTreeVerifierPass"; } +}; + +/// \brief Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index ad4b1395f0cb..51403281e964 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ private: ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits<Function, Module>; @@ -102,7 +105,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -143,6 +146,9 @@ public: /// arguments. bool isVarArg() const; + bool isMaterializable() const; + void setIsMaterializable(bool V); + /// getIntrinsicID - This method returns the ID number of the specified /// function, or Intrinsic::not_intrinsic if the function is not an /// intrinsic, or if the pointer is null. This value is always defined to be @@ -159,11 +165,11 @@ public: /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. CallingConv::ID getCallingConv() const { - return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2); + return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast<unsigned>(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast<unsigned>(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -445,12 +451,19 @@ public: bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index a1216a174282..6f57dc2a98a6 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -19,11 +19,13 @@ #define LLVM_IR_GVMATERIALIZER_H #include <system_error> +#include <vector> namespace llvm { class Function; class GlobalValue; class Module; +class StructType; class GVMaterializer { protected: @@ -32,17 +34,13 @@ protected: public: virtual ~GVMaterializer(); - /// True if GV can be materialized from whatever backing store this - /// GVMaterializer uses and has not been materialized yet. - virtual bool isMaterializable(const GlobalValue *GV) const = 0; - /// True if GV has been materialized and can be dematerialized back to /// whatever backing store this GVMaterializer uses. virtual bool isDematerializable(const GlobalValue *GV) const = 0; /// Make sure the given GlobalValue is fully read. /// - virtual std::error_code Materialize(GlobalValue *GV) = 0; + virtual std::error_code materialize(GlobalValue *GV) = 0; /// If the given GlobalValue is read in, and if the GVMaterializer supports /// it, release the memory for the GV, and set it up to be materialized @@ -55,7 +53,7 @@ public: /// virtual std::error_code MaterializeModule(Module *M) = 0; - virtual void releaseBuffer() = 0; + virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 2e042f489749..546fea2dfa9b 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -1,4 +1,4 @@ -//===-- llvm/GlobalObject.h - Class to represent a global object *- C++ -*-===// +//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -35,12 +35,24 @@ protected: std::string Section; // Section to emit this into, empty means default Comdat *ObjComdat; + static const unsigned AlignmentBits = 5; + static const unsigned GlobalObjectSubClassDataBits = + GlobalValueSubClassDataBits - AlignmentBits; + +private: + static const unsigned AlignmentMask = (1 << AlignmentBits) - 1; + public: unsigned getAlignment() const { - return (1u << getGlobalValueSubClassData()) >> 1; + unsigned Data = getGlobalValueSubClassData(); + unsigned AlignmentData = Data & AlignmentMask; + return (1u << AlignmentData) >> 1; } void setAlignment(unsigned Align); + unsigned getGlobalObjectSubClassData() const; + void setGlobalObjectSubClassData(unsigned Val); + bool hasSection() const { return !StringRef(getSection()).empty(); } const char *getSection() const { return Section.c_str(); } void setSection(StringRef S); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 68e410ba4b8b..d0f7e9a11790 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,6 +20,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" +#include <system_error> namespace llvm { @@ -84,6 +85,7 @@ private: // (19 + 3 + 2 + 1 + 2 + 5) == 32. unsigned SubClassData : 19; protected: + static const unsigned GlobalValueSubClassDataBits = 19; unsigned getGlobalValueSubClassData() const { return SubClassData; } @@ -246,6 +248,7 @@ public: bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } + bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); } bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } @@ -309,7 +312,7 @@ public: /// Make sure this GlobalValue is fully read. If the module is corrupt, this /// returns true and fills in the optional string with information about the /// problem. If successful, this returns false. - bool Materialize(std::string *ErrInfo = nullptr); + std::error_code materialize(); /// If this GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized @@ -325,6 +328,13 @@ public: /// the current translation unit. bool isDeclaration() const; + bool isDeclarationForLinker() const { + if (hasAvailableExternallyLinkage()) + return true; + + return isDeclaration(); + } + /// This method unlinks 'this' from the containing module, but does not delete /// it. virtual void removeFromParent() = 0; diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index aed2463d42d8..e5f62fb9625e 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -28,7 +28,7 @@ #include "llvm/Support/CBindingWrapping.h" namespace llvm { - class MDNode; +class MDNode; /// \brief This provides the default implementation of the IRBuilder /// 'InsertHelper' method that is called whenever an instruction is created by @@ -364,43 +364,60 @@ public: /// \brief Create and insert a memset to the specified pointer and the /// specified value. /// - /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memcpy between the specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr) { + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, - TBAAStructTag); + TBAAStructTag, ScopeTag, NoAliasTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr); + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memmove between the specified /// pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create a lifetime.start intrinsic. /// @@ -412,7 +429,46 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + + /// \brief Create an assume intrinsic call that allows the optimizer to + /// assume that the provided condition will be true. + CallInst *CreateAssumption(Value *Cond); + + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepoint(Value *ActualCallee, + ArrayRef<Value*> CallArgs, + ArrayRef<Value*> DeoptArgs, + ArrayRef<Value*> GCArgs, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); + private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -429,7 +485,7 @@ private: /// The first template argument handles whether or not to preserve names in the /// final instruction output. This defaults to on. The second template argument /// specifies a class to use for creating constants. This defaults to creating -/// minimally folded constants. The fourth template argument allows clients to +/// minimally folded constants. The third template argument allows clients to /// specify custom insertion hooks that are called on every newly created /// insertion. template<bool preserveNames = true, typename T = ConstantFolder, @@ -570,8 +626,7 @@ public: InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, const Twine &Name = "") { - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, - ArrayRef<Value *>()), + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None), Name); } InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, @@ -1226,6 +1281,18 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the @@ -1508,6 +1575,44 @@ public: } return V; } + + /// \brief Create an assume intrinsic call that represents an alignment + /// assumption on the provided pointer. + /// + /// An optional offset can be provided, and if it is provided, the offset + /// must be subtracted from the provided pointer to get the pointer with the + /// specified alignment. + CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, + unsigned Alignment, + Value *OffsetValue = nullptr) { + assert(isa<PointerType>(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + + PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + Value *Mask = ConstantInt::get(IntPtrTy, + Alignment > 0 ? Alignment - 1 : 0); + if (OffsetValue) { + bool IsOffsetZero = false; + if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, + "offsetcast"); + PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + Value *Zero = ConstantInt::get(IntPtrTy, 0); + Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); + Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + + return CreateAssumption(InvCond); + } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 2f78c83165eb..7f2027b6e297 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -16,8 +16,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_IR_PRINTING_PASSES_H -#define LLVM_IR_IR_PRINTING_PASSES_H +#ifndef LLVM_IR_IRPRINTINGPASSES_H +#define LLVM_IR_IRPRINTINGPASSES_H #include "llvm/ADT/StringRef.h" #include <string> @@ -58,7 +58,7 @@ public: PrintModulePass(); PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "PrintModulePass"; } }; @@ -75,7 +75,7 @@ public: PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Function &F); static StringRef name() { return "PrintFunctionPass"; } }; diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index ac190892bab0..b2d79d0f0bfc 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -25,12 +25,9 @@ namespace llvm { class PointerType; class FunctionType; class Module; + struct InlineAsmKeyType; -template<class ValType, class ValRefType, class TypeClass, class ConstantClass, - bool HasLargeKey> -class ConstantUniqueMap; -template<class ConstantClass, class TypeClass, class ValType> -struct ConstantCreator; +template <class ConstantClass> class ConstantUniqueMap; class InlineAsm : public Value { public: @@ -40,9 +37,8 @@ public: }; private: - friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>; - friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, - PointerType, InlineAsm, false>; + friend struct InlineAsmKeyType; + friend class ConstantUniqueMap<InlineAsm>; InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 981aad852b29..030f5d690a0c 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -29,8 +29,8 @@ class LLVMContext; // TerminatorInst Class //===----------------------------------------------------------------------===// -/// TerminatorInst - Subclasses of this class are all able to terminate a basic -/// block. Thus, these are all the flow control type of operations. +/// Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. /// class TerminatorInst : public Instruction { protected: @@ -51,23 +51,19 @@ protected: virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; virtual unsigned getNumSuccessorsV() const = 0; virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; - TerminatorInst *clone_impl() const override = 0; public: - /// getNumSuccessors - Return the number of successors that this terminator - /// has. + /// Return the number of successors that this terminator has. unsigned getNumSuccessors() const { return getNumSuccessorsV(); } - /// getSuccessor - Return the specified successor. - /// + /// Return the specified successor. BasicBlock *getSuccessor(unsigned idx) const { return getSuccessorV(idx); } - /// setSuccessor - Update the specified successor to point at the provided - /// block. + /// Update the specified successor to point at the provided block. void setSuccessor(unsigned idx, BasicBlock *B) { setSuccessorV(idx, B); } @@ -153,7 +149,7 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// Create() - Construct a binary instruction, given the opcode and the two + /// Construct a binary instruction, given the opcode and the two /// operands. Optionally (if InstBefore is specified) insert the instruction /// into a BasicBlock right before the specified instruction. The specified /// Instruction is allowed to be a dereferenced end iterator. @@ -162,14 +158,14 @@ public: const Twine &Name = Twine(), Instruction *InsertBefore = nullptr); - /// Create() - Construct a binary instruction, given the opcode and the two + /// Construct a binary instruction, given the opcode and the two /// operands. Also automatically insert this instruction to the end of the /// BasicBlock specified. /// static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - /// Create* - These methods just forward to Create, and are useful when you + /// These methods just forward to Create, and are useful when you /// statically know what type of instruction you're going to create. These /// helpers just save some typing. #define HANDLE_BINARY_INST(N, OPC, CLASS) \ @@ -281,8 +277,7 @@ public: /// Helper functions to construct and inspect unary operations (NEG and NOT) /// via binary operators SUB and XOR: /// - /// CreateNeg, CreateNot - Create the NEG and NOT - /// instructions out of SUB and XOR instructions. + /// Create the NEG and NOT instructions out of SUB and XOR instructions. /// static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", Instruction *InsertBefore = nullptr); @@ -305,16 +300,14 @@ public: static BinaryOperator *CreateNot(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); - /// isNeg, isFNeg, isNot - Check if the given Value is a - /// NEG, FNeg, or NOT instruction. + /// Check if the given Value is a NEG, FNeg, or NOT instruction. /// static bool isNeg(const Value *V); static bool isFNeg(const Value *V, bool IgnoreZeroSign=false); static bool isNot(const Value *V); - /// getNegArgument, getNotArgument - Helper functions to extract the - /// unary argument of a NEG, FNEG or NOT operation implemented via - /// Sub, FSub, or Xor. + /// Helper functions to extract the unary argument of a NEG, FNEG or NOT + /// operation implemented via Sub, FSub, or Xor. /// static const Value *getNegArgument(const Value *BinOp); static Value *getNegArgument( Value *BinOp); @@ -327,37 +320,42 @@ public: return static_cast<BinaryOps>(Instruction::getOpcode()); } - /// swapOperands - Exchange the two operands to this instruction. + /// Exchange the two operands to this instruction. /// This instruction is safe to use on any binary instruction and /// does not modify the semantics of the instruction. If the instruction /// cannot be reversed (ie, it's a Div), then return true. /// bool swapOperands(); - /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setHasNoUnsignedWrap(bool b = true); - /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setHasNoSignedWrap(bool b = true); - /// setIsExact - Set or clear the exact flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the exact flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setIsExact(bool b = true); - /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set. + /// Determine whether the no unsigned wrap flag is set. bool hasNoUnsignedWrap() const; - /// hasNoSignedWrap - Determine whether the no signed wrap flag is set. + /// Determine whether the no signed wrap flag is set. bool hasNoSignedWrap() const; - /// isExact - Determine whether the exact flag is set. + /// Determine whether the exact flag is set. bool isExact() const; + /// Convenience method to copy supported wrapping, exact, and fast-math flags + /// from V to this instruction. + void copyIRFlags(const Value *V); + + /// Logical 'and' of any supported wrapping, exact, and fast-math flags of + /// V and this instruction. + void andIRFlags(const Value *V); + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->isBinaryOp(); @@ -378,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) // CastInst Class //===----------------------------------------------------------------------===// -/// CastInst - This is the base class for all instructions that perform data +/// This is the base class for all instructions that perform data /// casts. It is simply provided so that instruction category testing /// can be performed with code like: /// @@ -491,6 +489,19 @@ public: Instruction *InsertBefore = 0 ///< Place to insert the instruction ); + /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// + /// If the value is a pointer type and the destination an integer type, + /// creates a PtrToInt cast. If the value is an integer type and the + /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates + /// a bitcast. + static CastInst *CreateBitOrPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) @@ -553,6 +564,17 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// types is valid and a no-op. + /// + /// This ensures that any pointer<->integer cast has enough bits in the + /// integer and any other cast is a bitcast. + static bool isBitOrNoopPointerCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout *Layout = 0 ///< Optional DataLayout. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index bac6a95b1b71..ba7791c99b6a 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -25,6 +25,7 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +struct AAMDNodes; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; @@ -155,19 +156,25 @@ public: /// getAllMetadata - Get all metadata attached to this Instruction. The first /// element of each pair returned is the KindID, the second element is the /// metadata value. This list is returned sorted by the KindID. - void getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode*> > &MDs)const{ + void + getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const { if (hasMetadata()) getAllMetadataImpl(MDs); } /// getAllMetadataOtherThanDebugLoc - This does the same thing as /// getAllMetadata, except that it filters out the debug location. - void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned, - MDNode*> > &MDs) const { + void getAllMetadataOtherThanDebugLoc( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const { if (hasMetadataOtherThanDebugLoc()) getAllMetadataOtherThanDebugLocImpl(MDs); } + /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from + /// this instruction. When Merge is true, the existing AA metadata is + /// merged with that from this instruction providing the most-general result. + void getAAMetadata(AAMDNodes &N, bool Merge = false) const; + /// setMetadata - Set the metadata of the specified kind to the specified /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. @@ -179,7 +186,7 @@ public: /// convenience method for passes to do so. void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs); void dropUnknownMetadata() { - return dropUnknownMetadata(ArrayRef<unsigned>()); + return dropUnknownMetadata(None); } void dropUnknownMetadata(unsigned ID1) { return dropUnknownMetadata(makeArrayRef(ID1)); @@ -189,6 +196,10 @@ public: return dropUnknownMetadata(IDs); } + /// setAAMetadata - Sets the metadata on this instruction from the + /// AAMDNodes structure. + void setAAMetadata(const AAMDNodes &N); + /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } @@ -220,11 +231,16 @@ public: /// this flag. void setHasAllowReciprocal(bool B); - /// Convenience function for setting all the fast-math flags on this + /// Convenience function for setting multiple fast-math flags on this /// instruction, which must be an operator which supports these flags. See - /// LangRef.html for the meaning of these flats. + /// LangRef.html for the meaning of these flags. void setFastMathFlags(FastMathFlags FMF); + /// Convenience function for transferring all fast-math flag values to this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flags. + void copyFastMathFlags(FastMathFlags FMF); + /// Determine whether the unsafe-algebra flag is set. bool hasUnsafeAlgebra() const; @@ -242,7 +258,7 @@ public: /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of - /// these flats. + /// these flags. FastMathFlags getFastMathFlags() const; /// Copy I's fast-math flags @@ -258,9 +274,10 @@ private: // These are all implemented in Metadata.cpp. MDNode *getMetadataImpl(unsigned KindID) const; MDNode *getMetadataImpl(StringRef Kind) const; - void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const; - void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned, - MDNode*> > &) const; + void + getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const; + void getAllMetadataOtherThanDebugLocImpl( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const; void clearMetadataHashEntries(); public: //===--------------------------------------------------------------------===// @@ -323,6 +340,11 @@ public: return mayReadFromMemory() || mayWriteToMemory(); } + /// isAtomic - Return true if this instruction has an + /// AtomicOrdering of unordered or higher. + /// + bool isAtomic() const; + /// mayThrow - Return true if this instruction may throw an exception. /// bool mayThrow() const; diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 308467f7aa17..045e51eb1baa 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,8 +17,8 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" @@ -50,6 +50,22 @@ enum SynchronizationScope { CrossThread = 1 }; +/// Returns true if the ordering is at least as strong as acquire +/// (i.e. acquire, acq_rel or seq_cst) +inline bool isAtLeastAcquire(AtomicOrdering Ord) { + return (Ord == Acquire || + Ord == AcquireRelease || + Ord == SequentiallyConsistent); +} + +/// Returns true if the ordering is at least as strong as release +/// (i.e. release, acq_rel or seq_cst) +inline bool isAtLeastRelease(AtomicOrdering Ord) { +return (Ord == Release || + Ord == AcquireRelease || + Ord == SequentiallyConsistent); +} + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -119,7 +135,7 @@ public: return getSubclassDataFromInstruction() & 32; } - /// \brief Specify whether this alloca is used to represent a the arguments to + /// \brief Specify whether this alloca is used to represent the arguments to /// a call. void setUsedWithInAlloca(bool V) { setInstructionSubclassData((getSubclassDataFromInstruction() & ~32) | @@ -225,7 +241,6 @@ public: (xthread << 6)); } - bool isAtomic() const { return getOrdering() != NotAtomic; } void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread) { setOrdering(Ordering); @@ -345,7 +360,6 @@ public: (xthread << 6)); } - bool isAtomic() const { return getOrdering() != NotAtomic; } void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread) { setOrdering(Ordering); @@ -637,7 +651,7 @@ public: Sub, /// *p = old & v And, - /// *p = ~old & v + /// *p = ~(old & v) Nand, /// *p = old | v Or, diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index e053f7867c53..c227ea080167 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -28,6 +28,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Metadata.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic @@ -81,7 +82,14 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); } + MDNode *getVariable() const { + return cast<MDNode>( + cast<MetadataAsValue>(getArgOperand(1))->getMetadata()); + } + MDNode *getExpression() const { + return cast<MDNode>( + cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -102,7 +110,14 @@ namespace llvm { return cast<ConstantInt>( const_cast<Value*>(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); } + MDNode *getVariable() const { + return cast<MDNode>( + cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + } + MDNode *getExpression() const { + return cast<MDNode>( + cast<MetadataAsValue>(getArgOperand(3))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -320,6 +335,33 @@ namespace llvm { Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); } }; + /// This represents the llvm.instrprof_increment intrinsic. + class InstrProfIncrementInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_increment; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + GlobalVariable *getName() const { + return cast<GlobalVariable>( + const_cast<Value *>(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); + } + + ConstantInt *getNumCounters() const { + return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2))); + } + + ConstantInt *getIndex() const { + return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3))); + } + }; } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index b0d746bd4127..56d1e4af26aa 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -28,10 +28,9 @@ class LLVMContext; class Module; class AttributeSet; -/// Intrinsic Namespace - This namespace contains an enum with a value for -/// every intrinsic/builtin function known by LLVM. These enum values are -/// returned by Function::getIntrinsicID(). -/// +/// This namespace contains an enum with a value for every intrinsic/builtin +/// function known by LLVM. The enum values are returned by +/// Function::getIntrinsicID(). namespace Intrinsic { enum ID { not_intrinsic = 0, // Must be zero @@ -43,25 +42,21 @@ namespace Intrinsic { , num_intrinsics }; - /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as - /// "llvm.ppc.altivec.lvx". + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef<Type*> Tys = None); - /// Intrinsic::getType(ID) - Return the function type for an intrinsic. - /// + /// Return the function type for an intrinsic. FunctionType *getType(LLVMContext &Context, ID id, ArrayRef<Type*> Tys = None); - /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be - /// overloaded. + /// Returns true if the intrinsic can be overloaded. bool isOverloaded(ID id); - /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. - /// + /// Return the attributes for an intrinsic. AttributeSet getAttributes(LLVMContext &C, ID id); - /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function - /// declaration for an intrinsic, and return it. + /// Create or insert an LLVM Function declaration for an intrinsic, and return + /// it. /// /// The Tys parameter is for intrinsics with overloaded types (e.g., those /// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded @@ -75,14 +70,14 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - /// IITDescriptor - This is a type descriptor which explains the type - /// requirements of an intrinsic. This is returned by - /// getIntrinsicInfoTableEntries. + /// This is a type descriptor which explains the type requirements of an + /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendArgument, TruncArgument, HalfVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument, + SameVecWidthArgument, PtrToArgument } Kind; union { @@ -102,13 +97,15 @@ namespace Intrinsic { }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument); return Argument_Info >> 2; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return (ArgKind)(Argument_Info&3); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument); + return (ArgKind)(Argument_Info & 3); } static IITDescriptor get(IITDescriptorKind K, unsigned Field) { @@ -117,9 +114,8 @@ namespace Intrinsic { } }; - /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the - /// specified intrinsic into an array of IITDescriptors. - /// + /// Return the IIT table descriptor for the specified intrinsic into an array + /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T); } // End Intrinsic namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 0b8f64fc7984..a1188bccdc25 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -112,6 +112,11 @@ class LLVMMatchType<int num> // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType<int num> : LLVMMatchType<num>; class LLVMTruncatedType<int num> : LLVMMatchType<num>; +class LLVMVectorSameWidth<int num, LLVMType elty> + : LLVMMatchType<num> { + ValueType ElTy = elty.VT; +} +class LLVMPointerTo<int num> : LLVMMatchType<num>; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many @@ -254,6 +259,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_framerecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -277,12 +286,22 @@ def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; +// The assume intrinsic is marked as arbitrarily writing so that proper +// control dependencies will be maintained. +def int_assume : Intrinsic<[], [llvm_i1_ty], []>; + // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], [IntrReadWriteArgMem]>; +// A counter increment for instrumentation based profiling. +def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // @@ -324,6 +343,8 @@ let Properties = [IntrNoMem] in { def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_copysign : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; @@ -369,9 +390,12 @@ let Properties = [IntrNoMem] in { // places. let Properties = [IntrNoMem] in { def int_dbg_declare : Intrinsic<[], - [llvm_metadata_ty, llvm_metadata_ty]>; + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; def int_dbg_value : Intrinsic<[], [llvm_metadata_ty, llvm_i64_ty, + llvm_metadata_ty, llvm_metadata_ty]>; } @@ -476,11 +500,29 @@ def int_experimental_stackmap : Intrinsic<[], def int_experimental_patchpoint_void : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty]>; + llvm_vararg_ty], + [Throws]>; def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty]>; + llvm_vararg_ty], + [Throws]>; + + +//===------------------------ Garbage Collection Intrinsics ---------------===// +// These are documented in docs/Statepoint.rst + +def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty]>; + +def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], + [llvm_i32_ty]>; +def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; + +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; //===-------------------------- Other Intrinsics --------------------------===// // @@ -528,6 +570,17 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +//===-------------------------- Masked Intrinsics -------------------------===// +// +def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, + llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMPointerTo<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadArgMem]>; //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index a02d7072d720..ce758e257312 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -20,8 +20,13 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +// A space-consuming intrinsic primarily for testing ARMConstantIslands. The +// first argument is the number of bytes this "instruction" takes up, the second +// and return value are essentially chains, used to force ordering during ISel. +def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; + //===----------------------------------------------------------------------===// -// Saturating Arithmentic +// Saturating Arithmetic def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], @@ -132,6 +137,7 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], // HINT def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // RBIT @@ -340,10 +346,6 @@ def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; // Vector Count Leading Sign/Zero Bits. def int_arm_neon_vcls : Neon_1Arg_Intrinsic; -def int_arm_neon_vclz : Neon_1Arg_Intrinsic; - -// Vector Count One Bits. -def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; // Vector Reciprocal Estimate. def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index cd512841a1af..9deed414b50a 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -797,24 +797,30 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64* // Generated within nvvm. Use for ldu on sm_20 or later def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.i">; def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.f">; def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.p">; // Generated within nvvm. Use for ldg on sm_35 or later def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.i">; def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.f">; def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.p">; // Use for generic pointers diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 49ddfb8b613b..5cdabdeadaea 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -28,8 +28,10 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; - // sync instruction + // sync instruction (i.e. sync 0, a.k.a hwsync) def int_ppc_sync : Intrinsic<[], [], []>; + // lwsync is sync 1 + def int_ppc_lwsync : Intrinsic<[], [], []>; // Intrinsics used to generate ctr-based loops. These should only be // generated by the PowerPC backend! @@ -45,6 +47,13 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". list<IntrinsicProperty> properties> : GCCBuiltin<!strconcat("__builtin_altivec_", GCCIntSuffix)>, Intrinsic<ret_types, param_types, properties>; + + /// PowerPC_VSX_Intrinsic - Base class for all VSX intrinsics. + class PowerPC_VSX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_vsx_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; } //===----------------------------------------------------------------------===// @@ -87,6 +96,32 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> //===----------------------------------------------------------------------===// +// PowerPC VSX Intrinsic Class Definitions. +// + +/// PowerPC_VSX_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Vec_DDD_Intrinsic<string GCCIntSuffix> + : PowerPC_VSX_Intrinsic<GCCIntSuffix, + [llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +/// PowerPC_VSX_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Vec_FFF_Intrinsic<string GCCIntSuffix> + : PowerPC_VSX_Intrinsic<GCCIntSuffix, + [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +/// PowerPC_VSX_Sca_DDD_Intrinsic - A PowerPC intrinsic that takes two f64 +/// scalars and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix> + : PowerPC_VSX_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; + + +//===----------------------------------------------------------------------===// // PowerPC Altivec Intrinsic Definitions. let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". @@ -474,3 +509,36 @@ def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; + + +//===----------------------------------------------------------------------===// +// PowerPC VSX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + +// Vector load. +def int_ppc_vsx_lxvw4x : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; +def int_ppc_vsx_lxvd2x : + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + +// Vector store. +def int_ppc_vsx_stxvw4x : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>; +def int_ppc_vsx_stxvd2x : + Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>; + +// Vector and scalar maximum. +def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">; +def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">; +def int_ppc_vsx_xsmaxdp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmaxdp">; + +// Vector and scalar minimum. +def int_ppc_vsx_xvmindp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmindp">; +def int_ppc_vsx_xvminsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvminsp">; +def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; + +// Vector divide. +def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; +def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; +} diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index ba69eaae089f..505566738221 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -33,10 +33,14 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tgid">; defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tidig">; - } // End TargetPrefix = "r600" let TargetPrefix = "AMDGPU" in { + +class AMDGPUReadPreloadRegisterIntrinsic<string name> + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<name>; + def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, // 1st parameter: Numerator // 2nd parameter: Denominator @@ -48,7 +52,7 @@ def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], [IntrNoMem]>; def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, @@ -69,4 +73,13 @@ def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; +def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < + "__builtin_amdgpu_read_workdim">; + } // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 5de950813cd4..81c729065505 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -886,7 +886,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; } @@ -896,13 +896,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], [IntrNoMem]>; def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], @@ -915,17 +915,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector dot product let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty], + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, Commutative]>; } // Vector sum of absolute differences let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty], + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty], [IntrNoMem, Commutative]>; } @@ -1171,10 +1171,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; @@ -1187,7 +1187,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector compare @@ -1389,6 +1389,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ss : + GCCBuiltin<"__builtin_ia32_storess_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; } //===----------------------------------------------------------------------===// @@ -1580,6 +1584,44 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrai_d : GCCBuiltin<"__builtin_ia32_psradi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Pack ops. @@ -1706,13 +1748,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v32i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -1787,6 +1829,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vextractf32x4_512 : + GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextracti32x4_512 : + GCCBuiltin<"__builtin_ia32_extracti32x4_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i32_ty, llvm_i8_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextractf64x4_512 : + GCCBuiltin<"__builtin_ia32_extractf64x4_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextracti64x4_512 : + GCCBuiltin<"__builtin_ia32_extracti64x4_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Conditional load ops @@ -1871,6 +1930,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; } // Gather ops @@ -1951,11 +2035,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v32i8_ty], [IntrNoMem]>; def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrNoMem, Commutative]>; + llvm_i8_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>; - def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, - Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// @@ -1986,13 +2068,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">, + def int_x86_fma_mask_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">, + def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], @@ -2018,13 +2122,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">, + def int_x86_fma_mask_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">, + def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], @@ -2050,13 +2176,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">, + def int_x86_fma_mask_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">, + def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], @@ -2082,13 +2230,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">, + def int_x86_fma_mask_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">, + def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], @@ -2108,13 +2278,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">, + def int_x86_fma_mask_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">, + def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], @@ -2134,13 +2326,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">, + def int_x86_fma_mask_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">, + def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; } @@ -2749,6 +2963,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// ADX + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarry_u32: GCCBuiltin<"__builtin_ia32_addcarry_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarry_u64: GCCBuiltin<"__builtin_ia32_addcarry_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_subborrow_u32: GCCBuiltin<"__builtin_ia32_subborrow_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_subborrow_u64: GCCBuiltin<"__builtin_ia32_subborrow_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; +} + +//===----------------------------------------------------------------------===// // RTM intrinsics. Transactional Memory support. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". @@ -2955,10 +3193,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, @@ -2993,6 +3233,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], @@ -3167,10 +3414,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -3180,8 +3443,428 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +} + +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_valign_q_512 : GCCBuiltin<"__builtin_ia32_alignq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_valign_d_512 : GCCBuiltin<"__builtin_ia32_alignd512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; } +// Compares +let TargetPrefix = "x86" in { + // 512-bit + def int_x86_avx512_mask_pcmpeq_b_512 : GCCBuiltin<"__builtin_ia32_pcmpeqb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_512 : GCCBuiltin<"__builtin_ia32_pcmpeqw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_512: GCCBuiltin<"__builtin_ia32_pcmpgtb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_512: GCCBuiltin<"__builtin_ia32_pcmpgtw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_512: GCCBuiltin<"__builtin_ia32_pcmpgtd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_512: GCCBuiltin<"__builtin_ia32_pcmpgtq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem ]>; + def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + // 256-bit + def int_x86_avx512_mask_pcmpeq_b_256 : GCCBuiltin<"__builtin_ia32_pcmpeqb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_256 : GCCBuiltin<"__builtin_ia32_pcmpeqw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_256 : GCCBuiltin<"__builtin_ia32_pcmpeqd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_256 : GCCBuiltin<"__builtin_ia32_pcmpeqq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_256: GCCBuiltin<"__builtin_ia32_pcmpgtb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_256: GCCBuiltin<"__builtin_ia32_pcmpgtw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_256: GCCBuiltin<"__builtin_ia32_pcmpgtd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_256: GCCBuiltin<"__builtin_ia32_pcmpgtq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + // 128-bit + def int_x86_avx512_mask_pcmpeq_b_128 : GCCBuiltin<"__builtin_ia32_pcmpeqb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_128 : GCCBuiltin<"__builtin_ia32_pcmpeqw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_128 : GCCBuiltin<"__builtin_ia32_pcmpeqd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_128 : GCCBuiltin<"__builtin_ia32_pcmpeqq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_128: GCCBuiltin<"__builtin_ia32_pcmpgtb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_128: GCCBuiltin<"__builtin_ia32_pcmpgtw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_128: GCCBuiltin<"__builtin_ia32_pcmpgtd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_128: GCCBuiltin<"__builtin_ia32_pcmpgtq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; +} + +// Compress, Expand +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_compress_ps_512 : + GCCBuiltin<"__builtin_ia32_compresssf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_512 : + GCCBuiltin<"__builtin_ia32_compressdf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_256 : + GCCBuiltin<"__builtin_ia32_compresssf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_256 : + GCCBuiltin<"__builtin_ia32_compressdf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_128 : + GCCBuiltin<"__builtin_ia32_compresssf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_128 : + GCCBuiltin<"__builtin_ia32_compressdf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_ps_512 : + GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_512 : + GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_256 : + GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_256 : + GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_128 : + GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_128 : + GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + + def int_x86_avx512_mask_compress_d_512 : + GCCBuiltin<"__builtin_ia32_compresssi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_512 : + GCCBuiltin<"__builtin_ia32_compressdi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_256 : + GCCBuiltin<"__builtin_ia32_compresssi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_256 : + GCCBuiltin<"__builtin_ia32_compressdi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_128 : + GCCBuiltin<"__builtin_ia32_compresssi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_128 : + GCCBuiltin<"__builtin_ia32_compressdi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_d_512 : + GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_512 : + GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_256 : + GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_256 : + GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_128 : + GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_128 : + GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + +// expand + def int_x86_avx512_mask_expand_ps_512 : + GCCBuiltin<"__builtin_ia32_expandsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_512 : + GCCBuiltin<"__builtin_ia32_expanddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_256 : + GCCBuiltin<"__builtin_ia32_expandsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_256 : + GCCBuiltin<"__builtin_ia32_expanddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_128 : + GCCBuiltin<"__builtin_ia32_expandsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_128 : + GCCBuiltin<"__builtin_ia32_expanddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_ps_512 : + GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_512 : + GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_256 : + GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_256 : + GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_128 : + GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_128 : + GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + + def int_x86_avx512_mask_expand_d_512 : + GCCBuiltin<"__builtin_ia32_expandsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_512 : + GCCBuiltin<"__builtin_ia32_expanddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_256 : + GCCBuiltin<"__builtin_ia32_expandsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_256 : + GCCBuiltin<"__builtin_ia32_expanddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_128 : + GCCBuiltin<"__builtin_ia32_expandsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_128 : + GCCBuiltin<"__builtin_ia32_expanddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_d_512 : + GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_512 : + GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_256 : + GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_256 : + GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_128 : + GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_128 : + GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + +} // Misc. let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, @@ -3190,13 +3873,6 @@ let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], @@ -3205,6 +3881,8 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 4d940d599b9a..2f18782a0730 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -18,6 +18,7 @@ #include "llvm-c/Core.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Options.h" namespace llvm { @@ -52,7 +53,12 @@ public: MD_fpmath = 3, // "fpmath" MD_range = 4, // "range" MD_tbaa_struct = 5, // "tbaa.struct" - MD_invariant_load = 6 // "invariant.load" + MD_invariant_load = 6, // "invariant.load" + MD_alias_scope = 7, // "alias.scope" + MD_noalias = 8, // "noalias", + MD_nontemporal = 9, // "nontemporal" + MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" + MD_nonnull = 11 // "nonnull" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -97,12 +103,14 @@ public: /// setDiagnosticHandler - This method sets a handler that is invoked /// when the backend needs to report anything to the user. The first /// argument is a function pointer and the second is a context pointer that - /// gets passed into the DiagHandler. + /// gets passed into the DiagHandler. The third argument should be set to + /// true if the handler only expects enabled diagnostics. /// /// LLVMContext doesn't take ownership or interpret either of these /// pointers. void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler, - void *DiagContext = nullptr); + void *DiagContext = nullptr, + bool RespectFilters = false); /// getDiagnosticHandler - Return the diagnostic handler set by /// setDiagnosticHandler. @@ -112,14 +120,16 @@ public: /// setDiagnosticContext. void *getDiagnosticContext() const; - /// diagnose - Report a message to the currently installed diagnostic handler. + /// \brief Report a message to the currently installed diagnostic handler. + /// /// This function returns, in particular in the case of error reporting - /// (DI.Severity == RS_Error), so the caller should leave the compilation + /// (DI.Severity == \a DS_Error), so the caller should leave the compilation /// process in a self-consistent state, even though the generated code /// need not be correct. - /// The diagnostic message will be implicitly prefixed with a severity - /// keyword according to \p DI.getSeverity(), i.e., "error: " - /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note. + /// + /// The diagnostic message will be implicitly prefixed with a severity keyword + /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error, + /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note. void diagnose(const DiagnosticInfo &DI); /// \brief Registers a yield callback with the given context. @@ -157,6 +167,14 @@ public: void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); + /// \brief Query for a debug option's value. + /// + /// This function returns typed data populated from command line parsing. + template <typename ValT, typename Base, ValT(Base::*Mem)> + ValT getOption() const { + return OptionRegistry::instance().template get<ValT, Base, Mem>(); + } + private: LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index cb18df875867..000000000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include <string> - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index c967a6bca8b2..6c04e9dc3d3f 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -37,9 +37,10 @@ class PassManagerBase { public: virtual ~PassManagerBase(); - /// add - Add a pass to the queue of passes to run. This passes ownership of + /// Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This + /// may even destroy the pass right away if it is found to be redundant. This /// implies that all passes MUST be allocated with 'new'. virtual void add(Pass *P) = 0; }; @@ -51,10 +52,6 @@ public: PassManager(); ~PassManager(); - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep track of @@ -75,11 +72,6 @@ public: explicit FunctionPassManager(Module *M); ~FunctionPassManager(); - /// add - Add a pass to the queue of passes to run. This passes - /// ownership of the Pass to the PassManager. When the - /// PassManager_X is destroyed, the pass will be destroyed as well, so - /// there is no need to delete the pass. - /// This implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index f6065a4e21a6..ab500a1dd2a3 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PASSMANAGERS_H -#define LLVM_PASSMANAGERS_H +#ifndef LLVM_IR_LEGACYPASSMANAGERS_H +#define LLVM_IR_LEGACYPASSMANAGERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -61,7 +61,7 @@ // // [o] class FunctionPassManager; // -// This is a external interface used by JIT to manage FunctionPasses. This +// This is a external interface used to manage FunctionPasses. This // interface relies on FunctionPassManagerImpl to do all the tasks. // // [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, @@ -248,7 +248,7 @@ private: DenseMap<Pass *, SmallPtrSet<Pass *, 8> > InversedLastUser; /// Immutable passes are managed by top level manager. - SmallVector<ImmutablePass *, 8> ImmutablePasses; + SmallVector<ImmutablePass *, 16> ImmutablePasses; DenseMap<Pass *, AnalysisUsage *> AnUsageMap; }; @@ -393,7 +393,7 @@ private: // Collection of higher level analysis used by the pass managed by // this manager. - SmallVector<Pass *, 8> HigherLevelAnalysis; + SmallVector<Pass *, 16> HigherLevelAnalysis; unsigned Depth; }; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 37d263bf52a8..91a6685f6125 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_MDBUILDER_H #define LLVM_IR_MDBUILDER_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include <utility> @@ -23,9 +24,10 @@ namespace llvm { class APInt; template <typename T> class ArrayRef; class LLVMContext; +class Constant; +class ConstantAsMetadata; class MDNode; class MDString; -class StringRef; class MDBuilder { LLVMContext &Context; @@ -36,6 +38,9 @@ public: /// \brief Return the given string as metadata. MDString *createString(StringRef Str); + /// \brief Return the given constant as metadata. + ConstantAsMetadata *createConstant(Constant *C); + //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// @@ -63,19 +68,54 @@ public: MDNode *createRange(const APInt &Lo, const APInt &Hi); //===------------------------------------------------------------------===// - // TBAA metadata. + // AA metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata appropriate for a TBAA root node. Each returned +protected: + /// \brief Return metadata appropriate for a AA root node (scope or TBAA). + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAARoot(StringRef Name = StringRef(), + MDNode *Extra = nullptr); + +public: + /// \brief Return metadata appropriate for a TBAA root node. Each returned /// node is distinct from all other metadata and will never be identified /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot(); + MDNode *createAnonymousTBAARoot() { + return createAnonymousAARoot(); + } + + /// \brief Return metadata appropriate for an alias scope domain node. + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) { + return createAnonymousAARoot(Name); + } + + /// \brief Return metadata appropriate for an alias scope root node. + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAliasScope(MDNode *Domain, + StringRef Name = StringRef()) { + return createAnonymousAARoot(Name, Domain); + } /// \brief Return metadata appropriate for a TBAA root node with the given /// name. This may be identified (uniqued) with other roots with the same /// name. MDNode *createTBAARoot(StringRef Name); + /// \brief Return metadata appropriate for an alias scope domain node with + /// the given name. This may be identified (uniqued) with other roots with + /// the same name. + MDNode *createAliasScopeDomain(StringRef Name); + + /// \brief Return metadata appropriate for an alias scope node with + /// the given name. This may be identified (uniqued) with other scopes with + /// the same name and domain. + MDNode *createAliasScope(StringRef Name, MDNode *Domain); + /// \brief Return metadata for a non-root TBAA node with the given name, /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. MDNode *createTBAANode(StringRef Name, MDNode *Parent, diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h index c1ba5858a612..1e6b5b1dca00 100644 --- a/include/llvm/IR/Mangler.h +++ b/include/llvm/IR/Mangler.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_MANGLER_H -#define LLVM_TARGET_MANGLER_H +#ifndef LLVM_IR_MANGLER_H +#define LLVM_IR_MANGLER_H #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" @@ -66,4 +66,4 @@ public: } // End llvm namespace -#endif // LLVM_TARGET_MANGLER_H +#endif diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def new file mode 100644 index 000000000000..2098bb57eb56 --- /dev/null +++ b/include/llvm/IR/Metadata.def @@ -0,0 +1,59 @@ +//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \ + defined HANDLE_UNIQUABLE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes under UniquableMDNode. +#ifndef HANDLE_UNIQUABLE_LEAF +#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under UniquableMDNode. +#ifndef HANDLE_UNIQUABLE_BRANCH +#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_METADATA_BRANCH(MDNode) +HANDLE_METADATA_LEAF(MDNodeFwdDecl) +HANDLE_UNIQUABLE_BRANCH(UniquableMDNode) +HANDLE_UNIQUABLE_LEAF(MDTuple) +HANDLE_UNIQUABLE_LEAF(MDLocation) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_UNIQUABLE_LEAF +#undef HANDLE_UNIQUABLE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 7a0ca887201b..3bf6d38d311d 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -17,10 +17,14 @@ #define LLVM_IR_METADATA_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/MetadataTracking.h" #include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" +#include <type_traits> namespace llvm { class LLVMContext; @@ -30,169 +34,887 @@ template<typename ValueSubClass, typename ItemParentClass> enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 1 // Current debug info version number. + DEBUG_METADATA_VERSION = 2 // Current debug info version number. }; +/// \brief Root of the metadata hierarchy. +/// +/// This is a root class for typeless data in the IR. +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + bool IsDistinctInContext : 1; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { + MDTupleKind, + MDLocationKind, + MDNodeFwdDeclKind, + ConstantAsMetadataKind, + LocalAsMetadataKind, + MDStringKind + }; + +protected: + Metadata(unsigned ID) + : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0), + SubclassData32(0) {} + ~Metadata() {} + + /// \brief Store this in a big non-uniqued untyped bucket. + bool isStoredDistinctInContext() const { return IsDistinctInContext; } + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + void dump() const; + void print(raw_ostream &OS) const; + void printAsOperand(raw_ostream &OS, bool PrintType = true, + const Module *M = nullptr) const; +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue(); + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } + +public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + + static bool classof(const Value *V) { + return V->getValueID() == MetadataAsValueVal; + } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); +}; + +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + uint64_t NextIndex; + SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap; + +public: + ReplaceableMetadataImpl() : NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last + /// operand is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + static ReplaceableMetadataImpl *get(Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() {} + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast<ConstantAsMetadata>(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast<LocalAsMetadata>(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null<ConstantAsMetadata>(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null<LocalAsMetadata>(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast<Constant>(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa<Constant>(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast<ConstantInt>(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast<MDInt>(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template <class T> T &make(); +template <class T, class Result> struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template <size_t N> struct SFINAE {}; + + template <class U, class V> + static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0); + template <class U, class V> static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes); +}; +template <class V, class M> struct IsValidPointer { + static const bool value = std::is_base_of<Constant, V>::value && + HasDereference<M, const Metadata &>::value; +}; +template <class V, class M> struct IsValidReference { + static const bool value = std::is_base_of<Constant, V>::value && + std::is_convertible<M, const Metadata &>::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast<ConstantAsMetadata>(MD)) + return isa<X>(V->getValue()); + return false; +} +template <class X, class Y> +inline + typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +extract(Y &&MD) { + return cast<X>(cast<ConstantAsMetadata>(MD)->getValue()); +} +template <class X, class Y> +inline + typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null<ConstantAsMetadata>(MD)) + return cast<X>(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast<ConstantAsMetadata>(MD)) + return dyn_cast<X>(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD)) + return dyn_cast<X>(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + //===----------------------------------------------------------------------===// -/// MDString - a single uniqued string. +/// \brief A single uniqued string. +/// /// These are used to efficiently contain a byte sequence for metadata. /// MDString is always unnamed. -class MDString : public Value { - virtual void anchor(); +class MDString : public Metadata { + friend class StringMapEntry<MDString>; + MDString(const MDString &) LLVM_DELETED_FUNCTION; + MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION; + MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION; + + StringMapEntry<MDString> *Entry; + MDString() : Metadata(MDStringKind), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind) {} - explicit MDString(LLVMContext &C); public: static MDString *get(LLVMContext &Context, StringRef Str); static MDString *get(LLVMContext &Context, const char *Str) { return get(Context, Str ? StringRef(Str) : StringRef()); } - StringRef getString() const { return getName(); } + StringRef getString() const; - unsigned getLength() const { return (unsigned)getName().size(); } + unsigned getLength() const { return (unsigned)getString().size(); } typedef StringRef::iterator iterator; - /// begin() - Pointer to the first byte of the string. - iterator begin() const { return getName().begin(); } + /// \brief Pointer to the first byte of the string. + iterator begin() const { return getString().begin(); } - /// end() - Pointer to one byte past the end of the string. - iterator end() const { return getName().end(); } + /// \brief Pointer to one byte past the end of the string. + iterator end() const { return getString().end(); } - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; } }; +/// \brief A collection of metadata nodes that might be associated with a +/// memory access used by the alias-analysis infrastructure. +struct AAMDNodes { + explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, + MDNode *N = nullptr) + : TBAA(T), Scope(S), NoAlias(N) {} + + bool operator==(const AAMDNodes &A) const { + return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias; + } + + bool operator!=(const AAMDNodes &A) const { return !(*this == A); } + + LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + + /// \brief The tag for type-based alias analysis. + MDNode *TBAA; -class MDNodeOperand; + /// \brief The tag for alias scope specification (used with noalias). + MDNode *Scope; + + /// \brief The tag specifying the noalias scope. + MDNode *NoAlias; +}; + +// Specialize DenseMapInfo for AAMDNodes. +template<> +struct DenseMapInfo<AAMDNodes> { + static inline AAMDNodes getEmptyKey() { + return AAMDNodes(DenseMapInfo<MDNode *>::getEmptyKey(), 0, 0); + } + static inline AAMDNodes getTombstoneKey() { + return AAMDNodes(DenseMapInfo<MDNode *>::getTombstoneKey(), 0, 0); + } + static unsigned getHashValue(const AAMDNodes &Val) { + return DenseMapInfo<MDNode *>::getHashValue(Val.TBAA) ^ + DenseMapInfo<MDNode *>::getHashValue(Val.Scope) ^ + DenseMapInfo<MDNode *>::getHashValue(Val.NoAlias); + } + static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) { + return LHS == RHS; + } +}; + +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION; + MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION; + MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION; + MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION; + + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast<void *>(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type<MDOperand> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type<const MDOperand> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; //===----------------------------------------------------------------------===// -/// MDNode - a tuple of other values. -class MDNode : public Value, public FoldingSetNode { +/// \brief Tuple of metadata. +class MDNode : public Metadata { MDNode(const MDNode &) LLVM_DELETED_FUNCTION; void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - friend class MDNodeOperand; - friend class LLVMContextImpl; - friend struct FoldingSetTrait<MDNode>; - - /// Hash - If the MDNode is uniqued cache the hash to speed up lookup. - unsigned Hash; + void *operator new(size_t) LLVM_DELETED_FUNCTION; - /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the - /// end of this MDNode. + LLVMContext &Context; unsigned NumOperands; - // Subclass data enums. - enum { - /// FunctionLocalBit - This bit is set if this MDNode is function local. - /// This is true when it (potentially transitively) contains a reference to - /// something in a function, like an argument, basicblock, or instruction. - FunctionLocalBit = 1 << 0, +protected: + unsigned MDNodeSubclassData; - /// NotUniquedBit - This is set on MDNodes that are not uniqued because they - /// have a null operand. - NotUniquedBit = 1 << 1, + void *operator new(size_t Size, unsigned NumOps); + void operator delete(void *Mem); - /// DestroyFlag - This bit is set by destroy() so the destructor can assert - /// that the node isn't being destroyed with a plain 'delete'. - DestroyFlag = 1 << 2 - }; + /// \brief Required by std, but never called. + void operator delete(void *, unsigned) { + llvm_unreachable("Constructor throws?"); + } - // FunctionLocal enums. - enum FunctionLocalness { - FL_Unknown = -1, - FL_No = 0, - FL_Yes = 1 - }; + /// \brief Required by std, but never called. + void operator delete(void *, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } - /// replaceOperand - Replace each instance of F from the operand list of this - /// node with T. - void replaceOperand(MDNodeOperand *Op, Value *NewVal); - ~MDNode(); + MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs); + ~MDNode() {} - MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal); + void dropAllReferences(); + + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } - static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals, - FunctionLocalness FL, bool Insert = true); public: - // Constructors and destructors. - static MDNode *get(LLVMContext &Context, ArrayRef<Value*> Vals); - // getWhenValsUnresolved - Construct MDNode determining function-localness - // from isFunctionLocal argument, not by analyzing Vals. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, - ArrayRef<Value*> Vals, - bool isFunctionLocal); - - static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals); - - /// getTemporary - Return a temporary MDNode, for use in constructing - /// cyclic MDNode structures. A temporary MDNode is not uniqued, - /// may be RAUW'd, and must be manually deleted with deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals); - - /// deleteTemporary - Deallocate a node created by getTemporary. The - /// node must not have any users. + static inline MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline MDNode *getIfExists(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + static inline MDNode *getDistinct(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + + /// \brief Return a temporary MDNode + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static MDNodeFwdDecl *getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + + /// \brief Deallocate a node created by getTemporary. + /// + /// The node must not have any users. static void deleteTemporary(MDNode *N); - /// replaceOperandWith - Replace a specific operand. - void replaceOperandWith(unsigned i, Value *NewVal); + LLVMContext &getContext() const { return Context; } - /// getOperand - Return specified operand. - Value *getOperand(unsigned i) const LLVM_READONLY; + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); - /// getNumOperands - Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } + /// \brief Check if node is fully resolved. + bool isResolved() const; - /// isFunctionLocal - Return whether MDNode is local to a function. - bool isFunctionLocal() const { - return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + /// \brief Check if node is distinct. + /// + /// Distinct nodes are not uniqued, and will not be returned by \a + /// MDNode::get(). + bool isDistinct() const { + return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this); } - // getFunction - If this metadata is function-local and recursively has a - // function-local operand, return the first such operand's parent function. - // Otherwise, return null. getFunction() should not be used for performance- - // critical code because it recursively visits all the MDNode's operands. - const Function *getFunction() const; +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); - /// Profile - calculate a unique identifier for this MDNode to collapse - /// duplicates - void Profile(FoldingSetNodeID &ID) const; +public: + typedef const MDOperand *op_iterator; + typedef iterator_range<op_iterator> op_range; - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == MDNodeVal; + op_iterator op_begin() const { + return const_cast<MDNode *>(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast<MDNode *>(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind || + MD->getMetadataID() == MDLocationKind || + MD->getMetadataID() == MDNodeFwdDeclKind; } - /// Check whether MDNode is a vtable access. + /// \brief Check whether MDNode is a vtable access. bool isTBAAVtableAccess() const; - /// Methods for metadata merging. + /// \brief Methods for metadata merging. + static MDNode *concatenate(MDNode *A, MDNode *B); + static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); + static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); +}; + +/// \brief Uniquable metadata node. +/// +/// A uniquable metadata node. This contains the basic functionality +/// for implementing sub-types of \a MDNode that can be uniqued like +/// constants. +/// +/// There is limited support for RAUW at construction time. At +/// construction time, if any operands are an instance of \a +/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which +/// indicates an \a MDNodeFwdDecl in its path), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop +/// RAUW support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle when each \a MDNodeFwdDecl +/// has been removed. +class UniquableMDNode : public MDNode { + friend class ReplaceableMetadataImpl; + friend class MDNode; + friend class LLVMContextImpl; + + /// \brief Support RAUW as long as one of its arguments is replaceable. + /// + /// FIXME: Save memory by storing this in a pointer union with the + /// LLVMContext, and adding an LLVMContext reference to RMI. + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses; + +protected: + /// \brief Create a new node. + /// + /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW + /// will be dropped once all operands have been resolved (or if \a + /// resolveCycles() is called). + UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals, + bool AllowRAUW); + ~UniquableMDNode() {} + + void storeDistinctInContext(); + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind || + MD->getMetadataID() == MDLocationKind; + } + + /// \brief Check whether any operands are forward declarations. + /// + /// Returns \c true as long as any operands (or their operands, etc.) are \a + /// MDNodeFwdDecl. + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !ReplaceableUses; } + + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl. + void resolveCycles(); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + + void deleteAsSubclass(); + UniquableMDNode *uniquify(); + void eraseFromStore(); +}; + +/// \brief Tuple of metadata. +/// +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public UniquableMDNode { + friend class LLVMContextImpl; + friend class UniquableMDNode; + + MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW) + : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {} + ~MDTuple() { dropAllReferences(); } + + void setHash(unsigned Hash) { MDNodeSubclassData = Hash; } + void recalculateHash(); + + static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs, + bool ShouldCreate); + +public: + /// \brief Get the hash, if any. + unsigned getHash() const { return MDNodeSubclassData; } + + static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, /* ShouldCreate */ true); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, /* ShouldCreate */ false); + } + + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs); + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; + } + +private: + MDTuple *uniquifyImpl(); + void eraseFromStoreImpl(); +}; + +MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::get(Context, MDs); +} +MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::getDistinct(Context, MDs); +} + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public UniquableMDNode { + friend class LLVMContextImpl; + friend class UniquableMDNode; + + MDLocation(LLVMContext &C, unsigned Line, unsigned Column, + ArrayRef<Metadata *> MDs, bool AllowRAUW); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *constructHelper(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool AllowRAUW); + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool ShouldCreate); + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; + +public: + static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column, + Metadata *Scope, Metadata *InlinedAt = nullptr) { + return getImpl(Context, Line, Column, Scope, InlinedAt, + /* ShouldCreate */ true); + } + static MDLocation *getIfExists(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr) { + return getImpl(Context, Line, Column, Scope, InlinedAt, + /* ShouldCreate */ false); + } + static MDLocation *getDistinct(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr); + + unsigned getLine() const { return MDNodeSubclassData; } + unsigned getColumn() const { return SubclassData16; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } + private: - // destroy - Delete this node. Only when there are no uses. - void destroy(); + MDLocation *uniquifyImpl(); + void eraseFromStoreImpl(); +}; + +/// \brief Forward declaration of metadata. +/// +/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a +/// MDTuple, this class has full support for RAUW, is not owned, is not +/// uniqued, and is suitable for forward references. +class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { + friend class Metadata; + friend class ReplaceableMetadataImpl; + + MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals) + : MDNode(C, MDNodeFwdDeclKind, Vals) {} + +public: + ~MDNodeFwdDecl() { dropAllReferences(); } + + // MSVC doesn't see the alternative: "using MDNode::operator delete". + void operator delete(void *Mem) { MDNode::operator delete(Mem); } - bool isNotUniqued() const { - return (getSubclassDataFromValue() & NotUniquedBit) != 0; + static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return new (MDs.size()) MDNodeFwdDecl(Context, MDs); } - void setIsNotUniqued(); - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNodeFwdDeclKind; } + + using ReplaceableMetadataImpl::replaceAllUsesWith; }; //===----------------------------------------------------------------------===// -/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't -/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain -/// lists of MDNodes. +/// \brief A tuple of MDNodes. +/// +/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong +/// to modules, have names, and contain lists of MDNodes. +/// +/// TODO: Inherit from Metadata. class NamedMDNode : public ilist_node<NamedMDNode> { friend class SymbolTableListTraits<NamedMDNode, Module>; friend struct ilist_traits<NamedMDNode>; @@ -202,7 +924,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> { std::string Name; Module *Parent; - void *Operands; // SmallVector<TrackingVH<MDNode>, 4> + void *Operands; // SmallVector<TrackingMDRef, 4> void setParent(Module *M) { Parent = M; } @@ -245,46 +967,34 @@ class NamedMDNode : public ilist_node<NamedMDNode> { }; public: - /// eraseFromParent - Drop all references and remove the node from parent - /// module. + /// \brief Drop all references and remove the node from parent module. void eraseFromParent(); - /// dropAllReferences - Remove all uses and clear node vector. + /// \brief Remove all uses and clear node vector. void dropAllReferences(); - /// ~NamedMDNode - Destroy NamedMDNode. ~NamedMDNode(); - /// getParent - Get the module that holds this named metadata collection. + /// \brief Get the module that holds this named metadata collection. inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } - /// getOperand - Return specified operand. MDNode *getOperand(unsigned i) const; - - /// getNumOperands - Return the number of NamedMDNode operands. unsigned getNumOperands() const; - - /// addOperand - Add metadata operand. void addOperand(MDNode *M); - - /// getName - Return a constant reference to this named metadata's name. + void setOperand(unsigned I, MDNode *New); StringRef getName() const; - - /// print - Implement operator<< on NamedMDNode. void print(raw_ostream &ROS) const; - - /// dump() - Allow printing of NamedMDNodes from the debugger. void dump() const; // --------------------------------------------------------------------------- // Operand Iterator interface... // - typedef op_iterator_impl<MDNode*, MDNode> op_iterator; + typedef op_iterator_impl<MDNode *, MDNode> op_iterator; op_iterator op_begin() { return op_iterator(this, 0); } op_iterator op_end() { return op_iterator(this, getNumOperands()); } - typedef op_iterator_impl<const MDNode*, MDNode> const_op_iterator; + typedef op_iterator_impl<const MDNode *, MDNode> const_op_iterator; const_op_iterator op_begin() const { return const_op_iterator(this, 0); } const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); } diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h new file mode 100644 index 000000000000..541d9b3b1245 --- /dev/null +++ b/include/llvm/IR/MetadataTracking.h @@ -0,0 +1,99 @@ +//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Low-level functions to enable tracking of metadata that could RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATATRACKING_H +#define LLVM_IR_METADATATRACKING_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include <type_traits> + +namespace llvm { + +class Metadata; +class MetadataAsValue; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast<Metadata *>(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 26f62db9db53..b24023b05e4f 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -23,6 +23,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/DataTypes.h" #include <system_error> @@ -32,8 +33,6 @@ class GVMaterializer; class LLVMContext; class RandomNumberGenerator; class StructType; -template<typename T> struct DenseMapInfo; -template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap; template<> struct ilist_traits<Function> : public SymbolTableListTraits<Function, Module> { @@ -137,6 +136,11 @@ public: /// The Function constant iterator typedef FunctionListType::const_iterator const_iterator; + /// The Function reverse iterator. + typedef FunctionListType::reverse_iterator reverse_iterator; + /// The Function constant reverse iterator. + typedef FunctionListType::const_reverse_iterator const_reverse_iterator; + /// The Global Alias iterators. typedef AliasListType::iterator alias_iterator; /// The Global Alias constant iterator @@ -144,7 +148,7 @@ public: /// The named metadata iterators. typedef NamedMDListType::iterator named_metadata_iterator; - /// The named metadata constant interators. + /// The named metadata constant iterators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; /// This enumeration defines the supported behaviors of module flags. @@ -177,15 +181,23 @@ public: /// Appends the two values, which are required to be metadata /// nodes. However, duplicate entries in the second list are dropped /// during the append operation. - AppendUnique = 6 + AppendUnique = 6, + + // Markers: + ModFlagBehaviorFirstVal = Error, + ModFlagBehaviorLastVal = AppendUnique }; + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the + /// converted result in MFB. + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); + struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; - Value *Val; - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) - : Behavior(B), Key(K), Val(V) {} + Metadata *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} }; /// @} @@ -205,9 +217,8 @@ private: Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - // Allow lazy initialization in const method. - mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -237,6 +248,12 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// \brief Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). const std::string &getDataLayoutStr() const { return DataLayoutStr; } @@ -256,10 +273,16 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - /// Get the RandomNumberGenerator for this module. The RNG can be - /// seeded via -rng-seed=<uint64> and is salted with the ModuleID. - /// The returned RNG should not be shared across threads. - RandomNumberGenerator &getRNG() const; + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed=<uint64> and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + RandomNumberGenerator *createRNG(const Pass* P) const; /// @} /// @name Module Level Mutators @@ -313,6 +336,8 @@ public: /// name. StructType *getTypeByName(StringRef Name) const; + std::vector<StructType *> getIdentifiedStructTypes() const; + /// @} /// @name Function Accessors /// @{ @@ -339,11 +364,11 @@ public: /// function arguments, which makes it easier for clients to use. Constant *getOrInsertFunction(StringRef Name, AttributeSet AttributeList, - Type *RetTy, ...) END_WITH_NULL; + Type *RetTy, ...) LLVM_END_WITH_NULL; /// Same as above, but without the attributes. Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) - END_WITH_NULL; + LLVM_END_WITH_NULL; /// Look up the specified function in the module symbol table. If it does not /// exist, return null. @@ -357,8 +382,11 @@ public: /// does not exist, return null. If AllowInternal is set to true, this /// function will return types that have InternalLinkage. By default, these /// types are not returned. - const GlobalVariable *getGlobalVariable(StringRef Name, - bool AllowInternal = false) const { + GlobalVariable *getGlobalVariable(StringRef Name) const { + return getGlobalVariable(Name, false); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const { return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal); } @@ -424,7 +452,7 @@ public: /// Return the corresponding value if Key appears in module flags, otherwise /// return null. - Value *getModuleFlag(StringRef Key) const; + Metadata *getModuleFlag(StringRef Key) const; /// Returns the NamedMDNode in the module that represents module-level flags. /// This method returns null if there are no module-level flags. @@ -437,7 +465,8 @@ public: /// Add a module-level flag to the module-level flags metadata. It will create /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -456,9 +485,6 @@ public: /// Retrieves the GVMaterializer, if any, for this Module. GVMaterializer *getMaterializer() const { return Materializer.get(); } - /// True if the definition of GV has yet to be materializedfrom the - /// GVMaterializer. - bool isMaterializable(const GlobalValue *GV) const; /// Returns true if this GV was loaded from this Module's GVMaterializer and /// the GVMaterializer knows how to dematerialize the GV. bool isDematerializable(const GlobalValue *GV) const; @@ -466,10 +492,10 @@ public: /// Make sure the GlobalValue is fully read. If the module is corrupt, this /// returns true and fills in the optional string with information about the /// problem. If successful, this returns false. - bool Materialize(GlobalValue *GV, std::string *ErrInfo = nullptr); + std::error_code materialize(GlobalValue *GV); /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized - /// lazily. If !isDematerializable(), this method is a noop. + /// lazily. If !isDematerializable(), this method is a no-op. void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. @@ -478,7 +504,7 @@ public: /// Make sure all GlobalValues in this Module are fully read and clear the /// Materializer. If the module is corrupt, this DOES NOT clear the old /// Materializer. - std::error_code materializeAllPermanently(bool ReleaseBuffer = false); + std::error_code materializeAllPermanently(); /// @} /// @name Direct access to the globals list, functions list, and symbol table @@ -546,9 +572,20 @@ public: const_iterator begin() const { return FunctionList.begin(); } iterator end () { return FunctionList.end(); } const_iterator end () const { return FunctionList.end(); } + reverse_iterator rbegin() { return FunctionList.rbegin(); } + const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); } + reverse_iterator rend() { return FunctionList.rend(); } + const_reverse_iterator rend() const { return FunctionList.rend(); } size_t size() const { return FunctionList.size(); } bool empty() const { return FunctionList.empty(); } + iterator_range<iterator> functions() { + return iterator_range<iterator>(begin(), end()); + } + iterator_range<const_iterator> functions() const { + return iterator_range<const_iterator>(begin(), end()); + } + /// @} /// @name Alias Iteration /// @{ @@ -620,6 +657,15 @@ public: unsigned getDwarfVersion() const; /// @} +/// @name Utility functions for querying and setting PIC level +/// @{ + + /// \brief Returns the PIC level (small or large model) + PICLevel::Level getPICLevel() const; + + /// \brief Set the PIC level (small or large model) + void setPICLevel(PICLevel::Level PL); +/// @} }; /// An raw_ostream inserter for modules. diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 888cabffe378..0933f2170236 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -28,9 +28,8 @@ class GetElementPtrInst; class BinaryOperator; class ConstantExpr; -/// Operator - This is a utility class that provides an abstraction for the -/// common functionality between Instructions and ConstantExprs. -/// +/// This is a utility class that provides an abstraction for the common +/// functionality between Instructions and ConstantExprs. class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself @@ -46,17 +45,15 @@ protected: ~Operator(); public: - /// getOpcode - Return the opcode for this Instruction or ConstantExpr. - /// + /// Return the opcode for this Instruction or ConstantExpr. unsigned getOpcode() const { if (const Instruction *I = dyn_cast<Instruction>(this)) return I->getOpcode(); return cast<ConstantExpr>(this)->getOpcode(); } - /// getOpcode - If V is an Instruction or ConstantExpr, return its - /// opcode. Otherwise return UserOp1. - /// + /// If V is an Instruction or ConstantExpr, return its opcode. + /// Otherwise return UserOp1. static unsigned getOpcode(const Value *V) { if (const Instruction *I = dyn_cast<Instruction>(V)) return I->getOpcode(); @@ -72,10 +69,9 @@ public: } }; -/// OverflowingBinaryOperator - Utility class for integer arithmetic operators -/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv, -/// despite that operator having the potential for overflow. -/// +/// Utility class for integer arithmetic operators which may exhibit overflow - +/// Add, Sub, and Mul. It does not include SDiv, despite that operator having +/// the potential for overflow. class OverflowingBinaryOperator : public Operator { public: enum { @@ -96,13 +92,13 @@ private: } public: - /// hasNoUnsignedWrap - Test whether this operation is known to never + /// Test whether this operation is known to never /// undergo unsigned overflow, aka the nuw property. bool hasNoUnsignedWrap() const { return SubclassOptionalData & NoUnsignedWrap; } - /// hasNoSignedWrap - Test whether this operation is known to never + /// Test whether this operation is known to never /// undergo signed overflow, aka the nsw property. bool hasNoSignedWrap() const { return (SubclassOptionalData & NoSignedWrap) != 0; @@ -126,8 +122,8 @@ public: } }; -/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as -/// "exact", indicating that no bits are destroyed. +/// A udiv or sdiv instruction, which can be marked as "exact", +/// indicating that no bits are destroyed. class PossiblyExactOperator : public Operator { public: enum { @@ -142,8 +138,7 @@ private: } public: - /// isExact - Test whether this division is known to be exact, with - /// zero remainder. + /// Test whether this division is known to be exact, with zero remainder. bool isExact() const { return SubclassOptionalData & IsExact; } @@ -217,7 +212,7 @@ public: }; -/// FPMathOperator - Utility class for floating point operations which can have +/// Utility class for floating point operations which can have /// information about relaxed accuracy requirements attached to them. class FPMathOperator : public Operator { private: @@ -257,11 +252,18 @@ private: (B * FastMathFlags::AllowReciprocal); } - /// Convenience function for setting all the fast-math flags + /// Convenience function for setting multiple fast-math flags. + /// FMF is a mask of the bits to set. void setFastMathFlags(FastMathFlags FMF) { SubclassOptionalData |= FMF.Flags; } + /// Convenience function for copying all fast-math flags. + /// All values in FMF are transferred to this operator. + void copyFastMathFlags(FastMathFlags FMF) { + SubclassOptionalData = FMF.Flags; + } + public: /// Test whether this operation is permitted to be /// algebraically transformed, aka the 'A' fast-math property. @@ -312,8 +314,7 @@ public: }; -/// ConcreteOperator - A helper template for defining operators for individual -/// opcodes. +/// A helper template for defining operators for individual opcodes. template<typename SuperClass, unsigned Opc> class ConcreteOperator : public SuperClass { public: @@ -357,6 +358,8 @@ class LShrOperator }; +class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; + class GEPOperator : public ConcreteOperator<Operator, Instruction::GetElementPtr> { @@ -372,8 +375,7 @@ class GEPOperator } public: - /// isInBounds - Test whether this is an inbounds GEP, as defined - /// by LangRef.html. + /// Test whether this is an inbounds GEP, as defined by LangRef.html. bool isInBounds() const { return SubclassOptionalData & IsInBounds; } @@ -393,16 +395,14 @@ public: return 0U; // get index for modifying correct operand } - /// getPointerOperandType - Method to return the pointer operand as a - /// PointerType. + /// Method to return the pointer operand as a PointerType. Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - /// getPointerAddressSpace - Method to return the address space of the - /// pointer operand. + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast<PointerType>(getPointerOperandType())->getAddressSpace(); + return getPointerOperandType()->getPointerAddressSpace(); } unsigned getNumIndices() const { // Note: always non-negative @@ -413,8 +413,8 @@ public: return getNumOperands() > 1; } - /// hasAllZeroIndices - Return true if all of the indices of this GEP are - /// zeros. If so, the result pointer and the first operand have the same + /// Return true if all of the indices of this GEP are zeros. + /// If so, the result pointer and the first operand have the same /// value, just potentially different types. bool hasAllZeroIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { @@ -426,8 +426,8 @@ public: return true; } - /// hasAllConstantIndices - Return true if all of the indices of this GEP are - /// constant integers. If so, the result pointer and the first operand have + /// Return true if all of the indices of this GEP are constant integers. + /// If so, the result pointer and the first operand have /// a constant offset between them. bool hasAllConstantIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { @@ -493,14 +493,12 @@ public: return 0U; // get index for modifying correct operand } - /// getPointerOperandType - Method to return the pointer operand as a - /// PointerType. + /// Method to return the pointer operand as a PointerType. Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - /// getPointerAddressSpace - Method to return the address space of the - /// pointer operand. + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { return cast<PointerType>(getPointerOperandType())->getAddressSpace(); } diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index cc2a80b9ff7d..262576849264 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -35,14 +35,17 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_PASS_MANAGER_H -#define LLVM_IR_PASS_MANAGER_H +#ifndef LLVM_IR_PASSMANAGER_H +#define LLVM_IR_PASSMANAGER_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManagerInternal.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/type_traits.h" #include <list> #include <memory> @@ -91,9 +94,12 @@ public: } /// \brief Mark a particular pass as preserved, adding it to the set. - template <typename PassT> void preserve() { + template <typename PassT> void preserve() { preserve(PassT::ID()); } + + /// \brief Mark an abstract PassID as preserved, adding it to the set. + void preserve(void *PassID) { if (!areAllPreserved()) - PreservedPassIDs.insert(PassT::ID()); + PreservedPassIDs.insert(PassID); } /// \brief Intersect this set with another in place. @@ -107,11 +113,9 @@ public: PreservedPassIDs = Arg.PreservedPassIDs; return; } - for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(), - E = PreservedPassIDs.end(); - I != E; ++I) - if (!Arg.PreservedPassIDs.count(*I)) - PreservedPassIDs.erase(*I); + for (void *P : PreservedPassIDs) + if (!Arg.PreservedPassIDs.count(P)) + PreservedPassIDs.erase(P); } /// \brief Intersect this set with a temporary other set in place. @@ -125,11 +129,9 @@ public: PreservedPassIDs = std::move(Arg.PreservedPassIDs); return; } - for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(), - E = PreservedPassIDs.end(); - I != E; ++I) - if (!Arg.PreservedPassIDs.count(*I)) - PreservedPassIDs.erase(*I); + for (void *P : PreservedPassIDs) + if (!Arg.PreservedPassIDs.count(P)) + PreservedPassIDs.erase(P); } /// \brief Query whether a pass is marked as preserved by this set. @@ -144,408 +146,115 @@ public: PreservedPassIDs.count(PassID); } + /// \brief Test whether all passes are preserved. + /// + /// This is used primarily to optimize for the case of no changes which will + /// common in many scenarios. + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + private: // Note that this must not be -1 or -2 as those are already used by the // SmallPtrSet. static const uintptr_t AllPassesID = (intptr_t)(-3); - bool areAllPreserved() const { - return PreservedPassIDs.count((void *)AllPassesID); - } - SmallPtrSet<void *, 2> PreservedPassIDs; }; -/// \brief Implementation details of the pass manager interfaces. -namespace detail { - -/// \brief Template for the abstract base class used to dispatch -/// polymorphically over pass objects. -template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() {} - - /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManagerT. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT, - typename ResultT> -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)> - struct Checker; - - template <typename T> static SmallType f(Checker<T, &T::run> *); - template <typename T> static BigType f(...); +// Forward declare the analysis manager template. +template <typename IRUnitT> class AnalysisManager; -public: - enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief A template wrapper used to implement the polymorphic API. +/// \brief Manages a sequence of passes over units of IR. /// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT. It requires the pass to be a copyable object. When the -/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT, - bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< - IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT> -struct PassModel<IRUnitT, AnalysisManagerT, PassT, true> - : PassConcept<IRUnitT, AnalysisManagerT> { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR, AM); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT> -struct PassModel<IRUnitT, AnalysisManagerT, PassT, false> - : PassConcept<IRUnitT, AnalysisManagerT> { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Abstract concept of an analysis result. +/// A pass manager contains a sequence of passes to run over units of IR. It is +/// itself a valid pass over that unit of IR, and when over some given IR will +/// run each pass in sequence. This is the primary and most basic building +/// block of a pass pipeline. /// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template <typename IRUnitT> struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// This method also receives a set of preserved analyses which can be used - /// to avoid invalidation because the pass which changed the underlying IR - /// took care to update or preserve the analysis result in some way. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)> - struct Checker; - - template <typename T> static SmallType f(Checker<T, &T::invalidate> *); - template <typename T> static BigType f(...); - +/// If it is run with an \c AnalysisManager<IRUnitT> argument, it will propagate +/// that analysis manager to each pass it runs, as well as calling the analysis +/// manager's invalidation routine with the PreservedAnalyses of each pass it +/// runs. +template <typename IRUnitT> class PassManager { public: - enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template <typename IRUnitT, typename PassT, typename ResultT, - bool HasInvalidateHandler = - ResultHasInvalidateMethod<IRUnitT, ResultT>::Value> -struct AnalysisResultModel; - -/// \brief Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template <typename IRUnitT, typename PassT, typename ResultT> -struct AnalysisResultModel<IRUnitT, PassT, ResultT, false> - : AnalysisResultConcept<IRUnitT> { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { - return !PA.preserved(PassT::ID()); - } - - ResultT Result; -}; - -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template <typename IRUnitT, typename PassT, typename ResultT> -struct AnalysisResultModel<IRUnitT, PassT, ResultT, true> - : AnalysisResultConcept<IRUnitT> { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { - return Result.invalidate(IR, PA); - } - - ResultT Result; -}; - -/// \brief Abstract concept of an analysis pass. -/// -/// This concept is parameterized over the IR unit that it can run over and -/// produce an analysis result. -template <typename IRUnitT, typename AnalysisManagerT> -struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>> - run(IRUnitT IR, AnalysisManagerT *AM) = 0; -}; - -/// \brief Wrapper to model the analysis pass concept. -/// -/// Can wrap any type which implements a suitable \c run method. The method -/// must accept the IRUnitT as an argument and produce an object which can be -/// wrapped in a \c AnalysisResultModel. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT, - bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< - IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT> -struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true> - : AnalysisPassConcept<IRUnitT, AnalysisManagerT> { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { + Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr<AnalysisResultConcept<IRUnitT>> - run(IRUnitT IR, AnalysisManagerT *AM) override { - return make_unique<ResultModelT>(Pass.run(IR, AM)); - } + /// \brief Run all of the passes in this manager over the IR. + PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM = nullptr) { + PreservedAnalyses PA = PreservedAnalyses::all(); - PassT Pass; -}; + if (DebugLogging) + dbgs() << "Starting pass manager run.\n"; -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template <typename IRUnitT, typename AnalysisManagerT, typename PassT> -struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false> - : AnalysisPassConcept<IRUnitT, AnalysisManagerT> { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + if (DebugLogging) + dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> - ResultModelT; + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr<AnalysisResultConcept<IRUnitT>> - run(IRUnitT IR, AnalysisManagerT *) override { - return make_unique<ResultModelT>(Pass.run(IR)); - } + // If we have an active analysis manager at this level we want to ensure + // we update it as each pass runs and potentially invalidates analyses. + // We also update the preserved set of analyses based on what analyses we + // have already handled the invalidation for here and don't need to + // invalidate when finished. + if (AM) + PassPA = AM->invalidate(IR, std::move(PassPA)); - PassT Pass; -}; + // Finally, we intersect the final preserved analyses to compute the + // aggregate preserved set for this pass manager. + PA.intersect(std::move(PassPA)); -} // End namespace detail + // FIXME: Historically, the pass managers all called the LLVM context's + // yield function here. We don't have a generic way to acquire the + // context and it isn't yet clear what the right pattern is for yielding + // in the new pass manager so it is currently omitted. + //IR.getContext().yield(); + } -class ModuleAnalysisManager; + if (DebugLogging) + dbgs() << "Finished pass manager run.\n"; -class ModulePassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModulePassManager() {} - ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - ModulePassManager &operator=(ModulePassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; + return PA; } - /// \brief Run all of the module passes in this module pass manager over - /// a module. - /// - /// This method should only be called for a single module as there is the - /// expectation that the lifetime of a pass is bounded to that of a module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); - - template <typename ModulePassT> void addPass(ModulePassT Pass) { - Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass))); + template <typename PassT> void addPass(PassT Pass) { + typedef detail::PassModel<IRUnitT, PassT> PassModelT; + Passes.emplace_back(new PassModelT(std::move(Pass))); } - static StringRef name() { return "ModulePassManager"; } + static StringRef name() { return "PassManager"; } private: - // Pull in the concept type and model template specialized for modules. - typedef detail::PassConcept<Module *, ModuleAnalysisManager> - ModulePassConcept; - template <typename PassT> - struct ModulePassModel - : detail::PassModel<Module *, ModuleAnalysisManager, PassT> { - ModulePassModel(PassT Pass) - : detail::PassModel<Module *, ModuleAnalysisManager, PassT>( - std::move(Pass)) {} - }; + typedef detail::PassConcept<IRUnitT> PassConceptT; - ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; - ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + PassManager(const PassManager &) LLVM_DELETED_FUNCTION; + PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION; - std::vector<std::unique_ptr<ModulePassConcept>> Passes; -}; - -class FunctionAnalysisManager; + std::vector<std::unique_ptr<PassConceptT>> Passes; -class FunctionPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionPassManager() {} - FunctionPassManager(FunctionPassManager &&Arg) - : Passes(std::move(Arg.Passes)) {} - FunctionPassManager &operator=(FunctionPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - template <typename FunctionPassT> void addPass(FunctionPassT Pass) { - Passes.emplace_back(new FunctionPassModel<FunctionPassT>(std::move(Pass))); - } - - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); - - static StringRef name() { return "FunctionPassManager"; } - -private: - // Pull in the concept type and model template specialized for functions. - typedef detail::PassConcept<Function *, FunctionAnalysisManager> - FunctionPassConcept; - template <typename PassT> - struct FunctionPassModel - : detail::PassModel<Function *, FunctionAnalysisManager, PassT> { - FunctionPassModel(PassT Pass) - : detail::PassModel<Function *, FunctionAnalysisManager, PassT>( - std::move(Pass)) {} - }; + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; +}; - FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - FunctionPassManager & - operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; +/// \brief Convenience typedef for a pass manager over modules. +typedef PassManager<Module> ModulePassManager; - std::vector<std::unique_ptr<FunctionPassConcept>> Passes; -}; +/// \brief Convenience typedef for a pass manager over functions. +typedef PassManager<Function> FunctionPassManager; namespace detail { @@ -560,6 +269,12 @@ namespace detail { /// - invalidateImpl /// /// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase { DerivedT *derived_this() { return static_cast<DerivedT *>(this); } const DerivedT *derived_this() const { @@ -572,7 +287,7 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase { protected: typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; - typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT; + typedef detail::AnalysisPassConcept<IRUnitT> PassConceptT; // FIXME: Provide template aliases for the models when we're using C++11 in // a mode supporting them. @@ -592,7 +307,7 @@ public: /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template <typename PassT> typename PassT::Result &getResult(IRUnitT IR) { + template <typename PassT> typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -609,7 +324,7 @@ public: /// /// \returns null if there is no cached result. template <typename PassT> - typename PassT::Result *getCachedResult(IRUnitT IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -631,25 +346,28 @@ public: template <typename PassT> void registerPass(PassT Pass) { assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT; + typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT; AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass))); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. - template <typename PassT> void invalidate(Module *M) { + template <typename PassT> void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { - derived_this()->invalidateImpl(IR, PA); + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); } protected: @@ -679,108 +397,153 @@ private: } // End namespace detail -/// \brief A module analysis pass manager with lazy running and caching of +/// \brief A generic analysis pass manager with lazy running and caching of /// results. -class ModuleAnalysisManager - : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> { - friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>; - typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManager() {} - ModuleAnalysisManager(ModuleAnalysisManager &&Arg) - : BaseT(std::move(static_cast<BaseT &>(Arg))), - ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} - ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); - return *this; - } - -private: - ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - ModuleAnalysisManager & - operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a module pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Module *M); - - /// \brief Get a cached module pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; - - /// \brief Invalidate a module pass result. - void invalidateImpl(void *PassID, Module *M); - - /// \brief Invalidate results across a module. - void invalidateImpl(Module *M, const PreservedAnalyses &PA); - - /// \brief Map type from module analysis pass ID to pass result concept - /// pointer. - typedef DenseMap<void *, - std::unique_ptr<detail::AnalysisResultConcept<Module *>>> - ModuleAnalysisResultMapT; - - /// \brief Cache of computed module analysis results for this module. - ModuleAnalysisResultMapT ModuleAnalysisResults; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class FunctionAnalysisManager - : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> { - friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>; - typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> - BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +template <typename IRUnitT> +class AnalysisManager + : public detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> { + friend class detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT>; + typedef detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManager() {} - FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))), - FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} - FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } - /// \brief Clear the function analysis result cache. + /// \brief Clear the analysis result cache. /// - /// This routine allows cleaning up when the set of functions itself has + /// This routine allows cleaning up when the set of IR units itself has /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } private: - FunctionAnalysisManager(const FunctionAnalysisManager &) - LLVM_DELETED_FUNCTION; - FunctionAnalysisManager & - operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION; + + /// \brief Get an analysis result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( + std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(PassID); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; + ResultList.emplace_back(PassID, P.run(IR, this)); + RI->second = std::prev(ResultList.end()); + } - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Function *F); + return *RI->second->second; + } - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; + /// \brief Get a cached analysis result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; + } /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + void invalidateImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + if (RI == AnalysisResults.end()) + return; + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + AnalysisResultLists[&IR].erase(RI->second); + AnalysisResults.erase(RI); + } /// \brief Invalidate the results for a function.. - void invalidateImpl(Function *F, const PreservedAnalyses &PA); + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return std::move(PA); + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " + << IR.getName() << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector<void *, 8> InvalidatedPassIDs; + AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + void *PassID = I->first; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->second->invalidate(IR, PA)) { + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(PassID); + } + while (!InvalidatedPassIDs.empty()) + AnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); + if (ResultsList.empty()) + AnalysisResultLists.erase(&IR); + + return std::move(PA); + } /// \brief List of function analysis pass IDs and associated concept pointers. /// @@ -788,30 +551,37 @@ private: /// erases. Provides both the pass ID and concept pointer such that it is /// half of a bijection and provides storage for the actual result concept. typedef std::list<std::pair< - void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>> - FunctionAnalysisResultListT; + void *, std::unique_ptr<detail::AnalysisResultConcept<IRUnitT>>>> + AnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap<Function *, FunctionAnalysisResultListT> - FunctionAnalysisResultListMapT; + typedef DenseMap<IRUnitT *, AnalysisResultListT> AnalysisResultListMapT; /// \brief Map from function to a list of function analysis results. /// /// Provides linear time removal of all analysis results for a function and /// the ultimate storage for a particular cached analysis result. - FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + AnalysisResultListMapT AnalysisResultLists; /// \brief Map type from a pair of analysis ID and function pointer to an /// iterator into a particular result list. - typedef DenseMap<std::pair<void *, Function *>, - FunctionAnalysisResultListT::iterator> - FunctionAnalysisResultMapT; + typedef DenseMap<std::pair<void *, IRUnitT *>, + typename AnalysisResultListT::iterator> AnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. - FunctionAnalysisResultMapT FunctionAnalysisResults; + AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; +/// \brief Convenience typedef for the Module analysis manager. +typedef AnalysisManager<Module> ModuleAnalysisManager; + +/// \brief Convenience typedef for the Function analysis manager. +typedef AnalysisManager<Function> FunctionAnalysisManager; + /// \brief A module analysis which acts as a proxy for a function analysis /// manager. /// @@ -826,6 +596,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -850,7 +622,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -888,7 +660,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -924,7 +696,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -932,6 +704,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -950,7 +724,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(Function *) { return Result(*MAM); } + Result run(Function &) { return Result(*MAM); } private: static char PassID; @@ -966,6 +740,20 @@ private: /// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. +/// +/// Function passes run within this adaptor can rely on having exclusive access +/// to the function they are run over. They should not read or modify any other +/// functions! Other threads or systems may be manipulating other functions in +/// the module, and so their state should never be relied on. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. +/// +/// Function passes can also read the module containing the function, but they +/// should not modify that module outside of the use lists of various globals. +/// For example, a function pass is not permitted to add functions to the +/// module. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. template <typename FunctionPassT> class ModuleToFunctionPassAdaptor { public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) @@ -976,7 +764,8 @@ public: : Pass(Arg.Pass) {} ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + friend void swap(ModuleToFunctionPassAdaptor &LHS, + ModuleToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -986,21 +775,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(I, FAM); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + PreservedAnalyses PassPA = Pass.run(*I, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. + // directly handle the function analysis manager's invalidation here and + // update our preserved set to reflect that these have already been + // handled. if (FAM) - FAM->invalidate(I, PassPA); + PassPA = FAM->invalidate(*I, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -1029,6 +820,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); } +/// \brief A template utility pass to force an analysis result to be available. +/// +/// This is a no-op pass which simply forces a specific analysis pass's result +/// to be available when it is run. +template <typename AnalysisT> struct RequireAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template <typename IRUnitT> + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) { + if (AM) + (void)AM->template getResult<AnalysisT>(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "RequireAnalysisPass"; } +}; + +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template <typename AnalysisT> struct InvalidateAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template <typename IRUnitT> + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate<AnalysisT>(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "InvalidateAnalysisPass"; } +}; + +/// \brief A utility pass that does nothing but preserves no analyses. +/// +/// As a consequence fo not preserving any analyses, this pass will force all +/// analysis passes to be re-run to produce fresh results if any are needed. +struct InvalidateAllAnalysesPass { + /// \brief Run this pass over some unit of IR. + template <typename IRUnitT> PreservedAnalyses run(IRUnitT &Arg) { + return PreservedAnalyses::none(); + } + + static StringRef name() { return "InvalidateAllAnalysesPass"; } +}; + } #endif diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h new file mode 100644 index 000000000000..297f5f4e07f4 --- /dev/null +++ b/include/llvm/IR/PassManagerInternal.h @@ -0,0 +1,349 @@ +//===- PassManager internal APIs and implementation details -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides internal APIs and implementation details used by the +/// pass management interfaces exposed in PassManager.h. To understand more +/// context of why these particular interfaces are needed, see that header +/// file. None of these APIs should be used elsewhere. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSMANAGERINTERNAL_H +#define LLVM_IR_PASSMANAGERINTERNAL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template <typename IRUnitT> struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + + /// \brief The polymorphic API which runs the pass over a given IR entity. + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManager<IRUnitT>. +template <typename IRUnitT, typename PassT, typename ResultT> +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)> + struct Checker; + + template <typename T> static SmallType f(Checker<T, &T::run> *); + template <typename T> static BigType f(...); + +public: + enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it +/// along. +template <typename IRUnitT, typename PassT, + typename PreservedAnalysesT = PreservedAnalyses, + bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< + IRUnitT, PassT, PreservedAnalysesT>::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template <typename IRUnitT, typename PassT, typename PreservedAnalysesT> +struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true> + : PassConcept<IRUnitT> { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template <typename IRUnitT, typename PassT, typename PreservedAnalysesT> +struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false> + : PassConcept<IRUnitT> { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Abstract concept of an analysis result. +/// +/// This concept is parameterized over the IR unit that this result pertains +/// to. +template <typename IRUnitT> struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)> + struct Checker; + + template <typename T> static SmallType f(Checker<T, &T::invalidate> *); + template <typename T> static BigType f(...); + +public: + enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template <typename IRUnitT, typename PassT, typename ResultT, + typename PreservedAnalysesT = PreservedAnalyses, + bool HasInvalidateHandler = + ResultHasInvalidateMethod<IRUnitT, ResultT>::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template <typename IRUnitT, typename PassT, typename ResultT, + typename PreservedAnalysesT> +struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false> + : AnalysisResultConcept<IRUnitT> { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template <typename IRUnitT, typename PassT, typename ResultT, + typename PreservedAnalysesT> +struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true> + : AnalysisResultConcept<IRUnitT> { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { + return Result.invalidate(IR, PA); + } + + ResultT Result; +}; + +/// \brief Abstract concept of an analysis pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// produce an analysis result. +template <typename IRUnitT> struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief Wrapper to model the analysis pass concept. +/// +/// Can wrap any type which implements a suitable \c run method. The method +/// must accept the IRUnitT as an argument and produce an object which can be +/// wrapped in a \c AnalysisResultModel. +template <typename IRUnitT, typename PassT, + bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< + IRUnitT, PassT, typename PassT::Result>::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template <typename IRUnitT, typename PassT> +struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override { + return make_unique<ResultModelT>(Pass.run(IR, AM)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template <typename IRUnitT, typename PassT> +struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override { + return make_unique<ResultModelT>(Pass.run(IR)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +} // End namespace detail +} + +#endif diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 2efb29489473..f94e10576893 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -32,61 +32,64 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Operator.h" namespace llvm { namespace PatternMatch { -template<typename Val, typename Pattern> -bool match(Val *V, const Pattern &P) { - return const_cast<Pattern&>(P).match(V); +template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) { + return const_cast<Pattern &>(P).match(V); } - -template<typename SubPattern_t> -struct OneUse_match { +template <typename SubPattern_t> struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; -template<typename T> -inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; } - +template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) { + return SubPattern; +} -template<typename Class> -struct class_match { - template<typename ITy> - bool match(ITy *V) { return isa<Class>(V); } +template <typename Class> struct class_match { + template <typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; -/// m_Value() - Match an arbitrary value and ignore it. +/// \brief Match an arbitrary value and ignore it. inline class_match<Value> m_Value() { return class_match<Value>(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. + +/// \brief Match an arbitrary binary operation and ignore it. +inline class_match<BinaryOperator> m_BinOp() { + return class_match<BinaryOperator>(); +} + +/// \brief Matches any compare instruction and ignore it. +inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); } + +/// \brief Match an arbitrary ConstantInt and ignore it. inline class_match<ConstantInt> m_ConstantInt() { return class_match<ConstantInt>(); } -/// m_Undef() - Match an arbitrary undef constant. + +/// \brief Match an arbitrary undef constant. inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } +/// \brief Match an arbitrary Constant and ignore it. inline class_match<Constant> m_Constant() { return class_match<Constant>(); } /// Matching combinators -template<typename LTy, typename RTy> -struct match_combine_or { +template <typename LTy, typename RTy> struct match_combine_or { LTy L; RTy R; - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template<typename ITy> - bool match(ITy *V) { + template <typename ITy> bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) @@ -95,15 +98,13 @@ struct match_combine_or { } }; -template<typename LTy, typename RTy> -struct match_combine_and { +template <typename LTy, typename RTy> struct match_combine_and { LTy L; RTy R; - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template<typename ITy> - bool match(ITy *V) { + template <typename ITy> bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; @@ -112,46 +113,44 @@ struct match_combine_and { }; /// Combine two pattern matchers matching L || R -template<typename LTy, typename RTy> +template <typename LTy, typename RTy> inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or<LTy, RTy>(L, R); } /// Combine two pattern matchers matching L && R -template<typename LTy, typename RTy> +template <typename LTy, typename RTy> inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and<LTy, RTy>(L, R); } struct match_zero { - template<typename ITy> - bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) + template <typename ITy> bool match(ITy *V) { + if (const auto *C = dyn_cast<Constant>(V)) return C->isNullValue(); return false; } }; -/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { - template<typename ITy> - bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) + template <typename ITy> bool match(ITy *V) { + if (const auto *C = dyn_cast<Constant>(V)) return C->isNegativeZeroValue(); return false; } }; -/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() { @@ -161,16 +160,14 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() { struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} - template<typename ITy> - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + template <typename ITy> bool match(ITy *V) { + if (auto *CI = dyn_cast<ConstantInt>(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(C->getSplatValue())) { + if (const auto *C = dyn_cast<Constant>(V)) + if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) { Res = &CI->getValue(); return true; } @@ -178,16 +175,13 @@ struct apint_match { } }; -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - -template<int64_t Val> -struct constantint_match { - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { +template <int64_t Val> struct constantint_match { + template <typename ITy> bool match(ITy *V) { + if (const auto *CI = dyn_cast<ConstantInt>(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast<uint64_t>(Val); @@ -200,45 +194,39 @@ struct constantint_match { } }; -/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value. -template<int64_t Val> -inline constantint_match<Val> m_ConstantInt() { +/// \brief Match a ConstantInt with a specific value. +template <int64_t Val> inline constantint_match<Val> m_ConstantInt() { return constantint_match<Val>(); } -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template<typename Predicate> -struct cst_pred_ty : public Predicate { - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate. +template <typename Predicate> struct cst_pred_ty : public Predicate { + template <typename ITy> bool match(ITy *V) { + if (const auto *CI = dyn_cast<ConstantInt>(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (const ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + if (const auto *C = dyn_cast<Constant>(V)) + if (const auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template<typename Predicate> -struct api_pred_ty : public Predicate { +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APInt. +template <typename Predicate> struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + template <typename ITy> bool match(ITy *V) { + if (const auto *CI = dyn_cast<ConstantInt>(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + if (const auto *C = dyn_cast<Constant>(V)) + if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; @@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate { } }; - struct is_one { bool isValue(const APInt &C) { return C == 1; } }; -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +/// \brief Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } @@ -261,34 +248,43 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} +/// \brief Match an integer or vector with all bits set to true. +inline cst_pred_ty<is_all_ones> m_AllOnes() { + return cst_pred_ty<is_all_ones>(); +} inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } struct is_sign_bit { bool isValue(const APInt &C) { return C.isSignBit(); } }; -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();} +/// \brief Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty<is_sign_bit> m_SignBit() { + return cst_pred_ty<is_sign_bit>(); +} inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; } struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; -/// m_Power2() - Match an integer or vector power of 2. +/// \brief Match an integer or vector power of 2. inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } -template<typename Class> -struct bind_ty { +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { return cst_pred_ty<is_maxsignedvalue>(); } +inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { return V; } + +template <typename Class> struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} - template<typename ITy> - bool match(ITy *V) { - if (Class *CV = dyn_cast<Class>(V)) { + template <typename ITy> bool match(ITy *V) { + if (auto *CV = dyn_cast<Class>(V)) { VR = CV; return true; } @@ -296,64 +292,62 @@ struct bind_ty { } }; -/// m_Value - Match a value, capturing it if we match. +/// \brief Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +/// \brief Match a binary operator, capturing it if we match. +inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } + +/// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } -/// m_Constant - Match a Constant, capturing the value if we match. +/// \brief Match a Constant, capturing the value if we match. inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +/// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; } -/// specificval_ty - Match a specified Value*. +/// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} - template<typename ITy> - bool match(ITy *V) { - return V == Val; - } + template <typename ITy> bool match(ITy *V) { return V == Val; } }; -/// m_Specific - Match if we have a specific specified value. +/// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// Match a specified floating point value or vector of all elements of that -/// value. +/// \brief Match a specified floating point value or vector of all elements of +/// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} - template<typename ITy> - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) + template <typename ITy> bool match(ITy *V) { + if (const auto *CFP = dyn_cast<ConstantFP>(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) + if (const auto *C = dyn_cast<Constant>(V)) + if (auto *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; -/// Match a specific floating point value or vector with all elements equal to -/// the value. +/// \brief Match a specific floating point value or vector with all elements +/// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// Match a float 1.0 or vector with all elements equal to 1.0. +/// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - template<typename ITy> - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast<ConstantInt>(V)) + template <typename ITy> bool match(ITy *V) { + if (const auto *CV = dyn_cast<ConstantInt>(V)) if (CV->getBitWidth() <= 64) { VR = CV->getZExtValue(); return true; @@ -362,152 +356,196 @@ struct bind_const_intval_ty { } }; -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. +/// \brief Match a specified integer value or vector of all elements of that +// value. +struct specific_intval { + uint64_t Val; + specific_intval(uint64_t V) : Val(V) {} + + template <typename ITy> bool match(ITy *V) { + const auto *CI = dyn_cast<ConstantInt>(V); + if (!CI && V->getType()->isVectorTy()) + if (const auto *C = dyn_cast<Constant>(V)) + CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()); + + if (CI && CI->getBitWidth() <= 64) + return CI->getZExtValue() == Val; + + return false; + } +}; + +/// \brief Match a specific integer value or vector with all elements equal to +/// the value. +inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } + +/// \brief Match a ConstantInt and bind to its value. This does not match +/// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } //===----------------------------------------------------------------------===// +// Matcher for any binary operator. +// +template <typename LHS_t, typename RHS_t> struct AnyBinaryOp_match { + LHS_t L; + RHS_t R; + + AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template <typename OpTy> bool match(OpTy *V) { + if (auto *I = dyn_cast<BinaryOperator>(V)) + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + return false; + } +}; + +template <typename LHS, typename RHS> +inline AnyBinaryOp_match<LHS, RHS> m_BinOp(const LHS &L, const RHS &R) { + return AnyBinaryOp_match<LHS, RHS>(L, R); +} + +//===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template<typename LHS_t, typename RHS_t, unsigned Opcode> +template <typename LHS_t, typename RHS_t, unsigned Opcode> struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast<BinaryOperator>(V); + auto *I = cast<BinaryOperator>(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + if (auto *CE = dyn_cast<ConstantExpr>(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Add> -m_Add(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FAdd> -m_FAdd(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Sub> -m_Sub(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FSub> -m_FSub(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Mul> -m_Mul(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FMul> -m_FMul(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::UDiv> -m_UDiv(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SDiv> -m_SDiv(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FDiv> -m_FDiv(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::URem> -m_URem(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SRem> -m_SRem(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FRem> -m_FRem(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::And> -m_And(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Or> -m_Or(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Xor> -m_Xor(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Shl> -m_Shl(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::LShr> -m_LShr(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); } -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::AShr> -m_AShr(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, + const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); } -template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0> +template <typename LHS_t, typename RHS_t, unsigned Opcode, + unsigned WrapFlags = 0> struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) + : L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { - if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(V)) { + template <typename OpTy> bool match(OpTy *V) { + if (auto *Op = dyn_cast<OverflowingBinaryOperator>(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && @@ -591,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // -template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> +template <typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> struct BinOp2_match { LHS_t L; RHS_t R; BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opc1 || V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast<BinaryOperator>(V); + auto *I = cast<BinaryOperator>(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + if (auto *CE = dyn_cast<ConstantExpr>(V)) return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -/// m_Shr - Matches LShr or AShr. -template<typename LHS, typename RHS> +/// \brief Matches LShr or AShr. +template <typename LHS, typename RHS> inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr> m_Shr(const LHS &L, const RHS &R) { return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R); } -/// m_LogicalShift - Matches LShr or Shl. -template<typename LHS, typename RHS> +/// \brief Matches LShr or Shl. +template <typename LHS, typename RHS> inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl> m_LogicalShift(const LHS &L, const RHS &R) { return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R); } -/// m_IDiv - Matches UDiv and SDiv. -template<typename LHS, typename RHS> +/// \brief Matches UDiv and SDiv. +template <typename LHS, typename RHS> inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv> m_IDiv(const LHS &L, const RHS &R) { return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R); @@ -636,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // -template<typename SubPattern_t> -struct Exact_match { +template <typename SubPattern_t> struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { if (PossiblyExactOperator *PEO = dyn_cast<PossiblyExactOperator>(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; -template<typename T> -inline Exact_match<T> m_Exact(const T &SubPattern) { return SubPattern; } +template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) { + return SubPattern; +} //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // -template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy> +template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy> struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} + : Predicate(Pred), L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { if (Class *I = dyn_cast<Class>(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); @@ -677,123 +712,114 @@ struct CmpClass_match { } }; -template<typename LHS, typename RHS> +template <typename LHS, typename RHS> +inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate> +m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R); +} + +template <typename LHS, typename RHS> inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate> m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match<LHS, RHS, - ICmpInst, ICmpInst::Predicate>(Pred, L, R); + return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R); } -template<typename LHS, typename RHS> +template <typename LHS, typename RHS> inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate> m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match<LHS, RHS, - FCmpInst, FCmpInst::Predicate>(Pred, L, R); + return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // -template<typename Cond_t, typename LHS_t, typename RHS_t> +template <typename Cond_t, typename LHS_t, typename RHS_t> struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast<SelectInst>(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && + template <typename OpTy> bool match(OpTy *V) { + if (auto *I = dyn_cast<SelectInst>(V)) + return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; -template<typename Cond, typename LHS, typename RHS> -inline SelectClass_match<Cond, LHS, RHS> -m_Select(const Cond &C, const LHS &L, const RHS &R) { +template <typename Cond, typename LHS, typename RHS> +inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L, + const RHS &R) { return SelectClass_match<Cond, LHS, RHS>(C, L, R); } -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template<int64_t L, int64_t R, typename Cond> -inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> > +/// \brief This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template <int64_t L, int64_t R, typename Cond> +inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R>> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>()); } - //===----------------------------------------------------------------------===// // Matchers for CastInst classes // -template<typename Op_t, unsigned Opcode> -struct CastClass_match { +template <typename Op_t, unsigned Opcode> struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *O = dyn_cast<Operator>(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; -/// m_BitCast -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::BitCast> -m_BitCast(const OpTy &Op) { +/// \brief Matches BitCast. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) { return CastClass_match<OpTy, Instruction::BitCast>(Op); } -/// m_PtrToInt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::PtrToInt> -m_PtrToInt(const OpTy &Op) { +/// \brief Matches PtrToInt. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::PtrToInt>(Op); } -/// m_Trunc -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::Trunc> -m_Trunc(const OpTy &Op) { +/// \brief Matches Trunc. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) { return CastClass_match<OpTy, Instruction::Trunc>(Op); } -/// m_SExt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::SExt> -m_SExt(const OpTy &Op) { +/// \brief Matches SExt. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::SExt>(Op); } -/// m_ZExt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::ZExt> -m_ZExt(const OpTy &Op) { +/// \brief Matches ZExt. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::ZExt>(Op); } -/// m_UIToFP -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::UIToFP> -m_UIToFP(const OpTy &Op) { +/// \brief Matches UIToFP. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) { return CastClass_match<OpTy, Instruction::UIToFP>(Op); } -/// m_SIToFP -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::SIToFP> -m_SIToFP(const OpTy &Op) { +/// \brief Matches SIToFP. +template <typename OpTy> +inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) { return CastClass_match<OpTy, Instruction::SIToFP>(Op); } @@ -801,46 +827,41 @@ m_SIToFP(const OpTy &Op) { // Matchers for unary operators // -template<typename LHS_t> -struct not_match { +template <typename LHS_t> struct not_match { LHS_t L; not_match(const LHS_t &LHS) : L(LHS) {} - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *O = dyn_cast<Operator>(V)) if (O->getOpcode() == Instruction::Xor) return matchIfNot(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNot(Value *LHS, Value *RHS) { return (isa<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) || // FIXME: Remove CV. isa<ConstantVector>(RHS)) && - cast<Constant>(RHS)->isAllOnesValue() && - L.match(LHS); + cast<Constant>(RHS)->isAllOnesValue() && L.match(LHS); } }; -template<typename LHS> -inline not_match<LHS> m_Not(const LHS &L) { return L; } +template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; } - -template<typename LHS_t> -struct neg_match { +template <typename LHS_t> struct neg_match { LHS_t L; neg_match(const LHS_t &LHS) : L(LHS) {} - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *O = dyn_cast<Operator>(V)) if (O->getOpcode() == Instruction::Sub) return matchIfNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNeg(Value *LHS, Value *RHS) { return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) || @@ -849,36 +870,33 @@ private: } }; -/// m_Neg - Match an integer negate. -template<typename LHS> -inline neg_match<LHS> m_Neg(const LHS &L) { return L; } - +/// \brief Match an integer negate. +template <typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; } -template<typename LHS_t> -struct fneg_match { +template <typename LHS_t> struct fneg_match { LHS_t L; fneg_match(const LHS_t &LHS) : L(LHS) {} - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *O = dyn_cast<Operator>(V)) if (O->getOpcode() == Instruction::FSub) return matchIfFNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast<ConstantFP>(LHS)) + if (const auto *C = dyn_cast<ConstantFP>(LHS)) return C->isNegativeZeroValue() && L.match(RHS); return false; } }; -/// m_FNeg - Match a floating point negate. -template<typename LHS> -inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } - +/// \brief Match a floating point negate. +template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) { + return L; +} //===----------------------------------------------------------------------===// // Matchers for control flow. @@ -886,13 +904,10 @@ inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } struct br_match { BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } + br_match(BasicBlock *&Succ) : Succ(Succ) {} - template<typename OpTy> - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast<BranchInst>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *BI = dyn_cast<BranchInst>(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); return true; @@ -903,17 +918,14 @@ struct br_match { inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } -template<typename Cond_t> -struct brc_match { +template <typename Cond_t> struct brc_match { Cond_t Cond; BasicBlock *&T, *&F; brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } + : Cond(C), T(t), F(f) {} - template<typename OpTy> - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast<BranchInst>(V)) + template <typename OpTy> bool match(OpTy *V) { + if (auto *BI = dyn_cast<BranchInst>(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) { T = BI->getSuccessor(0); F = BI->getSuccessor(1); @@ -923,31 +935,28 @@ struct brc_match { } }; -template<typename Cond_t> +template <typename Cond_t> inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match<Cond_t>(C, T, F); } - //===----------------------------------------------------------------------===// // Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). // -template<typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t> +template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t> struct MaxMin_match { LHS_t L; RHS_t R; - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} + MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast<SelectInst>(V); + auto *SI = dyn_cast<SelectInst>(V); if (!SI) return false; - CmpInst_t *Cmp = dyn_cast<CmpInst_t>(SI->getCondition()); + auto *Cmp = dyn_cast<CmpInst_t>(SI->getCondition()); if (!Cmp) return false; // At this point we have a select conditioned on a comparison. Check that @@ -959,8 +968,8 @@ struct MaxMin_match { if ((TrueVal != LHS || FalseVal != RHS) && (TrueVal != RHS || FalseVal != LHS)) return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); + typename CmpInst_t::Predicate Pred = + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -969,83 +978,83 @@ struct MaxMin_match { } }; -/// smax_pred_ty - Helper class for identifying signed max predicates. +/// \brief Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// smin_pred_ty - Helper class for identifying signed min predicates. +/// \brief Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// umax_pred_ty - Helper class for identifying unsigned max predicates. +/// \brief Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// umin_pred_ty - Helper class for identifying unsigned min predicates. +/// \brief Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. +/// \brief Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. +/// \brief Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. +/// \brief Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. +/// \brief Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; } }; -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> -m_SMax(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> m_SMax(const LHS &L, + const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>(L, R); } -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> -m_SMin(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> m_SMin(const LHS &L, + const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>(L, R); } -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> -m_UMax(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> m_UMax(const LHS &L, + const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>(L, R); } -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> -m_UMin(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L, + const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R); } @@ -1058,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMax(L, R) = R iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> -m_OrdFMax(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L, + const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R); } @@ -1073,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> -m_OrdFMin(const LHS &L, const RHS &R) { +template <typename LHS, typename RHS> +inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L, + const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R); } @@ -1088,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template<typename LHS, typename RHS> +template <typename LHS, typename RHS> inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty> m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); @@ -1103,40 +1112,39 @@ m_UnordFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template<typename LHS, typename RHS> +template <typename LHS, typename RHS> inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty> m_UnordFMin(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R); } -template<typename Opnd_t> -struct Argument_match { +template <typename Opnd_t> struct Argument_match { unsigned OpI; Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template<typename OpTy> - bool match(OpTy *V) { + template <typename OpTy> bool match(OpTy *V) { CallSite CS(V); return CS.isCall() && Val.match(CS.getArgument(OpI)); } }; -/// Match an argument -template<unsigned OpI, typename Opnd_t> +/// \brief Match an argument. +template <unsigned OpI, typename Opnd_t> inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { return Argument_match<Opnd_t>(OpI, Op); } -/// Intrinsic matchers. +/// \brief Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template<typename OpTy> - bool match(OpTy *V) { - IntrinsicInst *II = dyn_cast<IntrinsicInst>(V); - return II && II->getIntrinsicID() == ID; + template <typename OpTy> bool match(OpTy *V) { + if (const auto *CI = dyn_cast<CallInst>(V)) + if (const auto *F = CI->getCalledFunction()) + return F->getIntrinsicID() == ID; + return false; } }; @@ -1147,64 +1155,74 @@ struct IntrinsicID_match { template <typename T0 = void, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, - typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty; -template <typename T0> -struct m_Intrinsic_Ty<T0> { - typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty; + typename T9 = void, typename T10 = void> +struct m_Intrinsic_Ty; +template <typename T0> struct m_Intrinsic_Ty<T0> { + typedef match_combine_and<IntrinsicID_match, Argument_match<T0>> Ty; }; -template <typename T0, typename T1> -struct m_Intrinsic_Ty<T0, T1> { - typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, - Argument_match<T1> > Ty; +template <typename T0, typename T1> struct m_Intrinsic_Ty<T0, T1> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, Argument_match<T1>> + Ty; }; template <typename T0, typename T1, typename T2> struct m_Intrinsic_Ty<T0, T1, T2> { typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty, - Argument_match<T2> > Ty; + Argument_match<T2>> Ty; }; template <typename T0, typename T1, typename T2, typename T3> struct m_Intrinsic_Ty<T0, T1, T2, T3> { typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty, - Argument_match<T3> > Ty; + Argument_match<T3>> Ty; }; -/// Match intrinsic calls like this: -/// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) -template <Intrinsic::ID IntrID> -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } +/// \brief Match intrinsic calls like this: +/// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) +template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() { + return IntrinsicID_match(IntrID); +} -template<Intrinsic::ID IntrID, typename T0> -inline typename m_Intrinsic_Ty<T0>::Ty -m_Intrinsic(const T0 &Op0) { +template <Intrinsic::ID IntrID, typename T0> +inline typename m_Intrinsic_Ty<T0>::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0)); } -template<Intrinsic::ID IntrID, typename T0, typename T1> -inline typename m_Intrinsic_Ty<T0, T1>::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { +template <Intrinsic::ID IntrID, typename T0, typename T1> +inline typename m_Intrinsic_Ty<T0, T1>::Ty m_Intrinsic(const T0 &Op0, + const T1 &Op1) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1)); } -template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2> +template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2> inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2)); } -template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3> +template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2, + typename T3> inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3)); } -// Helper intrinsic matching specializations -template<typename Opnd0> -inline typename m_Intrinsic_Ty<Opnd0>::Ty -m_BSwap(const Opnd0 &Op0) { +// Helper intrinsic matching specializations. +template <typename Opnd0> +inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic<Intrinsic::bswap>(Op0); } +template <typename Opnd0, typename Opnd1> +inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0, + const Opnd1 &Op1) { + return m_Intrinsic<Intrinsic::minnum>(Op0, Op1); +} + +template <typename Opnd0, typename Opnd1> +inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0, + const Opnd1 &Op1) { + return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 02bc583a255a..5e1be37805ff 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_IR_PREDITERATORCACHE_H +#define LLVM_IR_PREDITERATORCACHE_H + #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" #include "llvm/Support/Allocator.h" -#ifndef LLVM_IR_PREDITERATORCACHE_H -#define LLVM_IR_PREDITERATORCACHE_H - namespace llvm { /// PredIteratorCache - This class is an extremely trivial cache for diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h new file mode 100644 index 000000000000..e3c4243e9d81 --- /dev/null +++ b/include/llvm/IR/Statepoint.h @@ -0,0 +1,215 @@ +//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions and a wrapper class analogous to +// CallSite for accessing the fields of gc.statepoint, gc.relocate, and +// gc.result intrinsics +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_IR_STATEPOINT_H +#define __LLVM_IR_STATEPOINT_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +bool isStatepoint(const ImmutableCallSite &CS); +bool isStatepoint(const Instruction *inst); +bool isStatepoint(const Instruction &inst); + +bool isGCRelocate(const Instruction *inst); +bool isGCRelocate(const ImmutableCallSite &CS); + +bool isGCResult(const Instruction *inst); +bool isGCResult(const ImmutableCallSite &CS); + +/// Analogous to CallSiteBase, this provides most of the actual +/// functionality for Statepoint and ImmutableStatepoint. It is +/// templatized to allow easily specializing of const and non-const +/// concrete subtypes. This is structured analogous to CallSite +/// rather than the IntrinsicInst.h helpers since we want to support +/// invokable statepoints in the near future. +/// TODO: This does not currently allow the if(Statepoint S = ...) +/// idiom used with CallSites. Consider refactoring to support. +template <typename InstructionTy, typename ValueTy, typename CallSiteTy> +class StatepointBase { + CallSiteTy StatepointCS; + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t s) LLVM_DELETED_FUNCTION; + + protected: + explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { + assert(isStatepoint(I)); + } + explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { + assert(isStatepoint(CS)); + } + + public: + typedef typename CallSiteTy::arg_iterator arg_iterator; + + /// Return the underlying CallSite. + CallSiteTy getCallSite() { + return StatepointCS; + } + + /// Return the value actually being called or invoked. + ValueTy *actualCallee() { + return StatepointCS.getArgument(0); + } + /// Number of arguments to be passed to the actual callee. + int numCallArgs() { + return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue(); + } + /// Number of additional arguments excluding those intended + /// for garbage collection. + int numTotalVMSArgs() { + return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + } + + typename CallSiteTy::arg_iterator call_args_begin() { + // 3 = callTarget, #callArgs, flag + int Offset = 3; + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator call_args_end() { + int Offset = 3 + numCallArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for call arguments + iterator_range<arg_iterator> call_args() { + return iterator_range<arg_iterator>(call_args_begin(), call_args_end()); + } + + typename CallSiteTy::arg_iterator vm_state_begin() { + return call_args_end(); + } + typename CallSiteTy::arg_iterator vm_state_end() { + int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for vm state arguments + iterator_range<arg_iterator> vm_state_args() { + return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { + // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, + // 1st_#stack, 1st_#local, 1st_#monitor + return vm_state_begin() + 6; + } + + typename CallSiteTy::arg_iterator gc_args_begin() { + return vm_state_end(); + } + typename CallSiteTy::arg_iterator gc_args_end() { + return StatepointCS.arg_end(); + } + + /// range adapter for gc arguments + iterator_range<arg_iterator> gc_args() { + return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end()); + } + + +#ifndef NDEBUG + /// Asserts if this statepoint is malformed. Common cases for failure + /// include incorrect length prefixes for variable length sections or + /// illegal values for parameters. + void verify() { + assert(numCallArgs() >= 0 && + "number of arguments to actually callee can't be negative"); + + // The internal asserts in the iterator accessors do the rest. + (void)call_args_begin(); + (void)call_args_end(); + (void)vm_state_begin(); + (void)vm_state_end(); + (void)gc_args_begin(); + (void)gc_args_end(); + } +#endif +}; + +/// A specialization of it's base class for read only access +/// to a gc.statepoint. +class ImmutableStatepoint + : public StatepointBase<const Instruction, const Value, + ImmutableCallSite> { + typedef StatepointBase<const Instruction, const Value, ImmutableCallSite> + Base; + +public: + explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} + explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} +}; + +/// A specialization of it's base class for read-write access +/// to a gc.statepoint. +class Statepoint : public StatepointBase<Instruction, Value, CallSite> { + typedef StatepointBase<Instruction, Value, CallSite> Base; + +public: + explicit Statepoint(Instruction *I) : Base(I) {} + explicit Statepoint(CallSite CS) : Base(CS) {} +}; + +/// Wraps a call to a gc.relocate and provides access to it's operands. +/// TODO: This should likely be refactored to resememble the wrappers in +/// InstrinsicInst.h. +class GCRelocateOperands { + ImmutableCallSite RelocateCS; + + public: + GCRelocateOperands(const User* U) : RelocateCS(U) { + assert(isGCRelocate(U)); + } + GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { + assert(isGCRelocate(inst)); + } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { + assert(isGCRelocate(CS)); + } + + /// The statepoint with which this gc.relocate is associated. + const Instruction *statepoint() { + return cast<Instruction>(RelocateCS.getArgument(0)); + } + /// The index into the associate statepoint's argument list + /// which contains the base pointer of the pointer whose + /// relocation this gc.relocate describes. + int basePtrIndex() { + return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue(); + } + /// The index into the associate statepoint's argument list which + /// contains the pointer whose relocation this gc.relocate describes. + int derivedPtrIndex() { + return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue(); + } + Value *basePtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + basePtrIndex()); + } + Value *derivedPtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + derivedPtrIndex()); + } +}; +} +#endif diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 000000000000..e24112154e16 --- /dev/null +++ b/include/llvm/IR/TrackingMDRef.h @@ -0,0 +1,170 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class Metadata; +class MDNode; +class ValueAsMetadata; + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template <class T> class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef; +typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type<TrackingMDRef> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type<const TrackingMDRef> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template <class T> struct simplify_type<TypedTrackingMDRef<T>> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) { + return MD.get(); + } +}; + +template <class T> struct simplify_type<const TypedTrackingMDRef<T>> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 7955587e3c76..c2073c7750b2 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -265,7 +265,7 @@ public: /// get the actual size for a particular target, it is reasonable to use the /// DataLayout subsystem to do this. /// - bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const { + bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const { // If it's a primitive, it is always sized. if (getTypeID() == IntegerTyID || isFloatingPointTy() || getTypeID() == PointerTyID || @@ -313,6 +313,9 @@ public: typedef Type * const *subtype_iterator; subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef<Type*> subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator; subtype_reverse_iterator subtype_rbegin() const { @@ -323,7 +326,7 @@ public: } /// getContainedType - This method is used to implement the type iterator - /// (defined a the end of the file). For derived types, this returns the + /// (defined at the end of the file). For derived types, this returns the /// types 'contained' in the derived type. /// Type *getContainedType(unsigned i) const { @@ -419,7 +422,7 @@ private: /// isSizedDerivedType - Derived types like structures and arrays are sized /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. - bool isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited = nullptr) const; + bool isSizedDerivedType(SmallPtrSetImpl<const Type*> *Visited = nullptr) const; }; // Printing of types. diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index cea66a4ab069..73a63ad0349e 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -31,6 +31,7 @@ class TypeFinder { // To avoid walking constant expressions multiple times and other IR // objects, we keep several helper maps. DenseSet<const Value*> VisitedConstants; + DenseSet<const MDNode *> VisitedMetadata; DenseSet<Type*> VisitedTypes; std::vector<StructType*> StructTypes; diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h new file mode 100644 index 000000000000..5df459b1bd30 --- /dev/null +++ b/include/llvm/IR/UseListOrder.h @@ -0,0 +1,62 @@ +//===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file has structures and command-line options for preserving use-list +// order. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USELISTORDER_H +#define LLVM_IR_USELISTORDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace llvm { + +class Module; +class Function; +class Value; + +/// \brief Structure to hold a use-list order. +struct UseListOrder { + const Value *V; + const Function *F; + std::vector<unsigned> Shuffle; + + UseListOrder(const Value *V, const Function *F, size_t ShuffleSize) + : V(V), F(F), Shuffle(ShuffleSize) {} + + UseListOrder() : V(0), F(0) {} + UseListOrder(UseListOrder &&X) + : V(X.V), F(X.F), Shuffle(std::move(X.Shuffle)) {} + UseListOrder &operator=(UseListOrder &&X) { + V = X.V; + F = X.F; + Shuffle = std::move(X.Shuffle); + return *this; + } + +private: + UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; +}; + +typedef std::vector<UseListOrder> UseListOrderStack; + +/// \brief Whether to preserve use-list ordering. +bool shouldPreserveBitcodeUseListOrder(); +bool shouldPreserveAssemblyUseListOrder(); +void setPreserveBitcodeUseListOrder(bool ShouldPreserve); +void setPreserveAssemblyUseListOrder(bool ShouldPreserve); + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 848adae9ceca..f578227d6cae 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -26,9 +26,9 @@ namespace llvm { -/// OperandTraits - Compile-time customization of -/// operand-related allocators and accessors -/// for use of the User class +/// \brief Compile-time customization of User operands. +/// +/// Customizes operand-related allocators and accessors. template <class> struct OperandTraits; @@ -39,11 +39,8 @@ class User : public Value { friend struct HungoffOperandTraits; virtual void anchor(); protected: - /// NumOperands - The number of values used by this User. + /// \brief This is a pointer to the array of Uses for this User. /// - unsigned NumOperands; - - /// OperandList - This is a pointer to the array of Uses for this User. /// For nodes of fixed arity (e.g. a binary operator) this array will live /// prefixed to some derived class instance. For nodes of resizable variable /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically @@ -52,7 +49,9 @@ protected: void *operator new(size_t s, unsigned Us); User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) - : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {} + : Value(ty, vty), OperandList(OpList) { + NumOperands = NumOps; + } Use *allocHungoffUses(unsigned) const; void dropHungoffUses() { Use::zap(OperandList, OperandList + NumOperands, true); @@ -64,13 +63,13 @@ public: ~User() { Use::zap(OperandList, OperandList + NumOperands); } - /// operator delete - free memory allocated for User and Use objects + /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); - /// placement delete - required by std, but never called. + /// \brief Placement delete - required by std, but never called. void operator delete(void*, unsigned) { llvm_unreachable("Constructor throws?"); } - /// placement delete - required by std, but never called. + /// \brief Placement delete - required by std, but never called. void operator delete(void*, unsigned, bool) { llvm_unreachable("Constructor throws?"); } @@ -128,8 +127,7 @@ public: return const_op_range(op_begin(), op_end()); } - /// Convenience iterator for directly iterating over the Values in the - /// OperandList + /// \brief Iterator for directly iterating over the operand Values. struct value_op_iterator : iterator_adaptor_base<value_op_iterator, op_iterator, std::random_access_iterator_tag, Value *, @@ -150,22 +148,23 @@ public: return iterator_range<value_op_iterator>(value_op_begin(), value_op_end()); } - // dropAllReferences() - This function is in charge of "letting go" of all - // objects that this User refers to. This allows one to - // 'delete' a whole class at a time, even though there may be circular - // references... First all references are dropped, and all use counts go to - // zero. Then everything is deleted for real. Note that no operations are - // valid on an object that has "dropped all references", except operator - // delete. - // + /// \brief Drop all references to operands. + /// + /// This function is in charge of "letting go" of all objects that this User + /// refers to. This allows one to 'delete' a whole class at a time, even + /// though there may be circular references... First all references are + /// dropped, and all use counts go to zero. Then everything is deleted for + /// real. Note that no operations are valid on an object that has "dropped + /// all references", except operator delete. void dropAllReferences() { for (Use &U : operands()) U.set(nullptr); } - /// replaceUsesOfWith - Replaces all references to the "From" definition with - /// references to the "To" definition. + /// \brief Replace uses of one Value with another. /// + /// Replaces all references to the "From" definition with references to the + /// "To" definition. void replaceUsesOfWith(Value *From, Value *To); // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index b5bbc96eac2a..705fc0f52d58 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; -class MDNode; class Module; class StringRef; class Twine; @@ -53,6 +52,8 @@ typedef StringMapEntry<Value*> ValueName; // Value Class //===----------------------------------------------------------------------===// +/// \brief LLVM Value Representation +/// /// This is a very important LLVM class. It is the base class of all values /// computed by a program that may be used as operands to other values. Value is /// the super class of other important classes such as Instruction and Function. @@ -64,31 +65,45 @@ typedef StringMapEntry<Value*> ValueName; /// using this Value. A Value can also have an arbitrary number of ValueHandle /// objects that watch it and listen to RAUW and Destroy events. See /// llvm/IR/ValueHandle.h for details. -/// -/// @brief LLVM Value Representation class Value { Type *VTy; Use *UseList; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueHandleBase; - ValueName *Name; + PointerIntPair<ValueName *, 1> NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? protected: - /// SubclassOptionalData - This member is similar to SubclassData, however it - /// is for holding information which may be used to aid optimization, but - /// which may be cleared to zero without affecting conservative - /// interpretation. + /// \brief Hold subclass data that can be dropped. + /// + /// This member is similar to SubclassData, however it is for holding + /// information which may be used to aid optimization, but which may be + /// cleared to zero without affecting conservative interpretation. unsigned char SubclassOptionalData : 7; private: - /// SubclassData - This member is defined by this class, but is not used for - /// anything. Subclasses can use it to hold whatever state they find useful. - /// This field is initialized to zero by the ctor. + /// \brief Hold arbitrary subclass data. + /// + /// This member is defined by this class, but is not used for anything. + /// Subclasses can use it to hold whatever state they find useful. This + /// field is initialized to zero by the ctor. unsigned short SubclassData; +protected: + /// \brief The number of operands in the subclass. + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their number of operands, if they have + /// any. + /// + /// This is stored here to save space in User on 64-bit hosts. Since most + /// instances of Value have operands, 32-bit hosts aren't significantly + /// affected. + unsigned NumOperands; + +private: template <typename UseT> // UseT == 'Use' or 'const Use' class use_iterator_impl : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> { @@ -175,6 +190,7 @@ private: Use &getUse() const { return *UI; } /// \brief Return the operand # of this use in its User. + /// /// FIXME: Replace all callers with a direct call to Use::getOperandNo. unsigned getOperandNo() const { return UI->getOperandNo(); } }; @@ -187,15 +203,14 @@ protected: public: virtual ~Value(); - /// dump - Support for debugging, callable in GDB: V->dump() - // + /// \brief Support for debugging, callable in GDB: V->dump() void dump() const; - /// print - Implement operator<< on Value. - /// + /// \brief Implement operator<< on Value. void print(raw_ostream &O) const; /// \brief Print the name of this Value out to the specified raw_ostream. + /// /// This is useful when you just want to print 'int %reg126', not the /// instruction that generated it. If you specify a Module for context, then /// even constanst get pretty-printed; for example, the type of a null @@ -203,40 +218,56 @@ public: void printAsOperand(raw_ostream &O, bool PrintType = true, const Module *M = nullptr) const; - /// All values are typed, get the type of this value. - /// + /// \brief All values are typed, get the type of this value. Type *getType() const { return VTy; } - /// All values hold a context through their type. + /// \brief All values hold a context through their type. LLVMContext &getContext() const; - // All values can potentially be named. - bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; } - ValueName *getValueName() const { return Name; } - void setValueName(ValueName *VN) { Name = VN; } + // \brief All values can potentially be named. + bool hasName() const { return getValueName() != nullptr; } + ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } + void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } - /// getName() - Return a constant reference to the value's name. This is cheap - /// and guaranteed to return the same reference as long as the value is not - /// modified. +private: + void destroyValueName(); + +public: + /// \brief Return a constant reference to the value's name. + /// + /// This is cheap and guaranteed to return the same reference as long as the + /// value is not modified. StringRef getName() const; - /// setName() - Change the name of the value, choosing a new unique name if - /// the provided name is taken. + /// \brief Change the name of the value. + /// + /// Choose a new unique name if the provided name is taken. /// /// \param Name The new name; or "" if the value's name should be removed. void setName(const Twine &Name); - /// takeName - transfer the name from V to this value, setting V's name to - /// empty. It is an error to call V->takeName(V). + /// \brief Transfer the name from V to this value. + /// + /// After taking V's name, sets V's name to empty. + /// + /// \note It is an error to call V->takeName(V). void takeName(Value *V); - /// replaceAllUsesWith - Go through the uses list for this definition and make - /// each use point to "V" instead of "this". After this completes, 'this's - /// use list is guaranteed to be empty. + /// \brief Change all uses of this to point to a new Value. /// + /// Go through the uses list for this definition and make each use point to + /// "V" instead of "this". After this completes, 'this's use list is + /// guaranteed to be empty. void replaceAllUsesWith(Value *V); + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -255,6 +286,8 @@ public: return iterator_range<const_use_iterator>(use_begin(), use_end()); } + bool user_empty() const { return UseList == nullptr; } + typedef user_iterator_impl<User> user_iterator; typedef user_iterator_impl<const User> const_user_iterator; user_iterator user_begin() { return user_iterator(UseList); } @@ -270,36 +303,38 @@ public: return iterator_range<const_user_iterator>(user_begin(), user_end()); } - /// hasOneUse - Return true if there is exactly one user of this value. This - /// is specialized because it is a common request and does not require - /// traversing the whole use list. + /// \brief Return true if there is exactly one user of this value. /// + /// This is specialized because it is a common request and does not require + /// traversing the whole use list. bool hasOneUse() const { const_use_iterator I = use_begin(), E = use_end(); if (I == E) return false; return ++I == E; } - /// hasNUses - Return true if this Value has exactly N users. - /// + /// \brief Return true if this Value has exactly N users. bool hasNUses(unsigned N) const; - /// hasNUsesOrMore - Return true if this value has N users or more. This is - /// logically equivalent to getNumUses() >= N. + /// \brief Return true if this value has N users or more. /// + /// This is logically equivalent to getNumUses() >= N. bool hasNUsesOrMore(unsigned N) const; + /// \brief Check if this value is used in the specified basic block. bool isUsedInBasicBlock(const BasicBlock *BB) const; - /// getNumUses - This method computes the number of uses of this Value. This - /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore - /// to check for specific values. + /// \brief This method computes the number of uses of this Value. + /// + /// This is a linear time operation. Use hasOneUse, hasNUses, or + /// hasNUsesOrMore to check for specific values. unsigned getNumUses() const; - /// addUse - This method should only be used by the Use class. - /// + /// \brief This method should only be used by the Use class. void addUse(Use &U) { U.addToList(&UseList); } + /// \brief Concrete subclass of this. + /// /// An enumeration for keeping track of the concrete subclass of Value that /// is actually instantiated. Values of this enumeration are kept in the /// Value classes SubclassID field. They are used for concrete type @@ -322,8 +357,7 @@ public: ConstantStructVal, // This is an instance of ConstantStruct ConstantVectorVal, // This is an instance of ConstantVector ConstantPointerNullVal, // This is an instance of ConstantPointerNull - MDNodeVal, // This is an instance of MDNode - MDStringVal, // This is an instance of MDString + MetadataAsValueVal, // This is an instance of MetadataAsValue InlineAsmVal, // This is an instance of InlineAsm InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; @@ -334,11 +368,12 @@ public: ConstantLastVal = ConstantPointerNullVal }; - /// getValueID - Return an ID for the concrete type of this object. This is - /// used to implement the classof checks. This should not be used for any - /// other purpose, as the values may change as LLVM evolves. Also, note that - /// for instructions, the Instruction's opcode is added to InstructionVal. So - /// this means three things: + /// \brief Return an ID for the concrete type of this object. + /// + /// This is used to implement the classof checks. This should not be used + /// for any other purpose, as the values may change as LLVM evolves. Also, + /// note that for instructions, the Instruction's opcode is added to + /// InstructionVal. So this means three things: /// # there is no value with code InstructionVal (no opcode==0). /// # there are more possible values for the value type than in ValueTy enum. /// # the InstructionVal enumerator must be the highest valued enumerator in @@ -347,64 +382,62 @@ public: return SubclassID; } - /// getRawSubclassOptionalData - Return the raw optional flags value - /// contained in this value. This should only be used when testing two - /// Values for equivalence. + /// \brief Return the raw optional flags value contained in this value. + /// + /// This should only be used when testing two Values for equivalence. unsigned getRawSubclassOptionalData() const { return SubclassOptionalData; } - /// clearSubclassOptionalData - Clear the optional flags contained in - /// this value. + /// \brief Clear the optional flags contained in this value. void clearSubclassOptionalData() { SubclassOptionalData = 0; } - /// hasSameSubclassOptionalData - Test whether the optional flags contained - /// in this value are equal to the optional flags in the given value. + /// \brief Check the optional flags for equality. bool hasSameSubclassOptionalData(const Value *V) const { return SubclassOptionalData == V->SubclassOptionalData; } - /// intersectOptionalDataWith - Clear any optional flags in this value - /// that are not also set in the given value. + /// \brief Clear any optional flags not set in the given Value. void intersectOptionalDataWith(const Value *V) { SubclassOptionalData &= V->SubclassOptionalData; } - /// hasValueHandle - Return true if there is a value handle associated with - /// this value. + /// \brief Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases - /// from the specified value, returning the original uncasted value. + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripPointerCasts(); const Value *stripPointerCasts() const { return const_cast<Value*>(this)->stripPointerCasts(); } - /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the - /// specified value, returning the original uncasted value. + /// \brief Strip off pointer casts and all-zero GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripPointerCastsNoFollowAliases(); const Value *stripPointerCastsNoFollowAliases() const { return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases(); } - /// \brief Strips off unneeded pointer casts and all-constant GEPs from the - /// specified value, returning the original pointer value. + /// \brief Strip off pointer casts and all-constant inbounds GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripInBoundsConstantOffsets(); const Value *stripInBoundsConstantOffsets() const { return const_cast<Value*>(this)->stripInBoundsConstantOffsets(); } - /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates - /// the constant offset stripped. + /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets(). /// /// Stores the resulting constant offset stripped into the APInt provided. /// The provided APInt will be extended or truncated as needed to be the @@ -419,23 +452,27 @@ public: ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); } - /// \brief Strips off unneeded pointer casts and any in-bounds offsets from - /// the specified value, returning the original pointer value. + /// \brief Strip off pointer casts and inbounds GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripInBoundsOffsets(); const Value *stripInBoundsOffsets() const { return const_cast<Value*>(this)->stripInBoundsOffsets(); } - /// isDereferenceablePointer - Test if this value is always a pointer to - /// allocated and suitably aligned memory for a simple load or store. + /// \brief Check if this is always a dereferenceable pointer. + /// + /// Test if this value is always a pointer to allocated and suitably aligned + /// memory for a simple load or store. bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; - /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, - /// return the value in the PHI node corresponding to PredBB. If not, return - /// ourself. This is useful if you want to know the value something has in a - /// predecessor block. + /// \brief Translate PHI node to its predecessor from the given basic block. + /// + /// If this value is a PHI node with CurBB as its parent, return the value in + /// the PHI node corresponding to PredBB. If not, return ourself. This is + /// useful if you want to know the value something has in a predecessor + /// block. Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); const Value *DoPHITranslation(const BasicBlock *CurBB, @@ -443,11 +480,14 @@ public: return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB); } - /// MaximumAlignment - This is the greatest alignment value supported by - /// load, store, and alloca instructions, and global values. + /// \brief The maximum alignment for instructions. + /// + /// This is the greatest alignment value supported by load, store, and alloca + /// instructions, and global values. static const unsigned MaximumAlignment = 1u << 29; - /// mutateType - Mutate the type of this Value to be of the specified type. + /// \brief Mutate the type of this Value to be of the specified type. + /// /// Note that this is an extremely dangerous operation which can create /// completely invalid IR very easily. It is strongly recommended that you /// recreate IR objects with the right types instead of mutating them in @@ -456,6 +496,37 @@ public: VTy = Ty; } + /// \brief Sort the use-list. + /// + /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is + /// expected to compare two \a Use references. + template <class Compare> void sortUseList(Compare Cmp); + + /// \brief Reverse the use-list. + void reverseUseList(); + +private: + /// \brief Merge two lists together. + /// + /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes + /// "equal" items from L before items from R. + /// + /// \return the first element in the list. + /// + /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update). + template <class Compare> + static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) { + Use *Merged; + mergeUseListsImpl(L, R, &Merged, Cmp); + return Merged; + } + + /// \brief Tail-recursive helper for \a mergeUseLists(). + /// + /// \param[out] Next the first element in the list. + template <class Compare> + static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp); + protected: unsigned short getSubclassDataFromValue() const { return SubclassData; } void setValueSubclassData(unsigned short D) { SubclassData = D; } @@ -472,6 +543,91 @@ void Use::set(Value *V) { if (V) V->addUse(*this); } +template <class Compare> void Value::sortUseList(Compare Cmp) { + if (!UseList || !UseList->Next) + // No need to sort 0 or 1 uses. + return; + + // Note: this function completely ignores Prev pointers until the end when + // they're fixed en masse. + + // Create a binomial vector of sorted lists, visiting uses one at a time and + // merging lists as necessary. + const unsigned MaxSlots = 32; + Use *Slots[MaxSlots]; + + // Collect the first use, turning it into a single-item list. + Use *Next = UseList->Next; + UseList->Next = nullptr; + unsigned NumSlots = 1; + Slots[0] = UseList; + + // Collect all but the last use. + while (Next->Next) { + Use *Current = Next; + Next = Current->Next; + + // Turn Current into a single-item list. + Current->Next = nullptr; + + // Save Current in the first available slot, merging on collisions. + unsigned I; + for (I = 0; I < NumSlots; ++I) { + if (!Slots[I]) + break; + + // Merge two lists, doubling the size of Current and emptying slot I. + // + // Since the uses in Slots[I] originally preceded those in Current, send + // Slots[I] in as the left parameter to maintain a stable sort. + Current = mergeUseLists(Slots[I], Current, Cmp); + Slots[I] = nullptr; + } + // Check if this is a new slot. + if (I == NumSlots) { + ++NumSlots; + assert(NumSlots <= MaxSlots && "Use list bigger than 2^32"); + } + + // Found an open slot. + Slots[I] = Current; + } + + // Merge all the lists together. + assert(Next && "Expected one more Use"); + assert(!Next->Next && "Expected only one Use"); + UseList = Next; + for (unsigned I = 0; I < NumSlots; ++I) + if (Slots[I]) + // Since the uses in Slots[I] originally preceded those in UseList, send + // Slots[I] in as the left parameter to maintain a stable sort. + UseList = mergeUseLists(Slots[I], UseList, Cmp); + + // Fix the Prev pointers. + for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) { + I->setPrev(Prev); + Prev = &I->Next; + } +} + +template <class Compare> +void Value::mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp) { + if (!L) { + *Next = R; + return; + } + if (!R) { + *Next = L; + return; + } + if (Cmp(*R, *L)) { + *Next = R; + mergeUseListsImpl(L, R->Next, &R->Next, Cmp); + return; + } + *Next = L; + mergeUseListsImpl(L->Next, R, &L->Next, Cmp); +} // isa - Provide some specializations of isa so that we don't have to include // the subtype header files to test to see if the value is a subclass... @@ -537,12 +693,6 @@ template <> struct isa_impl<GlobalObject, Value> { } }; -template <> struct isa_impl<MDNode, Value> { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::MDNodeVal; - } -}; - // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Value*> { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index aa29b2ed6906..8fc7fdb03950 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -33,15 +33,16 @@ public: enum { NumLowBitsAvailable = 2 }; }; -/// ValueHandleBase - This is the common base class of value handles. +/// \brief This is the common base class of value handles. +/// /// ValueHandle's are smart pointers to Value's that have special behavior when /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles /// below for details. -/// class ValueHandleBase { friend class Value; protected: - /// HandleBaseKind - This indicates what sub class the handle actually is. + /// \brief This indicates what sub class the handle actually is. + /// /// This is to avoid having a vtable for the light-weight handle pointers. The /// fully general Callback version does have a vtable. enum HandleBaseKind { @@ -55,55 +56,48 @@ private: PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair; ValueHandleBase *Next; - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair<Value*, 2> VP; + Value* V; ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(V) { + if (isValid(V)) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) { + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (isValid(VP.getPointer())) + if (isValid(V)) RemoveFromUseList(); } Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); + if (V == RHS) return RHS; + if (isValid(V)) RemoveFromUseList(); + V = RHS; + if (isValid(V)) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); + if (V == RHS.V) return RHS.V; + if (isValid(V)) RemoveFromUseList(); + V = RHS.V; + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); + return V; } - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } + Value *operator->() const { return V; } + Value &operator*() const { return *V; } protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } + Value *getValPtr() const { return V; } static bool isValid(Value *V) { return V && @@ -122,26 +116,28 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where + /// \brief Add this ValueHandle to the use list for V. + /// /// List is the address of either the head of the list or a Next node within /// the existing use list. void AddToExistingUseList(ValueHandleBase **List); - /// AddToExistingUseListAfter - Add this ValueHandle to the use list after - /// Node. + /// \brief Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// AddToUseList - Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. void AddToUseList(); - /// RemoveFromUseList - Remove this ValueHandle from its current use list. + /// \brief Remove this ValueHandle from its current use list. void RemoveFromUseList(); }; -/// WeakVH - This is a value handle that tries hard to point to a Value, even -/// across RAUW operations, but will null itself out if the value is destroyed. -/// this is useful for advisory sorts of information, but should not be used as -/// the key of a map (since the map would have to rearrange itself when the -/// pointer changes). +/// \brief Value handle that is nullable, but tries to track the Value. +/// +/// This is a value handle that tries hard to point to a Value, even across +/// RAUW operations, but will null itself out if the value is destroyed. this +/// is useful for advisory sorts of information, but should not be used as the +/// key of a map (since the map would have to rearrange itself when the pointer +/// changes). class WeakVH : public ValueHandleBase { public: WeakVH() : ValueHandleBase(Weak) {} @@ -170,14 +166,16 @@ template<> struct simplify_type<WeakVH> { } }; -/// AssertingVH - This is a Value Handle that points to a value and asserts out -/// if the value is destroyed while the handle is still live. This is very -/// useful for catching dangling pointer bugs and other things which can be -/// non-obvious. One particularly useful place to use this is as the Key of a -/// map. Dangling pointer bugs often lead to really subtle bugs that only occur -/// if another object happens to get allocated to the same address as the old -/// one. Using an AssertingVH ensures that an assert is triggered as soon as -/// the bad delete occurs. +/// \brief Value handle that asserts if the Value is deleted. +/// +/// This is a Value Handle that points to a value and asserts out if the value +/// is destroyed while the handle is still live. This is very useful for +/// catching dangling pointer bugs and other things which can be non-obvious. +/// One particularly useful place to use this is as the Key of a map. Dangling +/// pointer bugs often lead to really subtle bugs that only occur if another +/// object happens to get allocated to the same address as the old one. Using +/// an AssertingVH ensures that an assert is triggered as soon as the bad +/// delete occurs. /// /// Note that an AssertingVH handle does *not* follow values across RAUW /// operations. This means that RAUW's need to explicitly update the @@ -189,25 +187,23 @@ class AssertingVH : public ValueHandleBase #endif { + friend struct DenseMapInfo<AssertingVH<ValueTy> >; #ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast<ValueTy*>(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } + Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } + void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } #else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } + Value *ThePtr; + Value *getRawValPtr() const { return ThePtr; } + void setRawValPtr(Value *P) { ThePtr = P; } #endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. + // Convert a ValueTy*, which may be const, to the raw Value*. static Value *GetAsValue(Value *V) { return V; } static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } + ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); } + void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} @@ -215,7 +211,7 @@ public: AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} + AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} #endif operator ValueTy*() const { @@ -238,21 +234,25 @@ public: // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template<typename T> struct DenseMapInfo<AssertingVH<T> > { - typedef DenseMapInfo<T*> PointerInfo; static inline AssertingVH<T> getEmptyKey() { - return AssertingVH<T>(PointerInfo::getEmptyKey()); + AssertingVH<T> Res; + Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey()); + return Res; } - static inline T* getTombstoneKey() { - return AssertingVH<T>(PointerInfo::getTombstoneKey()); + static inline AssertingVH<T> getTombstoneKey() { + AssertingVH<T> Res; + Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey()); + return Res; } static unsigned getHashValue(const AssertingVH<T> &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr()); } static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) { - return LHS == RHS; + return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(), + RHS.getRawValPtr()); } }; - + template <typename T> struct isPodLike<AssertingVH<T> > { #ifdef NDEBUG @@ -263,8 +263,7 @@ struct isPodLike<AssertingVH<T> > { }; -/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), -/// even across RAUW operations. +/// \brief Value handle that tracks a Value across RAUW. /// /// TrackingVH is designed for situations where a client needs to hold a handle /// to a Value (or subclass) across some operations which may move that value, @@ -332,12 +331,14 @@ public: ValueTy &operator*() const { return *getValPtr(); } }; -/// CallbackVH - This is a value handle that allows subclasses to define -/// callbacks that run when the underlying Value has RAUW called on it or is -/// destroyed. This class can be used as the key of a map, as long as the user -/// takes it out of the map before calling setValPtr() (since the map has to -/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this -/// class has a vtable and a virtual destructor. +/// \brief Value handle with callbacks on RAUW and destruction. +/// +/// This is a value handle that allows subclasses to define callbacks that run +/// when the underlying Value has RAUW called on it or is destroyed. This +/// class can be used as the key of a map, as long as the user takes it out of +/// the map before calling setValPtr() (since the map has to rearrange itself +/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable +/// and a virtual destructor. class CallbackVH : public ValueHandleBase { virtual void anchor(); protected: @@ -358,16 +359,20 @@ public: return getValPtr(); } - /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may - /// call any non-virtual Value method on getValPtr(), but no subclass methods. - /// If WeakVH were implemented as a CallbackVH, it would use this method to - /// call setValPtr(NULL). AssertingVH would use this method to cause an - /// assertion failure. + /// \brief Callback for Value destruction. + /// + /// Called when this->getValPtr() is destroyed, inside ~Value(), so you + /// may call any non-virtual Value method on getValPtr(), but no subclass + /// methods. If WeakVH were implemented as a CallbackVH, it would use this + /// method to call setValPtr(NULL). AssertingVH would use this method to + /// cause an assertion failure. /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. virtual void deleted() { setValPtr(nullptr); } + /// \brief Callback for Value RAUW. + /// /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were /// implemented as a CallbackVH, it would use this method to call diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index 43a79c7db2b9..f2ea405f1428 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -27,10 +27,13 @@ #define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/UniqueLock.h" #include "llvm/Support/type_traits.h" #include <iterator> +#include <memory> namespace llvm { @@ -78,8 +81,10 @@ class ValueMap { friend class ValueMapCallbackVH<KeyT, ValueT, Config>; typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH; typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT; + typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT; typedef typename Config::ExtraData ExtraData; MapT Map; + std::unique_ptr<MDMapT> MDMap; ExtraData Data; ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; @@ -90,12 +95,19 @@ public: typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} + : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} + : Map(NumInitBuckets), Data(Data) {} ~ValueMap() {} + bool hasMD() const { return MDMap; } + MDMapT &MD() { + if (!MDMap) + MDMap.reset(new MDMapT); + return *MDMap; + } + typedef ValueMapIterator<MapT, KeyT> iterator; typedef ValueMapConstIterator<MapT, KeyT> const_iterator; inline iterator begin() { return iterator(Map.begin()); } @@ -109,9 +121,12 @@ public: /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } - void clear() { Map.clear(); } + void clear() { + Map.clear(); + MDMap.reset(); + } - /// Return 1 if the specified key is in the map, 0 otherwise.
+ /// Return 1 if the specified key is in the map, 0 otherwise. size_type count(const KeyT &Val) const { return Map.find_as(Val) == Map.end() ? 0 : 1; } @@ -209,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH { : CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))), Map(Map) {} + // Private constructor used to create empty/tombstone DenseMap keys. + ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} + public: KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); } @@ -216,12 +234,11 @@ public: // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); + unique_lock<typename Config::mutex_type> Guard; if (M) - M->acquire(); + Guard = unique_lock<typename Config::mutex_type>(*M); Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. Copy.Map->Map.erase(Copy); // Definitely destroys *this. - if (M) - M->release(); } void allUsesReplacedWith(Value *new_key) override { assert(isa<KeySansPointerT>(new_key) && @@ -229,8 +246,9 @@ public: // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); + unique_lock<typename Config::mutex_type> Guard; if (M) - M->acquire(); + Guard = unique_lock<typename Config::mutex_type>(*M); KeyT typed_new_key = cast<KeySansPointerT>(new_key); // Can destroy *this: @@ -245,27 +263,24 @@ public: Copy.Map->insert(std::make_pair(typed_new_key, Target)); } } - if (M) - M->release(); } }; template<typename KeyT, typename ValueT, typename Config> struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > { typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH; - typedef DenseMapInfo<KeyT> PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), nullptr); + return VH(DenseMapInfo<Value *>::getEmptyKey()); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), nullptr); + return VH(DenseMapInfo<Value *>::getTombstoneKey()); } static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); + return DenseMapInfo<KeyT>::getHashValue(Val.Unwrap()); } static unsigned getHashValue(const KeyT &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo<KeyT>::getHashValue(Val); } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 0272e206f37a..43bd123e7f44 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -77,8 +77,8 @@ class VerifierPass { public: explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - PreservedAnalyses run(Module *M); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Module &M); + PreservedAnalyses run(Function &F); static StringRef name() { return "VerifierPass"; } }; diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index 59ffc095f47f..2d9ace0b62a0 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -15,12 +15,12 @@ #ifndef LLVM_IRREADER_IRREADER_H #define LLVM_IRREADER_IRREADER_H +#include "llvm/Support/MemoryBuffer.h" #include <string> namespace llvm { class Module; -class MemoryBuffer; class SMDiagnostic; class LLVMContext; @@ -28,20 +28,21 @@ class LLVMContext; /// for it which does lazy deserialization of function bodies. Otherwise, /// attempt to parse it as LLVM Assembly and return a fully populated /// Module. -Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context); +std::unique_ptr<Module> getLazyIRFileModule(StringRef Filename, + SMDiagnostic &Err, + LLVMContext &Context); /// If the given MemoryBuffer holds a bitcode image, return a Module /// for it. Otherwise, attempt to parse it as LLVM Assembly and return -/// a Module for it. This function *never* takes ownership of Buffer. -Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context); +/// a Module for it. +std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, + LLVMContext &Context); /// If the given file holds a bitcode image, return a Module for it. /// Otherwise, attempt to parse it as LLVM Assembly and return a Module /// for it. -Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context); - +std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context); } #endif diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 02f4259a51ac..30280033ee20 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -71,8 +71,9 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); -void initializeAtomicExpandLoadLinkedPass(PassRegistry&); +void initializeAtomicExpandPass(PassRegistry&); void initializeSampleProfileLoaderPass(PassRegistry&); +void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); @@ -89,6 +90,8 @@ void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeCFLAliasAnalysisPass(PassRegistry&); +void initializeForwardControlFlowIntegrityPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); @@ -103,7 +106,6 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); -void initializeDebugIRPass(PassRegistry&); void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); @@ -119,15 +121,16 @@ void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); +void initializeInstrProfilingPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); +void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); -void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); @@ -207,6 +210,7 @@ void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); +void initializePAEvalPass(PassRegistry &); void initializeOptimizePHIsPass(PassRegistry&); void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); @@ -259,10 +263,13 @@ void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeDataLayoutPassPass(PassRegistry &); void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); +void initializeFunctionTargetTransformInfoPass(PassRegistry &); void initializeNoTTIPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); +void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); +void initializeScopedNoAliasAAPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); @@ -277,7 +284,9 @@ void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); +void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); +void initializeRewriteSymbolsPass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index b19b2325f73b..0c9ce4a54f02 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -32,8 +32,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LTO_CODE_GENERATOR_H -#define LTO_CODE_GENERATOR_H +#ifndef LLVM_LTO_LTOCODEGENERATOR_H +#define LLVM_LTO_LTOCODEGENERATOR_H #include "llvm-c/lto.h" #include "llvm/ADT/ArrayRef.h" @@ -61,10 +61,11 @@ struct LTOCodeGenerator { static const char *getVersionString(); LTOCodeGenerator(); + LTOCodeGenerator(std::unique_ptr<LLVMContext> Context); ~LTOCodeGenerator(); // Merge given module, return true on success. - bool addModule(struct LTOModule*, std::string &errMsg); + bool addModule(struct LTOModule *); void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); @@ -101,6 +102,7 @@ struct LTOCodeGenerator { bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string &errMsg); // As with compile_to_file(), this function compiles the merged module into @@ -112,19 +114,23 @@ struct LTOCodeGenerator { bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string &errMsg); void setDiagnosticHandler(lto_diagnostic_handler_t, void *); + LLVMContext &getContext() { return Context; } + private: void initializeLTOPasses(); bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, std::string &errMsg); + bool disableGVNLoadPRE, bool disableVectorization, + std::string &errMsg); void applyScopeRestrictions(); - void applyRestriction(GlobalValue &GV, const ArrayRef<StringRef> &Libcalls, + void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls, std::vector<const char *> &MustPreserveList, - SmallPtrSet<GlobalValue *, 8> &AsmUsed, + SmallPtrSetImpl<GlobalValue *> &AsmUsed, Mangler &Mangler); bool determineTarget(std::string &errMsg); @@ -134,6 +140,8 @@ private: typedef StringMap<uint8_t> StringSet; + void initialize(); + std::unique_ptr<LLVMContext> OwnedContext; LLVMContext &Context; Linker IRLinker; TargetMachine *TargetMach; @@ -142,7 +150,7 @@ private: lto_codegen_model CodeModel; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; - MemoryBuffer *NativeObjectFile; + std::unique_ptr<MemoryBuffer> NativeObjectFile; std::vector<char *> CodegenOptions; std::string MCpu; std::string MAttr; @@ -152,4 +160,4 @@ private: void *DiagContext; }; } -#endif // LTO_CODE_GENERATOR_H +#endif diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h index c43846a64050..53c2b8e521be 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/LTOModule.h @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LTO_MODULE_H -#define LTO_MODULE_H +#ifndef LLVM_LTO_LTOMODULE_H +#define LLVM_LTO_LTOMODULE_H #include "llvm-c/lto.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -37,8 +38,6 @@ namespace llvm { /// struct LTOModule { private: - typedef StringMap<uint8_t> StringSet; - struct NameAndAttributes { const char *name; uint32_t attributes; @@ -46,21 +45,27 @@ private: const GlobalValue *symbol; }; + std::unique_ptr<LLVMContext> OwnedContext; + std::unique_ptr<object::IRObjectFile> IRFile; std::unique_ptr<TargetMachine> _target; - StringSet _linkeropt_strings; + StringSet<> _linkeropt_strings; std::vector<const char *> _deplibs; std::vector<const char *> _linkeropts; std::vector<NameAndAttributes> _symbols; // _defines and _undefines only needed to disambiguate tentative definitions - StringSet _defines; + StringSet<> _defines; StringMap<NameAndAttributes> _undefines; std::vector<const char*> _asm_undefines; LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM); + LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM, + std::unique_ptr<LLVMContext> Context); public: + ~LTOModule(); + /// Returns 'true' if the file or memory contents is LLVM bitcode. static bool isBitcodeFile(const void *mem, size_t length); static bool isBitcodeFile(const char *path); @@ -71,8 +76,8 @@ public: StringRef triplePrefix); /// Create a MemoryBuffer from a memory range with an optional name. - static MemoryBuffer *makeBuffer(const void *mem, size_t length, - StringRef name = ""); + static std::unique_ptr<MemoryBuffer> + makeBuffer(const void *mem, size_t length, StringRef name = ""); /// Create an LTOModule. N.B. These methods take ownership of the buffer. The /// caller must have initialized the Targets, the TargetMCs, the AsmPrinters, @@ -95,6 +100,13 @@ public: TargetOptions options, std::string &errMsg, StringRef path = ""); + static LTOModule *createInLocalContext(const void *mem, size_t length, + TargetOptions options, + std::string &errMsg, StringRef path); + static LTOModule *createInContext(const void *mem, size_t length, + TargetOptions options, std::string &errMsg, + StringRef path, LLVMContext *Context); + const Module &getModule() const { return const_cast<LTOModule*>(this)->getModule(); } @@ -202,10 +214,9 @@ private: /// Get string that the data pointer points to. bool objcClassNameFromExpression(const Constant *c, std::string &name); - /// Create an LTOModule (private version). N.B. This method takes ownership of - /// the buffer. - static LTOModule *makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer, - TargetOptions options, std::string &errMsg); + /// Create an LTOModule (private version). + static LTOModule *makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, + std::string &errMsg, LLVMContext *Context); }; } -#endif // LTO_MODULE_H +#endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index e06560ca0b64..2e8feab6d29d 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -18,7 +18,6 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" -#include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" @@ -33,6 +32,7 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" #include <cstdlib> @@ -52,15 +52,18 @@ namespace { (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); + (void) llvm::createAlignmentFromAssumptionsPass(); (void) llvm::createBasicAliasAnalysisPass(); (void) llvm::createLibCallAliasAnalysisPass(nullptr); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); + (void) llvm::createScopedNoAliasAAPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); + (void) llvm::createCFLAliasAnalysisPass(); (void) llvm::createStructurizeCFGPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); @@ -75,6 +78,7 @@ namespace { (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); (void) llvm::createGCOVProfilerPass(); + (void) llvm::createInstrProfilingPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -107,6 +111,7 @@ namespace { (void) llvm::createObjCARCExpandPass(); (void) llvm::createObjCARCContractPass(); (void) llvm::createObjCARCOptPass(); + (void) llvm::createPAEvalPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -134,7 +139,7 @@ namespace { (void) llvm::createConstantHoistingPass(); (void) llvm::createCodeGenPreparePass(); (void) llvm::createEarlyCSEPass(); - (void)llvm::createMergedLoadStoreMotionPass(); + (void) llvm::createMergedLoadStoreMotionPass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); @@ -160,15 +165,15 @@ namespace { (void) llvm::createPartiallyInlineLibCallsPass(); (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); + (void) llvm::createRewriteSymbolsPass(); (void)new llvm::IntervalPartition(); - (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); ((llvm::Function*)nullptr)->viewCFGOnly(); llvm::RGPassManager RGM; ((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr); - X.add((llvm::Value*)nullptr, 0, nullptr); // for -print-alias-sets + X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 6254bbb6d6d5..9c3ecea590bd 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -10,52 +10,78 @@ #ifndef LLVM_LINKER_LINKER_H #define LLVM_LINKER_LINKER_H -#include "llvm/ADT/SmallPtrSet.h" -#include <string> +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/DiagnosticInfo.h" namespace llvm { - -class Comdat; -class GlobalValue; class Module; -class StringRef; class StructType; +class Type; /// This class provides the core functionality of linking in LLVM. It keeps a /// pointer to the merged module so far. It doesn't take ownership of the /// module since it is assumed that the user of this class will want to do /// something with it after the linking. class Linker { - public: - enum LinkerMode { - DestroySource = 0, // Allow source module to be destroyed. - PreserveSource = 1 // Preserve the source module. +public: + struct StructTypeKeyInfo { + struct KeyTy { + ArrayRef<Type *> ETypes; + bool IsPacked; + KeyTy(ArrayRef<Type *> E, bool P); + KeyTy(const StructType *ST); + bool operator==(const KeyTy &that) const; + bool operator!=(const KeyTy &that) const; }; + static StructType *getEmptyKey(); + static StructType *getTombstoneKey(); + static unsigned getHashValue(const KeyTy &Key); + static unsigned getHashValue(const StructType *ST); + static bool isEqual(const KeyTy &LHS, const StructType *RHS); + static bool isEqual(const StructType *LHS, const StructType *RHS); + }; + + typedef DenseSet<StructType *, StructTypeKeyInfo> NonOpaqueStructTypeSet; + typedef DenseSet<StructType *> OpaqueStructTypeSet; + + struct IdentifiedStructTypeSet { + // The set of opaque types is the composite module. + OpaqueStructTypeSet OpaqueStructTypes; + + // The set of identified but non opaque structures in the composite module. + NonOpaqueStructTypeSet NonOpaqueStructTypes; + + void addNonOpaque(StructType *Ty); + void addOpaque(StructType *Ty); + StructType *findNonOpaque(ArrayRef<Type *> ETypes, bool IsPacked); + bool hasType(StructType *Ty); + }; + + Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Linker(Module *M); + ~Linker(); + + Module *getModule() const { return Composite; } + void deleteModule(); - Linker(Module *M, bool SuppressWarnings=false); - ~Linker(); + /// \brief Link \p Src into the composite. The source is destroyed. + /// Returns true on error. + bool linkInModule(Module *Src); - Module *getModule() const { return Composite; } - void deleteModule(); + static bool LinkModules(Module *Dest, Module *Src, + DiagnosticHandlerFunction DiagnosticHandler); - /// \brief Link \p Src into the composite. The source is destroyed if - /// \p Mode is DestroySource and preserved if it is PreserveSource. - /// If \p ErrorMsg is not null, information about any error is written - /// to it. - /// Returns true on error. - bool linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg); - bool linkInModule(Module *Src, std::string *ErrorMsg) { - return linkInModule(Src, Linker::DestroySource, ErrorMsg); - } + static bool LinkModules(Module *Dest, Module *Src); - static bool LinkModules(Module *Dest, Module *Src, unsigned Mode, - std::string *ErrorMsg); +private: + void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Module *Composite; - private: - Module *Composite; - SmallPtrSet<StructType*, 32> IdentifiedStructTypes; + IdentifiedStructTypeSet IdentifiedStructTypes; - bool SuppressWarnings; + DiagnosticHandlerFunction DiagnosticHandler; }; } // End llvm namespace diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index 2e76074db774..1fc0332f63c2 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -12,10 +12,12 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_CONSTANTPOOL_H -#define LLVM_MC_CONSTANTPOOL_H +#ifndef LLVM_MC_CONSTANTPOOLS_H +#define LLVM_MC_CONSTANTPOOLS_H +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" + namespace llvm { class MCContext; class MCExpr; diff --git a/include/llvm/MC/MCAnalysis/MCAtom.h b/include/llvm/MC/MCAnalysis/MCAtom.h deleted file mode 100644 index 33f3431a59a9..000000000000 --- a/include/llvm/MC/MCAnalysis/MCAtom.h +++ /dev/null @@ -1,199 +0,0 @@ -//===-- MCAtom.h ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCAtom class, which is used to -// represent a contiguous region in a decoded object that is uniformly data or -// instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCATOM_H -#define LLVM_MC_MCANALYSIS_MCATOM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/DataTypes.h" -#include <vector> - -namespace llvm { - -class MCModule; - -class MCAtom; -class MCTextAtom; -class MCDataAtom; - -/// \brief Represents a contiguous range of either instructions (a TextAtom) -/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. -class MCAtom { - virtual void anchor(); -public: - virtual ~MCAtom() {} - - enum AtomKind { TextAtom, DataAtom }; - AtomKind getKind() const { return Kind; } - - /// \brief Get the start address of the atom. - uint64_t getBeginAddr() const { return Begin; } - /// \brief Get the end address, i.e. the last one inside the atom. - uint64_t getEndAddr() const { return End; } - - /// \name Atom modification methods: - /// When modifying a TextAtom, keep instruction boundaries in mind. - /// For instance, split must me given the start address of an instruction. - /// @{ - - /// \brief Splits the atom in two at a given address. - /// \param SplitPt Address at which to start a new atom, splitting this one. - /// \returns The newly created atom starting at \p SplitPt. - virtual MCAtom *split(uint64_t SplitPt) = 0; - - /// \brief Truncates an atom, discarding everything after \p TruncPt. - /// \param TruncPt Last byte address to be contained in this atom. - virtual void truncate(uint64_t TruncPt) = 0; - /// @} - - /// \name Naming: - /// - /// This is mostly for display purposes, and may contain anything that hints - /// at what the atom contains: section or symbol name, BB start address, .. - /// @{ - StringRef getName() const { return Name; } - void setName(StringRef NewName) { Name = NewName.str(); } - /// @} - -protected: - const AtomKind Kind; - std::string Name; - MCModule *Parent; - uint64_t Begin, End; - - friend class MCModule; - MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) - : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } - - /// \name Atom remapping helpers - /// @{ - - /// \brief Remap the atom, using the given range, updating Begin/End. - /// One or both of the bounds can remain the same, but overlapping with other - /// atoms in the module is still forbidden. - void remap(uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Remap the atom to prepare for a truncation at TruncPt. - /// Equivalent to: - /// \code - /// // Bound checks - /// remap(Begin, TruncPt); - /// \endcode - void remapForTruncate(uint64_t TruncPt); - - /// \brief Remap the atom to prepare for a split at SplitPt. - /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. - /// The current atom is truncated to \p LEnd. - void remapForSplit(uint64_t SplitPt, - uint64_t &LBegin, uint64_t &LEnd, - uint64_t &RBegin, uint64_t &REnd); - /// @} -}; - -/// \name Text atom -/// @{ - -/// \brief An entry in an MCTextAtom: a disassembled instruction. -/// NOTE: Both the Address and Size field are actually redundant when taken in -/// the context of the text atom, and may better be exposed in an iterator -/// instead of stored in the atom, which would replace this class. -class MCDecodedInst { -public: - MCInst Inst; - uint64_t Address; - uint64_t Size; - MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) - : Inst(Inst), Address(Address), Size(Size) {} -}; - -/// \brief An atom consisting of disassembled instructions. -class MCTextAtom : public MCAtom { -private: - typedef std::vector<MCDecodedInst> InstListTy; - InstListTy Insts; - - /// \brief The address of the next appended instruction, i.e., the - /// address immediately after the last instruction in the atom. - uint64_t NextInstAddress; -public: - /// Append an instruction, expanding the atom if necessary. - void addInst(const MCInst &Inst, uint64_t Size); - - /// \name Instruction list access - /// @{ - typedef InstListTy::const_iterator const_iterator; - const_iterator begin() const { return Insts.begin(); } - const_iterator end() const { return Insts.end(); } - - const MCDecodedInst &back() const { return Insts.back(); } - const MCDecodedInst &at(size_t n) const { return Insts.at(n); } - size_t size() const { return Insts.size(); } - /// @} - - /// \name Atom type specific split/truncate logic. - /// @{ - MCTextAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} -}; -/// @} - -/// \name Data atom -/// @{ - -/// \brief An entry in an MCDataAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; - -/// \brief An atom consising of a sequence of bytes. -class MCDataAtom : public MCAtom { - std::vector<MCData> Data; - -public: - /// Append a data entry, expanding the atom if necessary. - void addData(const MCData &D); - - /// Get a reference to the data in this atom. - ArrayRef<MCData> getData() const { return Data; } - - /// \name Atom type specific split/truncate logic. - /// @{ - MCDataAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(DataAtom, P, Begin, End) { - Data.reserve(End + 1 - Begin); - } -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCFunction.h b/include/llvm/MC/MCAnalysis/MCFunction.h deleted file mode 100644 index 44fa4503b8e0..000000000000 --- a/include/llvm/MC/MCAnalysis/MCFunction.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- MCFunction.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the data structures to hold a CFG reconstructed from -// machine code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCFUNCTION_H -#define LLVM_MC_MCANALYSIS_MCFUNCTION_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCInst.h" -#include <memory> -#include <string> -#include <vector> - -namespace llvm { - -class MCFunction; -class MCModule; -class MCTextAtom; - -/// \brief Basic block containing a sequence of disassembled instructions. -/// The basic block is backed by an MCTextAtom, which holds the instructions, -/// and the address range it covers. -/// Create a basic block using MCFunction::createBlock. -class MCBasicBlock { - const MCTextAtom *Insts; - - // MCFunction owns the basic block. - MCFunction *Parent; - friend class MCFunction; - MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); - - /// \name Predecessors/Successors, to represent the CFG. - /// @{ - typedef std::vector<const MCBasicBlock *> BasicBlockListTy; - BasicBlockListTy Successors; - BasicBlockListTy Predecessors; - /// @} -public: - - /// \brief Get the backing MCTextAtom, containing the instruction sequence. - const MCTextAtom *getInsts() const { return Insts; } - - /// \name Get the owning MCFunction. - /// @{ - const MCFunction *getParent() const { return Parent; } - MCFunction *getParent() { return Parent; } - /// @} - - /// MC CFG access: Predecessors/Successors. - /// @{ - typedef BasicBlockListTy::const_iterator succ_const_iterator; - succ_const_iterator succ_begin() const { return Successors.begin(); } - succ_const_iterator succ_end() const { return Successors.end(); } - - typedef BasicBlockListTy::const_iterator pred_const_iterator; - pred_const_iterator pred_begin() const { return Predecessors.begin(); } - pred_const_iterator pred_end() const { return Predecessors.end(); } - - void addSuccessor(const MCBasicBlock *MCBB); - bool isSuccessor(const MCBasicBlock *MCBB) const; - - void addPredecessor(const MCBasicBlock *MCBB); - bool isPredecessor(const MCBasicBlock *MCBB) const; - - /// \brief Split block, mirrorring NewAtom = Insts->split(..). - /// This moves all successors to \p SplitBB, and - /// adds a fallthrough to it. - /// \p SplitBB The result of splitting Insts, a basic block directly following - /// this basic block. - void splitBasicBlock(MCBasicBlock *SplitBB); - /// @} -}; - -/// \brief Represents a function in machine code, containing MCBasicBlocks. -/// MCFunctions are created by MCModule. -class MCFunction { - MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; - MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; - - std::string Name; - MCModule *ParentModule; - typedef std::vector<std::unique_ptr<MCBasicBlock>> BasicBlockListTy; - BasicBlockListTy Blocks; - - // MCModule owns the function. - friend class MCModule; - MCFunction(StringRef Name, MCModule *Parent); - -public: - /// \brief Create an MCBasicBlock backed by Insts and add it to this function. - /// \param Insts Sequence of straight-line code backing the basic block. - /// \returns The newly created basic block. - MCBasicBlock &createBlock(const MCTextAtom &Insts); - - StringRef getName() const { return Name; } - - /// \name Get the owning MC Module. - /// @{ - const MCModule *getParent() const { return ParentModule; } - MCModule *getParent() { return ParentModule; } - /// @} - - /// \name Access to the function's basic blocks. No ordering is enforced, - /// except that the first block is the entry block. - /// @{ - /// \brief Get the entry point basic block. - const MCBasicBlock *getEntryBlock() const { return front(); } - MCBasicBlock *getEntryBlock() { return front(); } - - bool empty() const { return Blocks.empty(); } - - typedef BasicBlockListTy::const_iterator const_iterator; - typedef BasicBlockListTy:: iterator iterator; - const_iterator begin() const { return Blocks.begin(); } - iterator begin() { return Blocks.begin(); } - const_iterator end() const { return Blocks.end(); } - iterator end() { return Blocks.end(); } - - const MCBasicBlock* front() const { return Blocks.front().get(); } - MCBasicBlock* front() { return Blocks.front().get(); } - const MCBasicBlock* back() const { return Blocks.back().get(); } - MCBasicBlock* back() { return Blocks.back().get(); } - - /// \brief Find the basic block, if any, that starts at \p StartAddr. - const MCBasicBlock *find(uint64_t StartAddr) const; - MCBasicBlock *find(uint64_t StartAddr); - /// @} -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCModule.h b/include/llvm/MC/MCAnalysis/MCModule.h deleted file mode 100644 index cf7e2c0a645e..000000000000 --- a/include/llvm/MC/MCAnalysis/MCModule.h +++ /dev/null @@ -1,134 +0,0 @@ -//===-- MCModule.h - MCModule class -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCModule class, which is used to -// represent a complete, disassembled object file or executable. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCMODULE_H -#define LLVM_MC_MCANALYSIS_MCMODULE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" -#include <memory> -#include <vector> - -namespace llvm { - -class MCAtom; -class MCBasicBlock; -class MCDataAtom; -class MCFunction; -class MCObjectDisassembler; -class MCTextAtom; - -/// \brief A completely disassembled object file or executable. -/// It comprises a list of MCAtom's, each representing a contiguous range of -/// either instructions or data. -/// An MCModule is created using MCObjectDisassembler::buildModule. -class MCModule { - /// \name Atom tracking - /// @{ - - /// \brief Atoms in this module, sorted by begin address. - /// FIXME: This doesn't handle overlapping atoms (which happen when a basic - /// block starts in the middle of an instruction of another basic block.) - typedef std::vector<MCAtom*> AtomListTy; - AtomListTy Atoms; - - // For access to map/remap. - friend class MCAtom; - - /// \brief Remap \p Atom to the given range, and update its Begin/End fields. - /// \param Atom An atom belonging to this module. - /// An atom should always use this method to update its bounds, because this - /// enables the owning MCModule to keep track of its atoms. - void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Insert an atom in the module, using its Begin and End addresses. - void map(MCAtom *NewAtom); - /// @} - - /// \name Basic block tracking - /// @{ - typedef std::vector<MCBasicBlock*> BBsByAtomTy; - BBsByAtomTy BBsByAtom; - - // For access to basic block > atom tracking. - friend class MCBasicBlock; - friend class MCTextAtom; - - /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. - /// This is used to update succs/preds when \p Atom is split. - void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); - void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); - /// @} - - /// \name Function tracking - /// @{ - typedef std::vector<std::unique_ptr<MCFunction>> FunctionListTy; - FunctionListTy Functions; - /// @} - - /// The address of the entrypoint function. - uint64_t Entrypoint; - - MCModule (const MCModule &) LLVM_DELETED_FUNCTION; - MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; - - // MCObjectDisassembler creates MCModules. - friend class MCObjectDisassembler; - -public: - MCModule(); - ~MCModule(); - - /// \name Create a new MCAtom covering the specified offset range. - /// @{ - MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); - MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); - /// @} - - /// \name Access to the owned atom list, ordered by begin address. - /// @{ - const MCAtom *findAtomContaining(uint64_t Addr) const; - MCAtom *findAtomContaining(uint64_t Addr); - const MCAtom *findFirstAtomAfter(uint64_t Addr) const; - MCAtom *findFirstAtomAfter(uint64_t Addr); - - typedef AtomListTy::const_iterator const_atom_iterator; - typedef AtomListTy:: iterator atom_iterator; - const_atom_iterator atom_begin() const { return Atoms.begin(); } - atom_iterator atom_begin() { return Atoms.begin(); } - const_atom_iterator atom_end() const { return Atoms.end(); } - atom_iterator atom_end() { return Atoms.end(); } - /// @} - - /// \brief Create a new MCFunction. - MCFunction *createFunction(StringRef Name); - - /// \name Access to the owned function list. - /// @{ - typedef FunctionListTy::const_iterator const_func_iterator; - typedef FunctionListTy:: iterator func_iterator; - const_func_iterator func_begin() const { return Functions.begin(); } - func_iterator func_begin() { return Functions.begin(); } - const_func_iterator func_end() const { return Functions.end(); } - func_iterator func_end() { return Functions.end(); } - /// @} - - /// \brief Get the address of the entrypoint function, or 0 if there is none. - uint64_t getEntrypoint() const { return Entrypoint; } -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCModuleYAML.h b/include/llvm/MC/MCAnalysis/MCModuleYAML.h deleted file mode 100644 index 48562777677b..000000000000 --- a/include/llvm/MC/MCAnalysis/MCModuleYAML.h +++ /dev/null @@ -1,40 +0,0 @@ -//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file declares classes for handling the YAML representation -/// of MCModule. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCMODULEYAML_H -#define LLVM_MC_MCANALYSIS_MCMODULEYAML_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -class MCInstrInfo; -class MCRegisterInfo; - -/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. -/// \returns The empty string on success, an error message on failure. -StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -/// \brief Creates a new module and returns it in \p MCM. -/// \returns The empty string on success, an error message on failure. -StringRef yaml2mcmodule(std::unique_ptr<MCModule> &MCM, StringRef YamlContent, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -} // end namespace llvm - -#endif diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 82b65fdaf5c8..216271086a40 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAsmBack.h - MC Asm Backend --------------------*- C++ -*-===// +//===-- llvm/MC/MCAsmBackend.h - MC Asm Backend -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -61,20 +61,6 @@ public: /// markers. If not, data region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// isSectionAtomizable - Check whether the given section can be split into - /// atoms. - /// - /// \see MCAssembler::isSymbolLinkerVisible(). - virtual bool isSectionAtomizable(const MCSection &Section) const { - return true; - } - /// @name Target Fixup Interfaces /// @{ @@ -146,7 +132,7 @@ public: /// \brief Generate the compact unwind encoding for the CFI instructions. virtual uint32_t - generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { + generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { return 0; } }; diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 06e473d6b625..a750a0fd5cef 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -31,22 +31,23 @@ class MCContext; namespace WinEH { enum class EncodingType { - ET_Invalid, /// Invalid - ET_Alpha, /// Windows Alpha - ET_Alpha64, /// Windows AXP64 - ET_ARM, /// Windows NT (Windows on ARM) - ET_CE, /// Windows CE ARM, PowerPC, SH3, SH4 - ET_Itanium, /// Windows x64, Windows Itanium (IA-64) - ET_MIPS = ET_Alpha, + Invalid, /// Invalid + Alpha, /// Windows Alpha + Alpha64, /// Windows AXP64 + ARM, /// Windows NT (Windows on ARM) + CE, /// Windows CE ARM, PowerPC, SH3, SH4 + Itanium, /// Windows x64, Windows Itanium (IA-64) + MIPS = Alpha, }; } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - WinEH, /// Windows Exception Handling + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) + MSVC, /// MSVC compatible exception handling }; namespace LCOMM { @@ -87,16 +88,11 @@ protected: bool HasMachoTBSSDirective; /// True if the compiler should emit a ".reference .constructors_used" or - /// ".reference .destructors_used" directive after the a static ctor/dtor + /// ".reference .destructors_used" directive after the static ctor/dtor /// list. This directive is only emitted in Static relocation model. Default /// is false. bool HasStaticCtorDtorReferenceInStaticMode; - /// True if the linker has a bug and requires that the debug_line section be - /// of a minimum size. In practice such a linker requires a non-empty line - /// sequence if a file is present. Default to false. - bool LinkerRequiresNonEmptyDwarfLines; - /// This is the maximum possible length of an instruction, which is needed to /// compute the size of an inline asm. Defaults to 4. unsigned MaxInstLength; @@ -128,6 +124,10 @@ protected: /// file. Defaults to "L" const char *PrivateGlobalPrefix; + /// This prefix is used for labels for basic blocks. Defaults to the same as + /// PrivateGlobalPrefix. + const char *PrivateLabelPrefix; + /// This prefix is used for symbols that should be passed through the /// assembler but be removed by the linker. This is 'l' on Darwin, currently /// used for some ObjC metadata. The default of "" meast that for this system @@ -220,11 +220,16 @@ protected: //===--- Global Variable Emission Directives --------------------------===// - /// This is the directive used to declare a global entity. Defaults to NULL. + /// This is the directive used to declare a global entity. Defaults to + /// ".globl". const char *GlobalDirective; - /// True if the assembler supports the .set directive. Defaults to true. - bool HasSetDirective; + /// True if the expression + /// .long f - g + /// uses an relocation but it can be supressed by writting + /// a = f - g + /// .long a + bool SetDirectiveSuppressesReloc; /// False if the assembler requires that we use /// \code @@ -265,6 +270,9 @@ protected: /// to false. bool HasNoDeadStrip; + /// Used to declare a global as being a weak symbol. Defaults to ".weak". + const char *WeakDirective; + /// This directive, if non-null, is used to declare a global as being a weak /// undefined symbol. Defaults to NULL. const char *WeakRefDirective; @@ -295,9 +303,6 @@ protected: //===--- Dwarf Emission Directives -----------------------------------===// - /// True if target asm supports leb128 directives. Defaults to false. - bool HasLEB128; - /// True if target supports emission of debugging information. Defaults to /// false. bool SupportsDebugInformation; @@ -377,6 +382,12 @@ public: return nullptr; } + /// \brief True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; @@ -404,9 +415,6 @@ public: bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } - bool getLinkerRequiresNonEmptyDwarfLines() const { - return LinkerRequiresNonEmptyDwarfLines; - } unsigned getMaxInstLength() const { return MaxInstLength; } unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } @@ -421,6 +429,7 @@ public: bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { return LinkerPrivateGlobalPrefix[0] != '\0'; } @@ -445,7 +454,9 @@ public: bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } unsigned getTextAlignFillValue() const { return TextAlignFillValue; } const char *getGlobalDirective() const { return GlobalDirective; } - bool hasSetDirective() const { return HasSetDirective; } + bool doesSetDirectiveSuppressesReloc() const { + return SetDirectiveSuppressesReloc; + } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } bool getCOMMDirectiveAlignmentIsInBytes() const { return COMMDirectiveAlignmentIsInBytes; @@ -457,6 +468,7 @@ public: bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakDirective() const { return WeakDirective; } const char *getWeakRefDirective() const { return WeakRefDirective; } bool hasWeakDefDirective() const { return HasWeakDefDirective; } bool hasWeakDefCanBeHiddenDirective() const { @@ -471,19 +483,27 @@ public: MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; } - bool hasLEB128() const { return HasLEB128; } bool doesSupportDebugInformation() const { return SupportsDebugInformation; } bool doesSupportExceptionHandling() const { return ExceptionsType != ExceptionHandling::None; } ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - bool isExceptionHandlingDwarf() const { + + /// Return true if the exception handling type uses the language-specific data + /// area (LSDA) format specified by the Itanium C++ ABI. + bool usesItaniumLSDAForExceptions() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || ExceptionsType == ExceptionHandling::ARM || - // Windows handler data still uses DWARF LSDA encoding. - ExceptionsType == ExceptionHandling::WinEH); + // This Windows EH type uses the Itanium LSDA encoding. + ExceptionsType == ExceptionHandling::ItaniumWinEH); } + + bool usesWindowsCFI() const { + return ExceptionsType == ExceptionHandling::ItaniumWinEH || + ExceptionsType == ExceptionHandling::MSVC; + } + bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index 3d249f93068d..d587c3ce9d54 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -19,9 +19,9 @@ namespace llvm { class MCAsmInfoDarwin : public MCAsmInfo { - virtual void anchor(); public: explicit MCAsmInfoDarwin(); + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; }; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index 27fea84e7a6d..7bd246056eca 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,6 +15,9 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); + const MCSection * + getNonexecutableStackSection(MCContext &Ctx) const override final; + protected: MCAsmInfoELF(); }; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 1cb34c2fe33b..31f29eb1f3ff 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,6 +11,8 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" @@ -593,7 +595,10 @@ private: unsigned Alignment; /// \brief Keeping track of bundle-locked state. - BundleLockStateType BundleLockState; + BundleLockStateType BundleLockState; + + /// \brief Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth; /// \brief We've seen a bundle_lock directive but not its first instruction /// yet. @@ -665,9 +670,7 @@ public: return BundleLockState; } - void setBundleLockState(BundleLockStateType NewState) { - BundleLockState = NewState; - } + void setBundleLockState(BundleLockStateType NewState); bool isBundleGroupBeforeFirstInst() const { return BundleGroupBeforeFirstInst; @@ -684,34 +687,27 @@ public: // FIXME: Same concerns as with SectionData. class MCSymbolData : public ilist_node<MCSymbolData> { -public: const MCSymbol *Symbol; - /// Fragment - The fragment this symbol's value is relative to, if any. - MCFragment *Fragment; - - /// Offset - The offset to apply to the fragment address to form this symbol's - /// value. - uint64_t Offset; - - /// IsExternal - True if this symbol is visible outside this translation - /// unit. - unsigned IsExternal : 1; + /// Fragment - The fragment this symbol's value is relative to, if any. Also + /// stores if this symbol is visible outside this translation unit (bit 0) or + /// if it is private extern (bit 1). + PointerIntPair<MCFragment *, 2> Fragment; - /// IsPrivateExtern - True if this symbol is private extern. - unsigned IsPrivateExtern : 1; + union { + /// Offset - The offset to apply to the fragment address to form this + /// symbol's value. + uint64_t Offset; - /// CommonSize - The size of the symbol, if it is 'common', or 0. - // - // FIXME: Pack this in with other fields? We could put it in offset, since a - // common symbol can never get a definition. - uint64_t CommonSize; + /// CommonSize - The size of the symbol, if it is 'common'. + uint64_t CommonSize; + }; /// SymbolSize - An expression describing how to calculate the size of /// a symbol. If a symbol has no size this field will be NULL. const MCExpr *SymbolSize; - /// CommonAlign - The alignment of the symbol, if it is 'common'. + /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. // // FIXME: Pack this in with other fields? unsigned CommonAlign; @@ -734,30 +730,41 @@ public: const MCSymbol &getSymbol() const { return *Symbol; } - MCFragment *getFragment() const { return Fragment; } - void setFragment(MCFragment *Value) { Fragment = Value; } + MCFragment *getFragment() const { return Fragment.getPointer(); } + void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } - uint64_t getOffset() const { return Offset; } - void setOffset(uint64_t Value) { Offset = Value; } + uint64_t getOffset() const { + assert(!isCommon()); + return Offset; + } + void setOffset(uint64_t Value) { + assert(!isCommon()); + Offset = Value; + } /// @} /// @name Symbol Attributes /// @{ - bool isExternal() const { return IsExternal; } - void setExternal(bool Value) { IsExternal = Value; } + bool isExternal() const { return Fragment.getInt() & 1; } + void setExternal(bool Value) { + Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); + } - bool isPrivateExtern() const { return IsPrivateExtern; } - void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + bool isPrivateExtern() const { return Fragment.getInt() & 2; } + void setPrivateExtern(bool Value) { + Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); + } /// isCommon - Is this a 'common' symbol. - bool isCommon() const { return CommonSize != 0; } + bool isCommon() const { return CommonAlign != -1U; } /// setCommon - Mark this symbol as being 'common'. /// /// \param Size - The size of the symbol. /// \param Align - The alignment of the symbol. void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); CommonSize = Size; CommonAlign = Align; } @@ -875,6 +882,8 @@ private: iplist<MCSymbolData> Symbols; + DenseSet<const MCSymbol *> LocalsUsedInReloc; + /// The map of sections to their associated assembler backend data. // // FIXME: Avoid this indirection? @@ -910,7 +919,6 @@ private: unsigned BundleAlignSize; unsigned RelaxAll : 1; - unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; /// ELF specific e_header flags @@ -975,6 +983,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, @@ -1056,9 +1067,6 @@ public: bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } - bool getNoExecStack() const { return NoExecStack; } - void setNoExecStack(bool Value) { NoExecStack = Value; } - bool isBundlingEnabled() const { return BundleAlignSize != 0; } diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index eb0340f7421a..e3163a7946a7 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -73,6 +73,10 @@ namespace llvm { /// Symbols - Bindings of names to symbols. SymbolTable Symbols; + /// ELF sections can have a corresponding symbol. This maps one to the + /// other. + DenseMap<const MCSectionELF*, MCSymbol*> SectionSymbols; + /// A maping from a local label number and an instance count to a symbol. /// For example, in the assembly /// 1: @@ -231,6 +235,10 @@ namespace llvm { MCSymbol *GetOrCreateSymbol(StringRef Name); MCSymbol *GetOrCreateSymbol(const Twine &Name); + MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// LookupSymbol - Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(StringRef Name) const; MCSymbol *LookupSymbol(const Twine &Name) const; @@ -284,6 +292,13 @@ namespace llvm { const MCSectionCOFF *getCOFFSection(StringRef Section); + /// Gets or creates a section equivalent to Sec that is associated with the + /// section containing KeySym. For example, to create a debug info section + /// associated with an inline function, pass the normal debug info section + /// as Sec and the function symbol as KeySym. + const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec, + const MCSymbol *KeySym); + /// @} /// @name Dwarf Management diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 9d441bbd88fb..d6b0a305b1da 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -10,6 +10,7 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" @@ -18,12 +19,11 @@ namespace llvm { class MCInst; class MCSubtargetInfo; -class MemoryObject; class raw_ostream; class MCContext; -/// MCDisassembler - Superclass for all disassemblers. Consumes a memory region -/// and provides an array of assembly instructions. +/// Superclass for all disassemblers. Consumes a memory region and provides an +/// array of assembly instructions. class MCDisassembler { public: /// Ternary decode status. Most backends will just use Fail and @@ -54,34 +54,31 @@ public: Success = 3 }; - /// Constructor - Performs initial setup for the disassembler. MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) : Ctx(Ctx), STI(STI), Symbolizer(), CommentStream(nullptr) {} virtual ~MCDisassembler(); - /// getInstruction - Returns the disassembly of a single instruction. + /// Returns the disassembly of a single instruction. /// - /// @param instr - An MCInst to populate with the contents of the + /// @param Instr - An MCInst to populate with the contents of the /// instruction. - /// @param size - A value to populate with the size of the instruction, or + /// @param Size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode /// an invalid instruction. - /// @param region - The memory object to use as a source for machine code. - /// @param address - The address, in the memory space of region, of the first + /// @param Address - The address, in the memory space of region, of the first /// byte of the instruction. - /// @param vStream - The stream to print warnings and diagnostic messages on. - /// @param cStream - The stream to print comments and annotations on. + /// @param VStream - The stream to print warnings and diagnostic messages on. + /// @param CStream - The stream to print comments and annotations on. /// @return - MCDisassembler::Success if the instruction is valid, /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. - virtual DecodeStatus getInstruction(MCInst& instr, - uint64_t& size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const = 0; + virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const = 0; + private: MCContext &Ctx; diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 6cd9a9a21e21..c266acf2f09c 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,16 +16,16 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" #include <map> -#include <vector> #include <string> #include <utility> +#include <vector> namespace llvm { class MCAsmBackend; @@ -457,7 +457,7 @@ public: return Offset; } - const StringRef getValues() const { + StringRef getValues() const { assert(Operation == OpEscape); return StringRef(&Values[0], Values.size()); } @@ -466,13 +466,15 @@ public: struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), - Instructions(), PersonalityEncoding(), LsdaEncoding(0), - CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} + Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), + LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), + IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; std::vector<MCCFIInstruction> Instructions; + unsigned CurrentCfaRegister; unsigned PersonalityEncoding; unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 66729fe0147e..ab6c5e3d6124 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -41,10 +41,18 @@ public: virtual ~MCELFStreamer(); + /// state management + void reset() override { + LocalCommons.clear(); + BindingExplicitlySet.clear(); + SeenIdent = false; + MCObjectStreamer::reset(); + } + /// @name MCStreamer Interface /// @{ - void InitSections() override; + void InitSections(bool NoExecStack) override; void ChangeSection(const MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; @@ -107,8 +115,7 @@ private: MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll, bool NoExecStack, - bool IsThumb); + bool RelaxAll, bool IsThumb); } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index e96ecb4be175..bd9b2bc4751a 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -19,6 +19,7 @@ class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; +class MCFixup; class MCSection; class MCSectionData; class MCStreamer; @@ -49,11 +50,17 @@ private: bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const SectionAddrMap *Addrs) const; + + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; + protected: explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, + const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet, bool ForceVarExpansion) const; @@ -87,13 +94,17 @@ public: bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const; + /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable /// value, i.e. an expression of the fixed form (a - b + constant). /// /// @param Res - The relocatable value, if evaluation succeeds. /// @param Layout - The assembler layout object to use for evaluating values. + /// @param Fixup - The Fixup object if available. /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const; + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; /// \brief Try to evaluate the expression to the form (a - b + constant) where /// neither a nor b are variables. @@ -101,7 +112,8 @@ public: /// This is a more aggressive variant of EvaluateAsRelocatable. The intended /// use is for when relocations are not available, like the symbol value in /// the symbol table. - bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const; + bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or @@ -182,6 +194,7 @@ public: VK_ARM_TARGET1, VK_ARM_TARGET2, VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) VK_ARM_TLSLDO, // symbol(tlsldo) VK_ARM_TLSCALL, // symbol(tlscall) VK_ARM_TLSDESC, // symbol(tlsdesc) @@ -238,6 +251,7 @@ public: VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld + VK_PPC_LOCAL, // symbol@local VK_Mips_GPREL, VK_Mips_GOT_CALL, @@ -270,21 +284,20 @@ public: }; private: - /// The symbol being referenced. - const MCSymbol *Symbol; - /// The symbol reference modifier. - const VariantKind Kind; + const unsigned Kind : 16; - /// MCAsmInfo that is used to print symbol variants correctly. - const MCAsmInfo *MAI; + /// Specifies how the variant kind should be printed. + const unsigned UseParensForSymbolVariant : 1; - explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind, - const MCAsmInfo *_MAI) - : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind), MAI(_MAI) { - assert(Symbol); - assert(MAI); - } + // FIXME: Remove this bit. + const unsigned HasSubsectionsViaSymbols : 1; + + /// The symbol being referenced. + const MCSymbol *Symbol; + + explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, + const MCAsmInfo *MAI); public: /// @name Construction @@ -304,9 +317,12 @@ public: /// @{ const MCSymbol &getSymbol() const { return *Symbol; } - const MCAsmInfo &getMCAsmInfo() const { return *MAI; } - VariantKind getKind() const { return Kind; } + VariantKind getKind() const { return static_cast<VariantKind>(Kind); } + + void printVariantKind(raw_ostream &OS) const; + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } /// @} /// @name Static Utility Functions @@ -524,7 +540,8 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const = 0; + const MCAsmLayout *Layout, + const MCFixup *Fixup) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual const MCSection *FindAssociatedSection() const = 0; diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 6918280a4219..25cd5ccb08fd 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -31,7 +31,7 @@ class MCInst; /// MCOperand - Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { - enum MachineOperandType { + enum MachineOperandType : unsigned char { kInvalid, ///< Uninitialized. kRegister, ///< Register operand. kImmediate, ///< Immediate operand. @@ -39,7 +39,7 @@ class MCOperand { kExpr, ///< Relocatable immediate operand. kInst ///< Sub-instruction operand. }; - unsigned char Kind; + MachineOperandType Kind; union { unsigned RegVal; @@ -172,8 +172,11 @@ public: size_t size() { return Operands.size(); } typedef SmallVectorImpl<MCOperand>::iterator iterator; + typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator; iterator begin() { return Operands.begin(); } - iterator end() { return Operands.end(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { return Operands.insert(I, Op); } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 7f55b29f8ee0..95124c3021dd 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -1,4 +1,4 @@ -//===-- MCInstPrinter.h - Convert an MCInst to target assembly syntax -----===// +//===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 5896de7f76df..360989305d3a 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -44,11 +44,12 @@ namespace MCOI { /// Operand Type - Operands are tagged with one of the values of this enum. enum OperandType { - OPERAND_UNKNOWN, - OPERAND_IMMEDIATE, - OPERAND_REGISTER, - OPERAND_MEMORY, - OPERAND_PCREL + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 }; } @@ -125,7 +126,10 @@ namespace MCID { Rematerializable, CheapAsAMove, ExtraSrcRegAllocReq, - ExtraDefRegAllocReq + ExtraDefRegAllocReq, + RegSequence, + ExtractSubreg, + InsertSubreg }; } @@ -357,6 +361,47 @@ public: return Flags & (1 << MCID::FoldableAsLoad); } + /// \brief Return true if this instruction behaves + /// the same way as the generic REG_SEQUENCE instructions. + /// E.g., on ARM, + /// dX VMOVDRR rY, rZ + /// is equivalent to + /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be + /// override accordingly. + bool isRegSequenceLike() const { return Flags & (1 << MCID::RegSequence); } + + /// \brief Return true if this instruction behaves + /// the same way as the generic EXTRACT_SUBREG instructions. + /// E.g., on ARM, + /// rX, rY VMOVRRD dZ + /// is equivalent to two EXTRACT_SUBREG: + /// rX = EXTRACT_SUBREG dZ, ssub_0 + /// rY = EXTRACT_SUBREG dZ, ssub_1 + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be + /// override accordingly. + bool isExtractSubregLike() const { + return Flags & (1 << MCID::ExtractSubreg); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic INSERT_SUBREG instructions. + /// E.g., on ARM, + /// dX = VSETLNi32 dY, rZ, Imm + /// is equivalent to a INSERT_SUBREG: + /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be + /// override accordingly. + bool isInsertSubregLike() const { + return Flags & (1 << MCID::InsertSubreg); + } + //===--------------------------------------------------------------------===// // Side Effect Analysis //===--------------------------------------------------------------------===// @@ -451,9 +496,12 @@ public: } /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is deprecated, please don't use it anymore. If this - /// flag is set, the isReallyTriviallyReMaterializable() method is called to - /// verify the instruction is really rematable. + /// remat. This flag is only used in TargetInstrInfo method + /// isTriviallyRematerializable. + /// + /// If this flag is set, the isReallyTriviallyReMaterializable() + /// or isReallyTriviallyReMaterializableGeneric methods are called to verify + /// the instruction is really rematable. bool isRematerializable() const { return Flags & (1 << MCID::Rematerializable); } @@ -464,6 +512,9 @@ public: /// where we would like to remat or hoist the instruction, but not if it costs /// more than moving the instruction into the appropriate register. Note, we /// are not marking copies from and to the same register class with this flag. + /// + /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove + /// for different subtargets. bool isAsCheapAsAMove() const { return Flags & (1 << MCID::CheapAsAMove); } diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 5104345e1abb..94d599f672af 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -22,7 +22,7 @@ namespace llvm { //===----------------------------------------------------------------------===// -/// Instruction stage - These values represent a non-pipelined step in +/// These values represent a non-pipelined step in /// the execution of an instruction. Cycles represents the number of /// discrete time slots needed to complete the stage. Units represent /// the choice of functional units that can be used to complete the @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// getCycles - returns the number of cycles the stage is occupied + /// Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// getUnits - returns the choice of FUs + /// Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,7 +81,7 @@ struct InstrStage { return Kind_; } - /// getNextCycles - returns the number of cycles from the start of + /// Returns the number of cycles from the start of /// this stage to the start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; @@ -90,10 +90,9 @@ struct InstrStage { //===----------------------------------------------------------------------===// -/// Instruction itinerary - An itinerary represents the scheduling -/// information for an instruction. This includes a set of stages -/// occupies by the instruction, and the pipeline cycle in which -/// operands are read and written. +/// An itinerary represents the scheduling information for an instruction. +/// This includes a set of stages occupied by the instruction and the pipeline +/// cycle in which operands are read and written. /// struct InstrItinerary { int NumMicroOps; ///< # of micro-ops, -1 means it's variable @@ -105,12 +104,11 @@ struct InstrItinerary { //===----------------------------------------------------------------------===// -/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be -/// used by a target. +/// Itinerary data supplied by a subtarget to be used by a target. /// class InstrItineraryData { public: - const MCSchedModel *SchedModel; ///< Basic machine properties. + MCSchedModel SchedModel; ///< Basic machine properties. const InstrStage *Stages; ///< Array of stages selected const unsigned *OperandCycles; ///< Array of operand cycles selected const unsigned *Forwardings; ///< Array of pipeline forwarding pathes @@ -118,45 +116,38 @@ public: /// Ctors. /// - InstrItineraryData() : SchedModel(&MCSchedModel::DefaultSchedModel), + InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()), Stages(nullptr), OperandCycles(nullptr), Forwardings(nullptr), Itineraries(nullptr) {} - InstrItineraryData(const MCSchedModel *SM, const InstrStage *S, + InstrItineraryData(const MCSchedModel &SM, const InstrStage *S, const unsigned *OS, const unsigned *F) : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), - Itineraries(SchedModel->InstrItineraries) {} + Itineraries(SchedModel.InstrItineraries) {} - /// isEmpty - Returns true if there are no itineraries. - /// + /// Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// isEndMarker - Returns true if the index is for the end marker - /// itinerary. - /// + /// Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && (Itineraries[ItinClassIndx].LastStage == ~0U)); } - /// beginStage - Return the first stage of the itinerary. - /// + /// Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// endStage - Return the last+1 stage of the itinerary. - /// + /// Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// getStageLatency - Return the total stage latency of the given - /// class. The latency is the maximum completion time for any stage - /// in the itinerary. - /// + /// Return the total stage latency of the given class. + /// The latency is the maximum completion time for any stage in the itinerary. /// If no stages exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple @@ -174,9 +165,8 @@ public: return Latency; } - /// getOperandCycle - Return the cycle for the given class and - /// operand. Return -1 if no cycle is specified for the operand. - /// + /// Return the cycle for the given class and operand. + /// Return -1 if no cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) return -1; @@ -189,7 +179,7 @@ public: return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// Return true if there is a pipeline forwarding /// between instructions of itinerary classes DefClass and UseClasses so that /// value produced by an instruction of itinerary class DefClass, operand /// index DefIdx can be bypassed when it's read by an instruction of @@ -212,7 +202,7 @@ public: Forwardings[FirstUseIdx + UseIdx]; } - /// getOperandLatency - Compute and return the use operand latency of a given + /// Compute and return the use operand latency of a given /// itinerary class and operand index if the value is produced by an /// instruction of the specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, @@ -236,9 +226,8 @@ public: return UseCycle; } - /// getNumMicroOps - Return the number of micro-ops that the given class - /// decodes to. Return -1 for classes that require dynamic lookup via - /// TargetInstrInfo. + /// Return the number of micro-ops that the given class decodes to. + /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) return 1; diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 50fd527ffe2a..890d6385aacd 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -18,8 +18,8 @@ #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/Support/raw_ostream.h" @@ -45,7 +45,7 @@ static inline StringRef MCLOHDirectiveName() { return StringRef(".loh"); } -static inline bool isValidMCLOHType(MCLOHType Kind) { +static inline bool isValidMCLOHType(unsigned Kind) { return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; } diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 12a7f0ee7bb5..e4681c0a3dc3 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MachO.h" #include <vector> @@ -67,12 +68,10 @@ public: /// @name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -96,15 +95,21 @@ class MachObjectWriter : public MCObjectWriter { /// @name Relocation Data /// @{ - llvm::DenseMap<const MCSectionData*, - std::vector<MachO::any_relocation_info> > Relocations; + struct RelAndSymbol { + const MCSymbolData *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap<const MCSectionData *, std::vector<RelAndSymbol>> Relocations; llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; /// @} /// @name Symbol Table Data /// @{ - SmallString<256> StringTable; + StringTableBuilder StringTable; std::vector<MachSymbolData> LocalSymbolData; std::vector<MachSymbolData> ExternalSymbolData; std::vector<MachSymbolData> UndefinedSymbolData; @@ -212,9 +217,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[SD].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -230,7 +241,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -239,8 +250,7 @@ public: /// ComputeSymbolTable - Compute the symbol table data /// - /// \param StringTable [out] - The string table data. - void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + void ComputeSymbolTable(MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &UndefinedSymbolData); diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h deleted file mode 100644 index 5b935db59585..000000000000 --- a/include/llvm/MC/MCObjectDisassembler.h +++ /dev/null @@ -1,174 +0,0 @@ -//===-- llvm/MC/MCObjectDisassembler.h --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCObjectDisassembler class, which -// can be used to construct an MCModule and an MC CFG from an ObjectFile. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H -#define LLVM_MC_MCOBJECTDISASSEMBLER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/MemoryObject.h" -#include <vector> - -namespace llvm { - -namespace object { - class ObjectFile; - class MachOObjectFile; -} - -class MCBasicBlock; -class MCDisassembler; -class MCFunction; -class MCInstrAnalysis; -class MCModule; -class MCObjectSymbolizer; - -/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. -/// This class builds on MCDisassembler to disassemble whole sections, creating -/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data). -/// It can also be used to create a control flow graph consisting of MCFunctions -/// and MCBasicBlocks. -class MCObjectDisassembler { -public: - MCObjectDisassembler(const object::ObjectFile &Obj, - const MCDisassembler &Dis, - const MCInstrAnalysis &MIA); - virtual ~MCObjectDisassembler() {} - - /// \brief Build an MCModule, creating atoms and optionally functions. - /// \param withCFG Also build a CFG by adding MCFunctions to the Module. - /// If withCFG is false, the MCModule built only contains atoms, representing - /// what was found in the object file. If withCFG is true, MCFunctions are - /// created, containing MCBasicBlocks. All text atoms are split to form basic - /// block atoms, which then each back an MCBasicBlock. - MCModule *buildModule(bool withCFG = false); - - MCModule *buildEmptyModule(); - - typedef std::vector<uint64_t> AddressSetTy; - /// \name Create a new MCFunction. - MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets); - - /// \brief Set the region on which to fallback if disassembly was requested - /// somewhere not accessible in the object file. - /// This is used for dynamic disassembly (see RawMemoryObject). - void setFallbackRegion(std::unique_ptr<MemoryObject> &Region) { - FallbackRegion.reset(Region.release()); - } - - /// \brief Set the symbolizer to use to get information on external functions. - /// Note that this isn't used to do instruction-level symbolization (that is, - /// plugged into MCDisassembler), but to symbolize function call targets. - void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { - MOS = ObjectSymbolizer; - } - - /// \brief Get the effective address of the entrypoint, or 0 if there is none. - virtual uint64_t getEntrypoint(); - - /// \name Get the addresses of static constructors/destructors in the object. - /// The caller is expected to know how to interpret the addresses; - /// for example, Mach-O init functions expect 5 arguments, not for ELF. - /// The addresses are original object file load addresses, not effective. - /// @{ - virtual ArrayRef<uint64_t> getStaticInitFunctions(); - virtual ArrayRef<uint64_t> getStaticExitFunctions(); - /// @} - - /// \name Translation between effective and objectfile load address. - /// @{ - /// \brief Compute the effective load address, from an objectfile virtual - /// address. This is implemented in a format-specific way, to take into - /// account things like PIE/ASLR when doing dynamic disassembly. - /// For example, on Mach-O this would be done by adding the VM addr slide, - /// on glibc ELF by keeping a map between segment load addresses, filled - /// using dl_iterate_phdr, etc.. - /// In most static situations and in the default impl., this returns \p Addr. - virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); - - /// \brief Compute the original load address, as specified in the objectfile. - /// This is the inverse of getEffectiveLoadAddr. - virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); - /// @} - -protected: - const object::ObjectFile &Obj; - const MCDisassembler &Dis; - const MCInstrAnalysis &MIA; - MCObjectSymbolizer *MOS; - - /// \brief The fallback memory region, outside the object file. - std::unique_ptr<MemoryObject> FallbackRegion; - - /// \brief Return a memory region suitable for reading starting at \p Addr. - /// In most cases, this returns a StringRefMemoryObject backed by the - /// containing section. When no section was found, this returns the - /// FallbackRegion, if it is suitable. - /// If it is not, or if there is no fallback region, this returns 0. - MemoryObject *getRegionFor(uint64_t Addr); - -private: - /// \brief Fill \p Module by creating an atom for each section. - /// This could be made much smarter, using information like symbols, but also - /// format-specific features, like mach-o function_start or data_in_code LCs. - void buildSectionAtoms(MCModule *Module); - - /// \brief Enrich \p Module with a CFG consisting of MCFunctions. - /// \param Module An MCModule returned by buildModule, with no CFG. - /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom. - /// When the CFG is built, contiguous instructions that were previously in a - /// single MCTextAtom will be split in multiple basic block atoms. - void buildCFG(MCModule *Module); - - MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets); -}; - -class MCMachOObjectDisassembler : public MCObjectDisassembler { - const object::MachOObjectFile &MOOF; - - uint64_t VMAddrSlide; - uint64_t HeaderLoadAddress; - - // __DATA;__mod_init_func support. - llvm::StringRef ModInitContents; - // __DATA;__mod_exit_func support. - llvm::StringRef ModExitContents; - -public: - /// \brief Construct a Mach-O specific object disassembler. - /// \param VMAddrSlide The virtual address slide applied by dyld. - /// \param HeaderLoadAddress The load address of the mach_header for this - /// object. - MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, - const MCDisassembler &Dis, - const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, - uint64_t HeaderLoadAddress); - -protected: - uint64_t getEffectiveLoadAddr(uint64_t Addr) override; - uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) override; - uint64_t getEntrypoint() override; - - ArrayRef<uint64_t> getStaticInitFunctions() override; - ArrayRef<uint64_t> getStaticExitFunctions() override; -}; - -} - -#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 4d1715eccf5a..321043c522ee 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCBJECTFILEINFO_H -#define LLVM_MC_MCBJECTFILEINFO_H +#ifndef LLVM_MC_MCOBJECTFILEINFO_H +#define LLVM_MC_MCOBJECTFILEINFO_H #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" @@ -116,6 +116,7 @@ protected: /// These are used for the Fission separate debug information files. const MCSection *DwarfInfoDWOSection; + const MCSection *DwarfTypesDWOSection; const MCSection *DwarfAbbrevDWOSection; const MCSection *DwarfStrDWOSection; const MCSection *DwarfLineDWOSection; @@ -261,7 +262,9 @@ public: return DwarfInfoDWOSection; } const MCSection *getDwarfTypesSection(uint64_t Hash) const; - const MCSection *getDwarfTypesDWOSection(uint64_t Hash) const; + const MCSection *getDwarfTypesDWOSection() const { + return DwarfTypesDWOSection; + } const MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 8d37c85b0585..0866ff5a9fc0 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCOBJECTSTREAMER_H #define LLVM_MC_MCOBJECTSTREAMER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCStreamer.h" @@ -37,11 +38,16 @@ class MCObjectStreamer : public MCStreamer { MCSectionData::iterator CurInsertionPoint; bool EmitEHFrame; bool EmitDebugFrame; + SmallVector<MCSymbolData *, 2> PendingLabels; virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; + // If any labels have been emitted but not assigned fragments, ensure that + // they get assigned, either to F if possible or to a new data fragment. + void flushPendingLabels(MCFragment *F); + protected: MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); @@ -69,14 +75,15 @@ protected: MCFragment *getCurrentFragment() const; - void insert(MCFragment *F) const { + void insert(MCFragment *F) { + flushPendingLabels(F); CurSectionData->getFragmentList().insert(CurInsertionPoint, F); F->setParent(CurSectionData); } /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. - MCDataFragment *getOrCreateDataFragment() const; + MCDataFragment *getOrCreateDataFragment(); public: void visitUsedSymbol(const MCSymbol &Sym) override; @@ -126,7 +133,7 @@ public: void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; - virtual bool mayHaveInstructions() const { + bool mayHaveInstructions() const override { return getCurrentSectionData()->hasInstructions(); } }; diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h deleted file mode 100644 index f75b7f58a141..000000000000 --- a/include/llvm/MC/MCObjectSymbolizer.h +++ /dev/null @@ -1,83 +0,0 @@ -//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is -// backed by an object::ObjectFile. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H -#define LLVM_MC_MCOBJECTSYMBOLIZER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/MC/MCSymbolizer.h" -#include "llvm/Object/ObjectFile.h" -#include <vector> - -namespace llvm { - -class MCExpr; -class MCInst; -class MCRelocationInfo; -class raw_ostream; - -/// \brief An ObjectFile-backed symbolizer. -class MCObjectSymbolizer : public MCSymbolizer { -protected: - const object::ObjectFile *Obj; - - // Map a load address to the first relocation that applies there. As far as I - // know, if there are several relocations at the exact same address, they are - // related and the others can be determined from the first that was found in - // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR - // relocation (referencing the minuend symbol) is followed by an UNSIGNED - // relocation (referencing the subtrahend symbol). - const object::RelocationRef *findRelocationAt(uint64_t Addr); - const object::SectionRef *findSectionContaining(uint64_t Addr); - - MCObjectSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo, - const object::ObjectFile *Obj); - -public: - /// \name Overridden MCSymbolizer methods: - /// @{ - bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, - int64_t Value, uint64_t Address, - bool IsBranch, uint64_t Offset, - uint64_t InstSize) override; - - void tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, - uint64_t Address) override; - /// @} - - /// \brief Look for an external function symbol at \p Addr. - /// (References through the ELF PLT, Mach-O stubs, and similar). - /// \returns An MCExpr representing the external symbol, or 0 if not found. - virtual StringRef findExternalFunctionAt(uint64_t Addr); - - /// \brief Create an object symbolizer for \p Obj. - static MCObjectSymbolizer * - createObjectSymbolizer(MCContext &Ctx, - std::unique_ptr<MCRelocationInfo> RelInfo, - const object::ObjectFile *Obj); - -private: - typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap; - typedef std::vector<object::SectionRef> SortedSectionList; - SortedSectionList SortedSections; - AddrToRelocMap AddrToReloc; - - void buildSectionList(); - void buildRelocationByAddrMap(); -}; - -} - -#endif diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c6c179..173ef416f2cc 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -76,12 +76,10 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0b550ba627e9..a9a30f172071 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -49,7 +49,7 @@ public: const AsmToken peekTok(bool ShouldSkipSpace = true) override; - bool isAtStartOfComment(char Char); + bool isAtStartOfComment(const char *Ptr); bool isAtStatementSeparator(const char *Ptr); const MCAsmInfo &getMAI() const { return MAI; } diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index e3d4181e086f..b05891c13250 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -18,7 +18,7 @@ namespace llvm { -/// AsmToken - Target independent representation for an assembler token. +/// Target independent representation for an assembler token. class AsmToken { public: enum TokenKind { @@ -74,25 +74,26 @@ public: SMLoc getLoc() const; SMLoc getEndLoc() const; + SMRange getLocRange() const; - /// getStringContents - Get the contents of a string token (without quotes). + /// Get the contents of a string token (without quotes). StringRef getStringContents() const { assert(Kind == String && "This token isn't a string!"); return Str.slice(1, Str.size() - 1); } - /// getIdentifier - Get the identifier string for the current token, which - /// should be an identifier or a string. This gets the portion of the string - /// which should be used as the identifier, e.g., it does not include the - /// quotes on strings. + /// Get the identifier string for the current token, which should be an + /// identifier or a string. This gets the portion of the string which should + /// be used as the identifier, e.g., it does not include the quotes on + /// strings. StringRef getIdentifier() const { if (Kind == Identifier) return getString(); return getStringContents(); } - /// getString - Get the string for the current token, this includes all - /// characters (for example, the quotes on strings) in the token. + /// Get the string for the current token, this includes all characters (for + /// example, the quotes on strings) in the token. /// /// The returned StringRef points into the source manager's memory buffer, and /// is safe to store across calls to Lex(). @@ -113,8 +114,8 @@ public: } }; -/// MCAsmLexer - Generic assembler lexer interface, for use by target specific -/// assembly lexers. +/// Generic assembler lexer interface, for use by target specific assembly +/// lexers. class MCAsmLexer { /// The current token, stored in the base class for faster access. AsmToken CurTok; @@ -142,7 +143,7 @@ protected: // Can only create subclasses. public: virtual ~MCAsmLexer(); - /// Lex - Consume the next token from the input stream and return it. + /// Consume the next token from the input stream and return it. /// /// The lexer will continuosly return the end-of-file token once the end of /// the main input file has been reached. @@ -152,37 +153,37 @@ public: virtual StringRef LexUntilEndOfStatement() = 0; - /// getLoc - Get the current source location. + /// Get the current source location. SMLoc getLoc() const; - /// getTok - Get the current (last) lexed token. - const AsmToken &getTok() { + /// Get the current (last) lexed token. + const AsmToken &getTok() const { return CurTok; } - /// peekTok - Look ahead at the next token to be lexed. + /// Look ahead at the next token to be lexed. virtual const AsmToken peekTok(bool ShouldSkipSpace = true) = 0; - /// getErrLoc - Get the current error location + /// Get the current error location const SMLoc &getErrLoc() { return ErrLoc; } - /// getErr - Get the current error string + /// Get the current error string const std::string &getErr() { return Err; } - /// getKind - Get the kind of current token. + /// Get the kind of current token. AsmToken::TokenKind getKind() const { return CurTok.getKind(); } - /// is - Check if the current token has kind \p K. + /// Check if the current token has kind \p K. bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } - /// isNot - Check if the current token has kind \p K. + /// Check if the current token has kind \p K. bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } - /// setSkipSpace - Set whether spaces should be ignored by the lexer + /// Set whether spaces should be ignored by the lexer void setSkipSpace(bool val) { SkipSpace = val; } bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 9836795450ff..34188e66e62d 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -45,20 +45,22 @@ public: } }; -/// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. +/// Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) = 0; + virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM, + SMLoc Location, bool Create) = 0; virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; }; -/// MCAsmParser - Generic assembler parser interface, for use by target specific -/// assembly parsers. +/// Generic assembler parser interface, for use by target specific assembly +/// parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); @@ -85,10 +87,13 @@ public: virtual SourceMgr &getSourceManager() = 0; virtual MCAsmLexer &getLexer() = 0; + const MCAsmLexer &getLexer() const { + return const_cast<MCAsmParser*>(this)->getLexer(); + } virtual MCContext &getContext() = 0; - /// getStreamer - Return the output streamer for the assembler. + /// Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -100,51 +105,49 @@ public: bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - /// Run - Run the parser on the input source buffer. + /// Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// parseMSInlineAsm - Parse ms-style inline assembly. - virtual bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl<std::pair<void *, bool> > &OpDecls, - SmallVectorImpl<std::string> &Constraints, - SmallVectorImpl<std::string> &Clobbers, - const MCInstrInfo *MII, - const MCInstPrinter *IP, - MCAsmParserSemaCallback &SI) = 0; - - /// Note - Emit a note at the location \p L, with the message \p Msg. + /// Parse ms-style inline assembly. + virtual bool parseMSInlineAsm( + void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, + SmallVectorImpl<std::string> &Constraints, + SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, + const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; + + /// Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Warning - Emit a warning at the location \p L, with the message \p Msg. + /// Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Error - Emit an error at the location \p L, with the message \p Msg. + /// Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. virtual bool Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Lex - Get the next AsmToken in the stream, possibly handling file - /// inclusion first. + /// Get the next AsmToken in the stream, possibly handling file inclusion + /// first. virtual const AsmToken &Lex() = 0; - /// getTok - Get the current AsmToken from the stream. - const AsmToken &getTok(); + /// Get the current AsmToken from the stream. + const AsmToken &getTok() const; /// \brief Report an error at the current lexer location. bool TokError(const Twine &Msg, ArrayRef<SMRange> Ranges = None); - /// parseIdentifier - Parse an identifier or string (as a quoted identifier) - /// and set \p Res to the identifier contents. + /// Parse an identifier or string (as a quoted identifier) and set \p Res to + /// the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the @@ -152,15 +155,14 @@ public: /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// parseEscapedString - Parse the current token as a string which may include - /// escaped characters and return the string contents. + /// Parse the current token as a string which may include escaped characters + /// and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// eatToEndOfStatement - Skip to the end of the current statement, for error - /// recovery. + /// Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// parseExpression - Parse an arbitrary expression. + /// Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. @@ -168,31 +170,30 @@ public: virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// parsePrimaryExpr - Parse a primary expression. + /// Parse a primary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// parseParenExpression - Parse an arbitrary expression, assuming that an - /// initial '(' has already been consumed. + /// Parse an arbitrary expression, assuming that an initial '(' has already + /// been consumed. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// parseAbsoluteExpression - Parse an expression which must evaluate to an - /// absolute value. + /// Parse an expression which must evaluate to an absolute value. /// /// @param Res - The value of the absolute expression. The result is undefined /// on error. /// @result - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// checkForValidSection - Ensure that we have a valid section set in the - /// streamer. Otherwise, report an error and switch to .text. + /// Ensure that we have a valid section set in the streamer. Otherwise, report + /// an error and switch to .text. virtual void checkForValidSection() = 0; }; diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 2eda3a9a2143..bfc0afa132b7 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -52,8 +52,17 @@ public: /// @{ MCContext &getContext() { return getParser().getContext(); } + MCAsmLexer &getLexer() { return getParser().getLexer(); } + const MCAsmLexer &getLexer() const { + return const_cast<MCAsmParserExtension *>(this)->getLexer(); + } + MCAsmParser &getParser() { return *Parser; } + const MCAsmParser &getParser() const { + return const_cast<MCAsmParserExtension*>(this)->getParser(); + } + SourceMgr &getSourceManager() { return getParser().getSourceManager(); } MCStreamer &getStreamer() { return getParser().getStreamer(); } bool Warning(SMLoc L, const Twine &Msg) { diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 766f63182925..8e25ee18e08d 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -32,9 +32,9 @@ public: typedef const MCPhysReg* iterator; typedef const MCPhysReg* const_iterator; - const char *Name; const iterator RegsBegin; const uint8_t *const RegSet; + const uint32_t NameIdx; const uint16_t RegsSize; const uint16_t RegSetSize; const uint16_t ID; @@ -46,10 +46,6 @@ public: /// unsigned getID() const { return ID; } - /// getName() - Return the register class name for debugging. - /// - const char *getName() const { return Name; } - /// begin/end - Return all of the registers in this class. /// iterator begin() const { return RegsBegin; } @@ -118,6 +114,10 @@ struct MCRegisterDesc { // RegUnits - Points to the list of register units. The low 4 bits holds the // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; }; /// MCRegisterInfo base class - We assume that the target defines a static @@ -161,7 +161,10 @@ private: unsigned NumRegUnits; // Number of regunits. const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. const MCPhysReg *DiffLists; // Pointer to the difflists array + const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. const char *RegStrings; // Pointer to the string table. + const char *RegClassStrings; // Pointer to the class strings. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered @@ -230,8 +233,10 @@ public: // These iterators are allowed to sub-class DiffListIterator and access // internal list pointers. friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; friend class MCSuperRegIterator; friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; /// \brief Initialize MCRegisterInfo, called by TableGen @@ -242,7 +247,9 @@ public: const MCPhysReg (*RURoots)[2], unsigned NRU, const MCPhysReg *DL, + const unsigned *RUMS, const char *Strings, + const char *ClassStrings, const uint16_t *SubIndices, unsigned NumIndices, const SubRegCoveredBits *SubIdxRanges, @@ -253,7 +260,9 @@ public: PCReg = PC; Classes = C; DiffLists = DL; + RegUnitMaskSequences = RUMS; RegStrings = Strings; + RegClassStrings = ClassStrings; NumClasses = NC; RegUnitRoots = RURoots; NumRegUnits = NRU; @@ -401,6 +410,10 @@ public: return Classes[i]; } + const char *getRegClassName(const MCRegisterClass *Class) const { + return RegClassStrings + Class->NameIdx; + } + /// \brief Returns the encoding for RegNo uint16_t getEncodingValue(unsigned RegNo) const { assert(RegNo < NumRegs && @@ -449,6 +462,38 @@ public: } }; +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + unsigned getSubReg() const { + return *SRIter; + } + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + /// MCSuperRegIterator enumerates all super-registers of Reg. /// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { @@ -510,6 +555,36 @@ public: } }; +/// MCRegUnitIterator enumerates a list of register units and their associated +/// lane masks for Reg. The register units are in ascending numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const unsigned *MaskListIter; +public: + MCRegUnitMaskIterator() {} + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair<unsigned,unsigned> operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + // Each register unit has one or two root registers. The complete set of // registers containing a register unit is the union of the roots and their // super-registers. All registers aliasing Unit can be visited like this: diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 43b8672265c6..1adfedd2638a 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -133,10 +133,7 @@ struct MCSchedClassDesc { /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. -class MCSchedModel { -public: - static MCSchedModel DefaultSchedModel; // For unknown processors. - +struct MCSchedModel { // IssueWidth is the maximum number of instructions that may be scheduled in // the same per-cycle group. unsigned IssueWidth; @@ -191,7 +188,6 @@ public: bool CompleteModel; -private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; const MCSchedClassDesc *SchedClassTable; @@ -201,37 +197,6 @@ private: friend class InstrItineraryData; const InstrItinerary *InstrItineraries; -public: - // Default's must be specified as static const literals so that tablegenerated - // target code can use it in static initializers. The defaults need to be - // initialized in this default ctor because some clients directly instantiate - // MCSchedModel instead of using a generated itinerary. - MCSchedModel(): IssueWidth(DefaultIssueWidth), - MicroOpBufferSize(DefaultMicroOpBufferSize), - LoopMicroOpBufferSize(DefaultLoopMicroOpBufferSize), - LoadLatency(DefaultLoadLatency), - HighLatency(DefaultHighLatency), - MispredictPenalty(DefaultMispredictPenalty), - PostRAScheduler(false), CompleteModel(true), - ProcID(0), ProcResourceTable(nullptr), - SchedClassTable(nullptr), NumProcResourceKinds(0), - NumSchedClasses(0), InstrItineraries(nullptr) { - (void)NumProcResourceKinds; - (void)NumSchedClasses; - } - - // Table-gen driven ctor. - MCSchedModel(unsigned iw, int mbs, int lmbs, unsigned ll, unsigned hl, - unsigned mp, bool postRASched, bool cm, unsigned pi, - const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, - unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MicroOpBufferSize(mbs), LoopMicroOpBufferSize(lmbs), - LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), PostRAScheduler(postRASched), - CompleteModel(cm), ProcID(pi), - ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), - NumSchedClasses(nsc), InstrItineraries(ii) {} - unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. @@ -258,6 +223,26 @@ public: assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx"); return &SchedClassTable[SchedClassIdx]; } + + // /\brief Returns a default initialized model. Used for unknown processors. + static MCSchedModel GetDefaultSchedModel() { + MCSchedModel Ret = { DefaultIssueWidth, + DefaultMicroOpBufferSize, + DefaultLoopMicroOpBufferSize, + DefaultLoadLatency, + DefaultHighLatency, + DefaultMispredictPenalty, + false, + true, + 0, + nullptr, + nullptr, + 0, + 0, + nullptr + }; + return Ret; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 63a43d08c3f2..18855f9cf03d 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -20,7 +20,7 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" -#include "llvm/MC/MCWin64EH.h" +#include "llvm/MC/MCWinEH.h" #include "llvm/Support/DataTypes.h" #include <string> @@ -49,14 +49,14 @@ typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; /// /// If target foo wants to use this, it should implement 3 classes: /// * FooTargetStreamer : public MCTargetStreamer -/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetAsmStreamer : public FooTargetStreamer /// * FooTargetELFStreamer : public FooTargetStreamer /// /// FooTargetStreamer should have a pure virtual method for each directive. For /// example, for a ".bar symbol_name" directive, it should have /// virtual emitBar(const MCSymbol &Symbol) = 0; /// -/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// The FooTargetAsmStreamer and FooTargetELFStreamer classes implement the /// method. The assembly streamer just prints ".bar symbol_name". The object /// streamer does whatever is needed to implement .bar in the object file. /// @@ -66,8 +66,9 @@ typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; /// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); /// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS); /// -/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* -/// be treated differently. Callers should always talk to a FooTargetStreamer. +/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should +/// *never* be treated differently. Callers should always talk to a +/// FooTargetStreamer. class MCTargetStreamer { protected: MCStreamer &Streamer; @@ -91,7 +92,6 @@ public: AArch64TargetStreamer(MCStreamer &S); ~AArch64TargetStreamer(); - void finish() override; /// Callback used to implement the ldr= pseudo. @@ -103,6 +103,9 @@ public: /// Emit contents of constant pool for the current section. void emitCurrentConstantPool(); + /// Callback used to implement the .inst directive. + virtual void emitInst(uint32_t Inst); + private: std::unique_ptr<AssemblerConstantPools> ConstantPools; }; @@ -181,8 +184,8 @@ class MCStreamer { MCSymbol *EmitCFICommon(); - std::vector<MCWinFrameInfo *> WinFrameInfos; - MCWinFrameInfo *CurrentWinFrameInfo; + std::vector<WinEH::FrameInfo *> WinFrameInfos; + WinEH::FrameInfo *CurrentWinFrameInfo; void EnsureValidWinFrameInfo(); // SymbolOrdering - Tracks an index to represent the order @@ -196,19 +199,14 @@ class MCStreamer { protected: MCStreamer(MCContext &Ctx); - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr *Expr); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - MCWinFrameInfo *getCurrentWinFrameInfo() { + WinEH::FrameInfo *getCurrentWinFrameInfo() { return CurrentWinFrameInfo; } - void EmitWindowsUnwindTables(); + virtual void EmitWindowsUnwindTables(); virtual void EmitRawTextImpl(StringRef String); @@ -238,7 +236,7 @@ public: } unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); } - ArrayRef<MCWinFrameInfo *> getWinFrameInfos() const { + ArrayRef<WinEH::FrameInfo *> getWinFrameInfos() const { return WinFrameInfos; } @@ -349,8 +347,8 @@ public: /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, - const MCExpr *Subsection = nullptr) { + virtual void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; @@ -373,7 +371,7 @@ public: } /// Create the default sections and set the initial one. - virtual void InitSections(); + virtual void InitSections(bool NoExecStack); /// AssignSection - Sets the symbol's section. /// @@ -552,12 +550,6 @@ public: /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); - /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO - /// this is done by producing - /// foo = value - /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size); - virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); @@ -669,11 +661,6 @@ public: StringRef FileName); virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); - - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); void EmitCFIEndProc(); @@ -782,8 +769,8 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, /// createELFStreamer - Create a machine code streamer which will generate /// ELF format object files. MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll, - bool NoExecStack); + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll); } // end namespace llvm diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 088c5e7470d6..3f38bd59a576 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCSUBTARGET_H -#define LLVM_MC_MCSUBTARGET_H +#ifndef LLVM_MC_MCSUBTARGETINFO_H +#define LLVM_MC_MCSUBTARGETINFO_H #include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/SubtargetFeature.h" @@ -36,7 +36,7 @@ class MCSubtargetInfo { const MCWriteProcResEntry *WriteProcResTable; const MCWriteLatencyEntry *WriteLatencyTable; const MCReadAdvanceEntry *ReadAdvanceTable; - const MCSchedModel *CPUSchedModel; + MCSchedModel CPUSchedModel; const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles @@ -65,6 +65,10 @@ public: return FeatureBits; } + /// setFeatureBits - Set the feature bits. + /// + void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; } + /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); @@ -82,11 +86,11 @@ public: /// getSchedModelForCPU - Get the machine model of a CPU. /// - const MCSchedModel *getSchedModelForCPU(StringRef CPU) const; + MCSchedModel getSchedModelForCPU(StringRef CPU) const; /// getSchedModel - Get the machine model for this subtarget's CPU. /// - const MCSchedModel *getSchedModel() const { return CPUSchedModel; } + const MCSchedModel &getSchedModel() const { return CPUSchedModel; } /// Return an iterator at the first process resource consumed by the given /// scheduling class. @@ -132,6 +136,15 @@ public: /// Initialize an InstrItineraryData instance. void initInstrItins(InstrItineraryData &InstrItins) const; + + /// Check whether the CPU string is valid. + bool isCPUStringValid(StringRef CPU) { + auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), + [=](const SubtargetFeatureKV &KV) { + return CPU == KV.Key; + }); + return Found != ProcDesc.end(); + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 0b3c3ceb210f..47a8789d463b 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -53,6 +53,9 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + /// IsUsed - True if this symbol has been used. mutable unsigned IsUsed : 1; @@ -61,7 +64,7 @@ namespace llvm { friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsUsed(false) {} + IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; @@ -79,6 +82,19 @@ namespace llvm { bool isUsed() const { return IsUsed; } void setUsed(bool Value) const { IsUsed = Value; } + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; + Section = nullptr; + IsRedefinable = false; + } + } + /// @} /// @name Associated Sections /// @{ diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 9a5881b14b44..ea71d1f433a4 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -7,13 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_TARGETPARSER_H -#define LLVM_MC_TARGETPARSER_H +#ifndef LLVM_MC_MCTARGETASMPARSER_H +#define LLVM_MC_MCTARGETASMPARSER_H #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" - #include <memory> namespace llvm { @@ -38,20 +37,22 @@ enum AsmRewriteKind { AOK_Input, // Rewrite in terms of $N. AOK_Output, // Rewrite in terms of $N. AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr). + AOK_Label, // Rewrite local labels. AOK_Skip // Skip emission (e.g., offset/type operators). }; const char AsmRewritePrecedence [] = { 0, // AOK_Delete - 1, // AOK_Align - 1, // AOK_DotOperator - 1, // AOK_Emit - 3, // AOK_Imm - 3, // AOK_ImmPrefix - 2, // AOK_Input - 2, // AOK_Output - 4, // AOK_SizeDirective - 1 // AOK_Skip + 2, // AOK_Align + 2, // AOK_DotOperator + 2, // AOK_Emit + 4, // AOK_Imm + 4, // AOK_ImmPrefix + 3, // AOK_Input + 3, // AOK_Output + 5, // AOK_SizeDirective + 1, // AOK_Label + 2 // AOK_Skip }; struct AsmRewrite { @@ -59,9 +60,12 @@ struct AsmRewrite { SMLoc Loc; unsigned Len; unsigned Val; + StringRef Label; public: AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0) : Kind(kind), Loc(loc), Len(len), Val(val) {} + AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label) + : Kind(kind), Loc(loc), Len(len), Val(0), Label(label) {} }; struct ParseInstructionInfo { @@ -93,7 +97,7 @@ protected: // Can only create subclasses. MCTargetAsmParser(); /// AvailableFeatures - The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm; @@ -108,12 +112,14 @@ protected: // Can only create subclasses. public: virtual ~MCTargetAsmParser(); - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool isParsingInlineAsm () { return ParsingInlineAsm; } void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + MCTargetOptions getTargetOptions() const { return MCOptions; } + void setSemaCallback(MCAsmParserSemaCallback *Callback) { SemaCallback = Callback; } @@ -121,6 +127,9 @@ public: virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// Sets frame register corresponding to the current MachineFunction. + virtual void SetFrameRegister(unsigned RegNo) {} + /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target @@ -161,7 +170,7 @@ public: /// explaining the match failure. virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) = 0; /// Allows targets to let registers opt out of clobber lists. diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index eb4348ed3ec2..ce28a196e974 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -10,8 +10,12 @@ #ifndef LLVM_MC_MCTARGETOPTIONS_H #define LLVM_MC_MCTARGETOPTIONS_H +#include <string> + namespace llvm { +class StringRef; + class MCTargetOptions { public: enum AsmInstrumentation { @@ -24,12 +28,18 @@ public: bool MCRelaxAll : 1; bool MCNoExecStack : 1; + bool MCFatalWarnings : 1; bool MCSaveTempLabels : 1; bool MCUseDwarfDirectory : 1; bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; int DwarfVersion; + /// getABIName - If this returns a non-empty string this represents the + /// textual name of the ABI that we want the backend to use, e.g. o32, or + /// aapcs-linux. + StringRef getABIName() const; + std::string ABIName; MCTargetOptions(); }; @@ -38,12 +48,14 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { return (ARE_EQUAL(SanitizeAddress) && ARE_EQUAL(MCRelaxAll) && ARE_EQUAL(MCNoExecStack) && + ARE_EQUAL(MCFatalWarnings) && ARE_EQUAL(MCSaveTempLabels) && ARE_EQUAL(MCUseDwarfDirectory) && ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && - ARE_EQUAL(DwarfVersion)); + ARE_EQUAL(DwarfVersion) && + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 6d4eb0ef5911..af23a92e6e99 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -15,8 +15,8 @@ #ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H #define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H -#include "llvm/Support/CommandLine.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; cl::opt<MCTargetOptions::AsmInstrumentation> AsmInstrumentation( @@ -40,6 +40,11 @@ cl::opt<bool> ShowMCInst("asm-show-inst", cl::desc("Emit internal instruction representation to " "assembly file")); +cl::opt<std::string> +ABIName("target-abi", cl::Hidden, + cl::desc("The name of the ABI to be targeted from the backend."), + cl::init("")); + static inline MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; Options.SanitizeAddress = @@ -47,6 +52,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { Options.MCRelaxAll = RelaxAll; Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; + Options.ABIName = ABIName; return Options; } diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h index 3df0d0ab8c46..0e81a191cd2c 100644 --- a/include/llvm/MC/MCWin64EH.h +++ b/include/llvm/MC/MCWin64EH.h @@ -20,9 +20,8 @@ #include <vector> namespace llvm { - class StringRef; - class MCStreamer; - class MCSymbol; +class MCStreamer; +class MCSymbol; namespace Win64EH { struct Instruction { @@ -52,36 +51,13 @@ struct Instruction { return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off); } }; -} - - struct MCWinFrameInfo { - MCWinFrameInfo() - : Begin(nullptr), End(nullptr),ExceptionHandler(nullptr), - Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), - HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), - ChainedParent(nullptr), Instructions() {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *ExceptionHandler; - const MCSymbol *Function; - MCSymbol *PrologEnd; - MCSymbol *Symbol; - bool HandlesUnwind; - bool HandlesExceptions; - int LastFrameInst; - MCWinFrameInfo *ChainedParent; - std::vector<WinEH::Instruction> Instructions; - }; - class MCWin64EHUnwindEmitter { - public: - static StringRef GetSectionSuffix(const MCSymbol *func); - // - // This emits the unwind info sections (.pdata and .xdata in PE/COFF). - // - static void Emit(MCStreamer &streamer); - static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info); - }; +class UnwindEmitter : public WinEH::UnwindEmitter { +public: + void Emit(MCStreamer &Streamer) const override; + void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override; +}; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 7d2d0e4f5560..57a75cec2204 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -30,10 +30,16 @@ public: MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS); + /// state management + void reset() override { + CurSymbol = nullptr; + MCObjectStreamer::reset(); + } + /// \name MCStreamer interface /// \{ - void InitSections() override; + void InitSections(bool NoExecStack) override; void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 1cd1b0f1b8ca..05b58c753b66 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -10,8 +10,14 @@ #ifndef LLVM_MC_MCWINEH_H #define LLVM_MC_MCWINEH_H +#include <vector> + namespace llvm { +class MCContext; +class MCSection; +class MCStreamer; class MCSymbol; +class StringRef; namespace WinEH { struct Instruction { @@ -23,6 +29,55 @@ struct Instruction { Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off) : Label(L), Offset(Off), Register(Reg), Operation(Op) {} }; + +struct FrameInfo { + const MCSymbol *Begin; + const MCSymbol *End; + const MCSymbol *ExceptionHandler; + const MCSymbol *Function; + const MCSymbol *PrologEnd; + const MCSymbol *Symbol; + + bool HandlesUnwind; + bool HandlesExceptions; + + int LastFrameInst; + const FrameInfo *ChainedParent; + std::vector<Instruction> Instructions; + + FrameInfo() + : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr), + Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(nullptr), Instructions() {} + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) + : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), + Function(Function), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(nullptr), Instructions() {} + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, + const FrameInfo *ChainedParent) + : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), + Function(Function), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(ChainedParent), Instructions() {} +}; + +class UnwindEmitter { +public: + static const MCSection *getPDataSection(const MCSymbol *Function, + MCContext &Context); + static const MCSection *getXDataSection(const MCSymbol *Function, + MCContext &Context); + + virtual ~UnwindEmitter() { } + + // + // This emits the unwind info sections (.pdata and .xdata in PE/COFF). + // + virtual void Emit(MCStreamer &Streamer) const = 0; + virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0; +}; } } diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h index 065e9e06e2c9..897d449254ea 100644 --- a/include/llvm/MC/StringTableBuilder.h +++ b/include/llvm/MC/StringTableBuilder.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_STRINGTABLE_BUILDER_H -#define LLVM_MC_STRINGTABLE_BUILDER_H +#ifndef LLVM_MC_STRINGTABLEBUILDER_H +#define LLVM_MC_STRINGTABLEBUILDER_H #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" @@ -26,12 +26,18 @@ public: /// copy of s. Can only be used before the table is finalized. StringRef add(StringRef s) { assert(!isFinalized()); - return StringIndexMap.GetOrCreateValue(s, 0).getKey(); + return StringIndexMap.insert(std::make_pair(s, 0)).first->first(); } + enum Kind { + ELF, + WinCOFF, + MachO + }; + /// \brief Analyze the strings and build the final table. No more strings can /// be added after this point. - void finalize(); + void finalize(Kind kind); /// \brief Retrieve the string table data. Can only be used after the table /// is finalized. @@ -48,6 +54,8 @@ public: return StringIndexMap[s]; } + void clear(); + private: bool isFinalized() { return !StringTable.empty(); diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index c5d62a6cbae8..bfecb8ba6ab0 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -72,21 +72,21 @@ struct SubtargetInfoKV { class SubtargetFeatures { std::vector<std::string> Features; // Subtarget features as a vector public: - explicit SubtargetFeatures(const StringRef Initial = ""); + explicit SubtargetFeatures(StringRef Initial = ""); /// Features string accessors. std::string getString() const; /// Adding Features. - void AddFeature(const StringRef String); + void AddFeature(StringRef String); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. - uint64_t ToggleFeature(uint64_t Bits, const StringRef String, + uint64_t ToggleFeature(uint64_t Bits, StringRef String, ArrayRef<SubtargetFeatureKV> FeatureTable); /// Get feature bits of a CPU. - uint64_t getFeatureBits(const StringRef CPU, + uint64_t getFeatureBits(StringRef CPU, ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> FeatureTable); diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index af6c995c1d05..4e96205a93ba 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_ARCHIVE_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -83,14 +84,13 @@ public: return getHeader()->getAccessMode(); } /// \return the size of the archive member without the header or padding. - uint64_t getSize() const { return Data.size() - StartOfFile; } + uint64_t getSize() const; StringRef getBuffer() const { return StringRef(Data.data() + StartOfFile, getSize()); } - ErrorOr<std::unique_ptr<MemoryBuffer>> - getMemoryBuffer(bool FullPath = false) const; + ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; ErrorOr<std::unique_ptr<Binary>> getAsBinary(LLVMContext *Context = nullptr) const; @@ -98,12 +98,12 @@ public: class child_iterator { Child child; + public: child_iterator() : child(Child(nullptr, nullptr)) {} child_iterator(const Child &c) : child(c) {} - const Child* operator->() const { - return &child; - } + const Child *operator->() const { return &child; } + const Child &operator*() const { return child; } bool operator==(const child_iterator &other) const { return child == other.child; @@ -113,11 +113,11 @@ public: return !(*this == other); } - bool operator <(const child_iterator &other) const { + bool operator<(const child_iterator &other) const { return child < other.child; } - child_iterator& operator++() { // Preincrement + child_iterator &operator++() { // Preincrement child = child.getNext(); return *this; } @@ -164,8 +164,8 @@ public: } }; - Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &EC); - static ErrorOr<Archive *> create(std::unique_ptr<MemoryBuffer> Source); + Archive(MemoryBufferRef Source, std::error_code &EC); + static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source); enum Kind { K_GNU, @@ -173,12 +173,14 @@ public: K_COFF }; - Kind kind() const { - return Format; - } + Kind kind() const { return (Kind)Format; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; + iterator_range<child_iterator> children(bool SkipInternal = true) const { + return iterator_range<child_iterator>(child_begin(SkipInternal), + child_end()); + } symbol_iterator symbol_begin() const; symbol_iterator symbol_end() const; @@ -197,7 +199,8 @@ private: child_iterator SymbolTable; child_iterator StringTable; child_iterator FirstRegular; - Kind Format; + unsigned Format : 2; + unsigned IsThin : 1; }; } diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 91984cb52715..4b2b7e6835cc 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -17,11 +17,11 @@ #include "llvm/Object/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" namespace llvm { class LLVMContext; -class MemoryBuffer; class StringRef; namespace object { @@ -34,9 +34,9 @@ private: unsigned int TypeID; protected: - std::unique_ptr<MemoryBuffer> Data; + MemoryBufferRef Data; - Binary(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); + Binary(unsigned int Type, MemoryBufferRef Source); enum { ID_Archive, @@ -78,8 +78,8 @@ public: virtual ~Binary(); StringRef getData() const; - MemoryBuffer *releaseBuffer() { return Data.release(); } StringRef getFileName() const; + MemoryBufferRef getMemoryBufferRef() const; // Cast methods. unsigned int getType() const { return TypeID; } @@ -126,10 +126,58 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. -ErrorOr<Binary *> createBinary(std::unique_ptr<MemoryBuffer> Source, - LLVMContext *Context = nullptr); +ErrorOr<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, + LLVMContext *Context = nullptr); -ErrorOr<Binary *> createBinary(StringRef Path); +template <typename T> class OwningBinary { + std::unique_ptr<T> Bin; + std::unique_ptr<MemoryBuffer> Buf; + +public: + OwningBinary(); + OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf); + OwningBinary(OwningBinary<T>&& Other); + OwningBinary<T> &operator=(OwningBinary<T> &&Other); + + std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary(); + + T* getBinary(); + const T* getBinary() const; +}; + +template <typename T> +OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin, + std::unique_ptr<MemoryBuffer> Buf) + : Bin(std::move(Bin)), Buf(std::move(Buf)) {} + +template <typename T> OwningBinary<T>::OwningBinary() {} + +template <typename T> +OwningBinary<T>::OwningBinary(OwningBinary &&Other) + : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {} + +template <typename T> +OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) { + Bin = std::move(Other.Bin); + Buf = std::move(Other.Buf); + return *this; +} + +template <typename T> +std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> +OwningBinary<T>::takeBinary() { + return std::make_pair(std::move(Bin), std::move(Buf)); +} + +template <typename T> T* OwningBinary<T>::getBinary() { + return Bin.get(); +} + +template <typename T> const T* OwningBinary<T>::getBinary() const { + return Bin.get(); +} + +ErrorOr<OwningBinary<Binary>> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index e2da070d47bd..522bf68c6cbd 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -14,22 +14,31 @@ #ifndef LLVM_OBJECT_COFF_H #define LLVM_OBJECT_COFF_H +#include "llvm/ADT/PointerUnion.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorOr.h" namespace llvm { template <typename T> class ArrayRef; namespace object { class ImportDirectoryEntryRef; +class DelayImportDirectoryEntryRef; class ExportDirectoryEntryRef; +class ImportedSymbolRef; +class BaseRelocRef; typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; +typedef content_iterator<DelayImportDirectoryEntryRef> + delay_import_directory_iterator; typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator; +typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator; +typedef content_iterator<BaseRelocRef> base_reloc_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { - support::ulittle16_t Magic; + char Magic[2]; support::ulittle16_t UsedBytesInTheLastPage; support::ulittle16_t FileSizeInPages; support::ulittle16_t NumberOfRelocationItems; @@ -62,6 +71,22 @@ struct coff_file_header { bool isImportLibrary() const { return NumberOfSections == 0xffff; } }; +struct coff_bigobj_file_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + uint8_t UUID[16]; + support::ulittle32_t unused1; + support::ulittle32_t unused2; + support::ulittle32_t unused3; + support::ulittle32_t unused4; + support::ulittle32_t NumberOfSections; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; +}; + /// The 32-bit PE header that follows the COFF header. struct pe32_header { support::ulittle16_t Magic; @@ -87,12 +112,14 @@ struct pe32_header { support::ulittle32_t SizeOfHeaders; support::ulittle32_t CheckSum; support::ulittle16_t Subsystem; + // FIXME: This should be DllCharacteristics. support::ulittle16_t DLLCharacteristics; support::ulittle32_t SizeOfStackReserve; support::ulittle32_t SizeOfStackCommit; support::ulittle32_t SizeOfHeapReserve; support::ulittle32_t SizeOfHeapCommit; support::ulittle32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes. support::ulittle32_t NumberOfRvaAndSize; }; @@ -142,22 +169,40 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; -struct import_lookup_table_entry32 { - support::ulittle32_t data; +template <typename IntTy> +struct import_lookup_table_entry { + IntTy Data; - bool isOrdinal() const { return data & 0x80000000; } + bool isOrdinal() const { return Data < 0; } uint16_t getOrdinal() const { assert(isOrdinal() && "ILT entry is not an ordinal!"); - return data & 0xFFFF; + return Data & 0xFFFF; } uint32_t getHintNameRVA() const { assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); - return data; + return Data & 0xFFFFFFFF; } }; +typedef import_lookup_table_entry<support::little32_t> + import_lookup_table_entry32; +typedef import_lookup_table_entry<support::little64_t> + import_lookup_table_entry64; + +struct delay_import_directory_table_entry { + // dumpbin reports this field as "Characteristics" instead of "Attributes". + support::ulittle32_t Attributes; + support::ulittle32_t Name; + support::ulittle32_t ModuleHandle; + support::ulittle32_t DelayImportAddressTable; + support::ulittle32_t DelayImportNameTable; + support::ulittle32_t BoundDelayImportTable; + support::ulittle32_t UnloadDelayImportTable; + support::ulittle32_t TimeStamp; +}; + struct export_directory_table_entry { support::ulittle32_t ExportFlags; support::ulittle32_t TimeDateStamp; @@ -180,67 +225,156 @@ union export_address_table_entry { typedef support::ulittle32_t export_name_pointer_table_entry; typedef support::ulittle16_t export_ordinal_table_entry; -struct coff_symbol { - struct StringTableOffset { - support::ulittle32_t Zeroes; - support::ulittle32_t Offset; - }; +struct StringTableOffset { + support::ulittle32_t Zeroes; + support::ulittle32_t Offset; +}; +template <typename SectionNumberType> +struct coff_symbol { union { - char ShortName[8]; + char ShortName[COFF::NameSize]; StringTableOffset Offset; } Name; support::ulittle32_t Value; - support::ulittle16_t SectionNumber; + SectionNumberType SectionNumber; support::ulittle16_t Type; - support::ulittle8_t StorageClass; - support::ulittle8_t NumberOfAuxSymbols; + uint8_t StorageClass; + uint8_t NumberOfAuxSymbols; +}; + +typedef coff_symbol<support::ulittle16_t> coff_symbol16; +typedef coff_symbol<support::ulittle32_t> coff_symbol32; + +class COFFSymbolRef { +public: + COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {} + COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {} + COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {} + + const void *getRawPtr() const { + return CS16 ? static_cast<const void *>(CS16) : CS32; + } + + friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { + return A.getRawPtr() < B.getRawPtr(); + } + + bool isBigObj() const { + if (CS16) + return false; + if (CS32) + return true; + llvm_unreachable("COFFSymbolRef points to nothing!"); + } + + const char *getShortName() const { + return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; + } + + const StringTableOffset &getStringTableOffset() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Name.Offset : CS32->Name.Offset; + } + + uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } + + int32_t getSectionNumber() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + if (CS16) { + // Reserved sections are returned as negative numbers. + if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) + return CS16->SectionNumber; + return static_cast<int16_t>(CS16->SectionNumber); + } + return static_cast<int32_t>(CS32->SectionNumber); + } + + uint16_t getType() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Type : CS32->Type; + } + + uint8_t getStorageClass() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->StorageClass : CS32->StorageClass; + } + + uint8_t getNumberOfAuxSymbols() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; + } + + uint8_t getBaseType() const { return getType() & 0x0F; } - uint8_t getBaseType() const { return Type & 0x0F; } + uint8_t getComplexType() const { + return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; + } + + bool isExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; + } + + bool isCommon() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() != 0; + } + + bool isUndefined() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() == 0; + } - uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } + bool isWeakExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + } bool isFunctionDefinition() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && - !COFF::isReservedSectionNumber(SectionNumber); + !COFF::isReservedSectionNumber(getSectionNumber()); } bool isFunctionLineInfo() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; } - bool isWeakExternal() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || - (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); + bool isAnyUndefined() const { + return isUndefined() || isWeakExternal(); } bool isFileRecord() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; } bool isSectionDefinition() const { // C++/CLI creates external ABS symbols for non-const appdomain globals. // These are also followed by an auxiliary section definition. - bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; - bool isOrdinarySection = - StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; + bool isAppdomainGlobal = + getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; + if (!getNumberOfAuxSymbols()) + return false; return isAppdomainGlobal || isOrdinarySection; } bool isCLRToken() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; } + +private: + bool isSet() const { return CS16 || CS32; } + + const coff_symbol16 *CS16; + const coff_symbol32 *CS32; }; struct coff_section { - char Name[8]; + char Name[COFF::NameSize]; support::ulittle32_t VirtualSize; support::ulittle32_t VirtualAddress; support::ulittle32_t SizeOfRawData; @@ -254,9 +388,9 @@ struct coff_section { // Returns true if the actual number of relocations is stored in // VirtualAddress field of the first relocation table entry. bool hasExtendedRelocations() const { - return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL && - NumberOfRelocations == UINT16_MAX; - }; + return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && + NumberOfRelocations == UINT16_MAX; + } }; struct coff_relocation { @@ -270,7 +404,6 @@ struct coff_aux_function_definition { support::ulittle32_t TotalSize; support::ulittle32_t PointerToLinenumber; support::ulittle32_t PointerToNextFunction; - char Unused[2]; }; struct coff_aux_bf_and_ef_symbol { @@ -278,17 +411,11 @@ struct coff_aux_bf_and_ef_symbol { support::ulittle16_t Linenumber; char Unused2[6]; support::ulittle32_t PointerToNextFunction; - char Unused3[2]; }; struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; - char Unused[10]; -}; - -struct coff_aux_file { - char FileName[18]; }; struct coff_aux_section_definition { @@ -296,16 +423,22 @@ struct coff_aux_section_definition { support::ulittle16_t NumberOfRelocations; support::ulittle16_t NumberOfLinenumbers; support::ulittle32_t CheckSum; - support::ulittle16_t Number; - support::ulittle8_t Selection; - char Unused[3]; + support::ulittle16_t NumberLowPart; + uint8_t Selection; + uint8_t Unused; + support::ulittle16_t NumberHighPart; + int32_t getNumber(bool IsBigObj) const { + uint32_t Number = static_cast<uint32_t>(NumberLowPart); + if (IsBigObj) + Number |= static_cast<uint32_t>(NumberHighPart) << 16; + return static_cast<int32_t>(Number); + } }; struct coff_aux_clr_token { - support::ulittle8_t AuxType; - support::ulittle8_t Reserved; + uint8_t AuxType; + uint8_t Reserved; support::ulittle32_t SymbolTableIndex; - char Unused[12]; }; struct coff_load_configuration32 { @@ -324,7 +457,7 @@ struct coff_load_configuration32 { support::ulittle32_t ProcessAffinityMask; support::ulittle32_t ProcessHeapFlags; support::ulittle16_t CSDVersion; - uint16_t Reserved; + support::ulittle16_t Reserved; support::ulittle32_t EditList; support::ulittle32_t SecurityCookie; support::ulittle32_t SEHandlerTable; @@ -337,32 +470,114 @@ struct coff_runtime_function_x64 { support::ulittle32_t UnwindInformation; }; +struct coff_base_reloc_block_header { + support::ulittle32_t PageRVA; + support::ulittle32_t BlockSize; +}; + +struct coff_base_reloc_block_entry { + support::ulittle16_t Data; + int getType() const { return Data >> 12; } + int getOffset() const { return Data & ((1 << 12) - 1); } +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; friend class ExportDirectoryEntryRef; const coff_file_header *COFFHeader; + const coff_bigobj_file_header *COFFBigObjHeader; const pe32_header *PE32Header; const pe32plus_header *PE32PlusHeader; const data_directory *DataDirectory; const coff_section *SectionTable; - const coff_symbol *SymbolTable; + const coff_symbol16 *SymbolTable16; + const coff_symbol32 *SymbolTable32; const char *StringTable; uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; uint32_t NumberOfImportDirectory; + const delay_import_directory_table_entry *DelayImportDirectory; + uint32_t NumberOfDelayImportDirectory; const export_directory_table_entry *ExportDirectory; + const coff_base_reloc_block_header *BaseRelocHeader; + const coff_base_reloc_block_header *BaseRelocEnd; std::error_code getString(uint32_t offset, StringRef &Res) const; - const coff_symbol *toSymb(DataRefImpl Symb) const; + template <typename coff_symbol_type> + const coff_symbol_type *toSymb(DataRefImpl Symb) const; const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; std::error_code initSymbolTablePtr(); std::error_code initImportTablePtr(); + std::error_code initDelayImportTablePtr(); std::error_code initExportTablePtr(); + std::error_code initBaseRelocPtr(); +public: + uintptr_t getSymbolTable() const { + if (SymbolTable16) + return reinterpret_cast<uintptr_t>(SymbolTable16); + if (SymbolTable32) + return reinterpret_cast<uintptr_t>(SymbolTable32); + return uintptr_t(0); + } + uint16_t getMachine() const { + if (COFFHeader) + return COFFHeader->Machine; + if (COFFBigObjHeader) + return COFFBigObjHeader->Machine; + llvm_unreachable("no COFF header!"); + } + uint16_t getSizeOfOptionalHeader() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->SizeOfOptionalHeader; + // bigobj doesn't have this field. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + uint16_t getCharacteristics() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; + // bigobj doesn't have characteristics to speak of, + // editbin will silently lie to you if you attempt to set any. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + uint32_t getTimeDateStamp() const { + if (COFFHeader) + return COFFHeader->TimeDateStamp; + if (COFFBigObjHeader) + return COFFBigObjHeader->TimeDateStamp; + llvm_unreachable("no COFF header!"); + } + uint32_t getNumberOfSections() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSections; + llvm_unreachable("no COFF header!"); + } + uint32_t getPointerToSymbolTable() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->PointerToSymbolTable; + if (COFFBigObjHeader) + return COFFBigObjHeader->PointerToSymbolTable; + llvm_unreachable("no COFF header!"); + } + uint32_t getNumberOfSymbols() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSymbols; + llvm_unreachable("no COFF header!"); + } protected: void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code getSymbolName(DataRefImpl Symb, @@ -378,24 +593,16 @@ protected: void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -414,54 +621,93 @@ protected: getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const override; - std::error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const override; - std::error_code getLibraryPath(DataRefImpl LibData, - StringRef &Result) const override; - public: - COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC); + COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; section_iterator section_begin() const override; section_iterator section_end() const override; const coff_section *getCOFFSection(const SectionRef &Section) const; - const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const; + COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; + COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const override; import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; + delay_import_directory_iterator delay_import_directory_begin() const; + delay_import_directory_iterator delay_import_directory_end() const; export_directory_iterator export_directory_begin() const; export_directory_iterator export_directory_end() const; - - std::error_code getHeader(const coff_file_header *&Res) const; - std::error_code getCOFFHeader(const coff_file_header *&Res) const; + base_reloc_iterator base_reloc_begin() const; + base_reloc_iterator base_reloc_end() const; + + iterator_range<import_directory_iterator> import_directories() const; + iterator_range<delay_import_directory_iterator> + delay_import_directories() const; + iterator_range<export_directory_iterator> export_directories() const; + iterator_range<base_reloc_iterator> base_relocs() const; + + const dos_header *getDOSHeader() const { + if (!PE32Header && !PE32PlusHeader) + return nullptr; + return reinterpret_cast<const dos_header *>(base()); + } std::error_code getPE32Header(const pe32_header *&Res) const; std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; std::error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; std::error_code getSection(int32_t index, const coff_section *&Res) const; - std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; + template <typename coff_symbol_type> + std::error_code getSymbol(uint32_t Index, + const coff_symbol_type *&Res) const { + if (Index >= getNumberOfSymbols()) + return object_error::parse_failed; + + Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; + return object_error::success; + } + ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { + if (SymbolTable16) { + const coff_symbol16 *Symb = nullptr; + if (std::error_code EC = getSymbol(index, Symb)) + return EC; + return COFFSymbolRef(Symb); + } + if (SymbolTable32) { + const coff_symbol32 *Symb = nullptr; + if (std::error_code EC = getSymbol(index, Symb)) + return EC; + return COFFSymbolRef(Symb); + } + return object_error::parse_failed; + } template <typename T> std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { - const coff_symbol *s; - std::error_code ec = getSymbol(index, s); - Res = reinterpret_cast<const T *>(s); - return ec; + ErrorOr<COFFSymbolRef> s = getSymbol(index); + if (std::error_code EC = s.getError()) + return EC; + Res = reinterpret_cast<const T *>(s->getRawPtr()); + return object_error::success; + } + std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; + + ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; + + size_t getSymbolTableEntrySize() const { + if (COFFHeader) + return sizeof(coff_symbol16); + if (COFFBigObjHeader) + return sizeof(coff_symbol32); + llvm_unreachable("null symbol table pointer!"); } - std::error_code getSymbolName(const coff_symbol *symbol, - StringRef &Res) const; - ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; + uint64_t getSectionSize(const coff_section *Sec) const; std::error_code getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const; @@ -470,6 +716,9 @@ public: std::error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + bool isRelocatableObject() const override; + bool is64() const { return PE32PlusHeader; } + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; @@ -483,7 +732,14 @@ public: bool operator==(const ImportDirectoryEntryRef &Other) const; void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range<imported_symbol_iterator> imported_symbols() const; + std::error_code getName(StringRef &Result) const; + std::error_code getImportLookupTableRVA(uint32_t &Result) const; + std::error_code getImportAddressTableRVA(uint32_t &Result) const; std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; @@ -497,6 +753,31 @@ private: const COFFObjectFile *OwningObject; }; +class DelayImportDirectoryEntryRef { +public: + DelayImportDirectoryEntryRef() : OwningObject(nullptr) {} + DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, + uint32_t I, const COFFObjectFile *Owner) + : Table(T), Index(I), OwningObject(Owner) {} + + bool operator==(const DelayImportDirectoryEntryRef &Other) const; + void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range<imported_symbol_iterator> imported_symbols() const; + + std::error_code getName(StringRef &Result) const; + std::error_code getDelayImportTable( + const delay_import_directory_table_entry *&Result) const; + std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; + +private: + const delay_import_directory_table_entry *Table; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + // The iterator for the export directory table entry. class ExportDirectoryEntryRef { public: @@ -519,6 +800,49 @@ private: uint32_t Index; const COFFObjectFile *OwningObject; }; + +class ImportedSymbolRef { +public: + ImportedSymbolRef() : OwningObject(nullptr) {} + ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} + ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} + + bool operator==(const ImportedSymbolRef &Other) const; + void moveNext(); + + std::error_code getSymbolName(StringRef &Result) const; + std::error_code getOrdinal(uint16_t &Result) const; + +private: + const import_lookup_table_entry32 *Entry32; + const import_lookup_table_entry64 *Entry64; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + +class BaseRelocRef { +public: + BaseRelocRef() : OwningObject(nullptr) {} + BaseRelocRef(const coff_base_reloc_block_header *Header, + const COFFObjectFile *Owner) + : Header(Header), Index(0), OwningObject(Owner) {} + + bool operator==(const BaseRelocRef &Other) const; + void moveNext(); + + std::error_code getType(uint8_t &Type) const; + std::error_code getRVA(uint32_t &Result) const; + +private: + const coff_base_reloc_block_header *Header; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + } // end namespace object } // end namespace llvm diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 4aba08f75ddc..12a25223bd37 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -31,6 +31,12 @@ inline SectionCharacteristics operator|(SectionCharacteristics a, uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b); return static_cast<SectionCharacteristics>(Ret); } + +inline DLLCharacteristics operator|(DLLCharacteristics a, + DLLCharacteristics b) { + uint16_t Ret = static_cast<uint16_t>(a) | static_cast<uint16_t>(b); + return static_cast<DLLCharacteristics>(Ret); +} } // The structure of the yaml files is not an exact 1:1 match to COFF. In order @@ -69,7 +75,13 @@ namespace COFFYAML { Symbol(); }; + struct PEHeader { + COFF::PE32Header Header; + Optional<COFF::DataDirectory> DataDirectories[COFF::NUM_DATA_DIRECTORIES]; + }; + struct Object { + Optional<PEHeader> OptionalHeader; COFF::header Header; std::vector<Section> Sections; std::vector<Symbol> Symbols; @@ -131,6 +143,11 @@ struct ScalarEnumerationTraits<COFF::RelocationTypeAMD64> { }; template <> +struct ScalarEnumerationTraits<COFF::WindowsSubsystem> { + static void enumeration(IO &IO, COFF::WindowsSubsystem &Value); +}; + +template <> struct ScalarBitSetTraits<COFF::Characteristics> { static void bitset(IO &IO, COFF::Characteristics &Value); }; @@ -141,11 +158,26 @@ struct ScalarBitSetTraits<COFF::SectionCharacteristics> { }; template <> +struct ScalarBitSetTraits<COFF::DLLCharacteristics> { + static void bitset(IO &IO, COFF::DLLCharacteristics &Value); +}; + +template <> struct MappingTraits<COFFYAML::Relocation> { static void mapping(IO &IO, COFFYAML::Relocation &Rel); }; template <> +struct MappingTraits<COFFYAML::PEHeader> { + static void mapping(IO &IO, COFFYAML::PEHeader &PH); +}; + +template <> +struct MappingTraits<COFF::DataDirectory> { + static void mapping(IO &IO, COFF::DataDirectory &DD); +}; + +template <> struct MappingTraits<COFF::header> { static void mapping(IO &IO, COFF::header &H); }; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index fbc48e6d7218..7c10bbf6e5ab 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -540,7 +540,7 @@ ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { if (Sec->sh_offset + Sec->sh_size > Buf.size()) return object_error::parse_failed; const uint8_t *Start = base() + Sec->sh_offset; - return ArrayRef<uint8_t>(Start, Sec->sh_size); + return makeArrayRef(Start, Sec->sh_size); } template <class ELFT> diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 069f38112def..c2d6438f45ba 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H -#define LLVM_OBJECT_ELF_OBJECT_FILE_H +#ifndef LLVM_OBJECT_ELFOBJECTFILE_H +#define LLVM_OBJECT_ELFOBJECTFILE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -35,8 +35,26 @@ namespace llvm { namespace object { -template <class ELFT> -class ELFObjectFile : public ObjectFile { +class ELFObjectFileBase : public ObjectFile { +protected: + ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + +public: + virtual std::error_code getRelocationAddend(DataRefImpl Rel, + int64_t &Res) const = 0; + virtual std::pair<symbol_iterator, symbol_iterator> + getELFDynamicSymbolIterators() const = 0; + + virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const = 0; + + virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; + virtual uint32_t getSectionType(SectionRef Sec) const = 0; + + static inline bool classof(const Binary *v) { return v->isELF(); } +}; + +template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -71,32 +89,19 @@ protected: std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; - std::error_code getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const override; - std::error_code getLibraryPath(DataRefImpl Data, - StringRef &Res) const override; - void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; @@ -178,7 +183,7 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC); + ELFObjectFile(MemoryBufferRef Object, std::error_code &EC); const Elf_Sym *getSymbol(DataRefImpl Symb) const; @@ -191,17 +196,18 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; - - std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + std::error_code getRelocationAddend(DataRefImpl Rel, + int64_t &Res) const override; std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; + bool &IsDefault) const override; + + uint64_t getSectionFlags(SectionRef Sec) const override; + uint32_t getSectionType(SectionRef Sec) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const override; + StringRef getLoadName() const; std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; @@ -215,6 +221,11 @@ public: return v->getType() == getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits); } + + std::pair<symbol_iterator, symbol_iterator> + getELFDynamicSymbolIterators() const override; + + bool isRelocatableObject() const override; }; // Use an alignment of 2 for the typedefs since that is the worst case for @@ -254,6 +265,18 @@ std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, } template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionFlags(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_flags; +} + +template <class ELFT> +uint32_t ELFObjectFile<ELFT>::getSectionType(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_type; +} + +template <class ELFT> std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); @@ -272,8 +295,9 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, const Elf_Ehdr *Header = EF.getHeader(); Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) + // Clear the ARM/Thumb or microMIPS indicator flag. + if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + ESym->getType() == ELF::STT_FUNC) Result &= ~1; if (Header->e_type == ELF::ET_REL) @@ -400,17 +424,13 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_addr; - return object_error::success; +uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_addr; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_size; - return object_error::success; +uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_size; } template <class ELFT> @@ -423,79 +443,43 @@ ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, } template <class ELFT> -std::error_code -ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_addralign; - return object_error::success; +uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_addralign; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; - return object_error::success; +bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, - bool &Result) const { +bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_PROGBITS; - return object_error::success; + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template <class ELFT> -std::error_code -ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; - return object_error::success; + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; +bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template <class ELFT> -std::error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); - return object_error::success; -} - -template <class ELFT> -std::error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +bool ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); uintX_t Index = ESym->st_shndx; bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; - Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); - return object_error::success; + return !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); } template <class ELFT> @@ -754,6 +738,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationValueString( Result.append(fmtbuf.begin(), fmtbuf.end()); break; } + case ELF::EM_386: case ELF::EM_ARM: case ELF::EM_HEXAGON: case ELF::EM_MIPS: @@ -786,13 +771,13 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { } template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, - std::error_code &EC) - : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == - support::little, - ELFT::Is64Bits), - std::move(Object)), - EF(Data->getBuffer(), EC) {} +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) + : ELFObjectFileBase( + getELFType(static_cast<endianness>(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Data.getBuffer(), EC) {} template <class ELFT> basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const { @@ -838,50 +823,13 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const { } template <class ELFT> -library_iterator ELFObjectFile<ELFT>::needed_library_begin() const { - Elf_Dyn_Iter DI = EF.begin_dynamic_table(); - Elf_Dyn_Iter DE = EF.end_dynamic_table(); - - while (DI != DE && DI->getTag() != ELF::DT_SONAME) - ++DI; - - return library_iterator(LibraryRef(toDRI(DI), this)); -} - -template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { - Elf_Dyn_Iter DI = toELFDynIter(Data); - Elf_Dyn_Iter DE = EF.end_dynamic_table(); - - // Skip to the next DT_NEEDED entry. - do - ++DI; - while (DI != DE && DI->getTag() != ELF::DT_NEEDED); - - Result = LibraryRef(toDRI(DI), this); - return object_error::success; -} - -template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { - Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); - return object_error::success; -} - -template <class ELFT> -library_iterator ELFObjectFile<ELFT>::needed_library_end() const { - return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); -} - -template <class ELFT> uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { return ELFT::Is64Bits ? 8 : 4; } template <class ELFT> StringRef ELFObjectFile<ELFT>::getFileFormatName() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader()->e_machine) { @@ -890,7 +838,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_X86_64: return "ELF32-x86-64"; case ELF::EM_ARM: - return "ELF32-arm"; + return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big"); case ELF::EM_HEXAGON: return "ELF32-hexagon"; case ELF::EM_MIPS: @@ -910,7 +858,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_X86_64: return "ELF64-x86-64"; case ELF::EM_AARCH64: - return "ELF64-aarch64"; + return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big"); case ELF::EM_PPC64: return "ELF64-ppc64"; case ELF::EM_S390: @@ -951,6 +899,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { default: report_fatal_error("Invalid ELFCLASS!"); } + case ELF::EM_PPC: + return Triple::ppc; case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: @@ -967,73 +917,34 @@ unsigned ELFObjectFile<ELFT>::getArch() const { } } -/// FIXME: Maybe we should have a base ElfObjectFile that is not a template -/// and make these member functions? +template <class ELFT> +std::pair<symbol_iterator, symbol_iterator> +ELFObjectFile<ELFT>::getELFDynamicSymbolIterators() const { + return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end()); +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { + return EF.getHeader()->e_type == ELF::ET_REL; +} + inline std::error_code getELFRelocationAddend(const RelocationRef R, int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); + return cast<ELFObjectFileBase>(Obj)->getRelocationAddend(DRI, Addend); } inline std::pair<symbol_iterator, symbol_iterator> -getELFDynamicSymbolIterators(SymbolicFile *Obj) { - if (const ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - - llvm_unreachable( - "Object passed to getELFDynamicSymbolIterators() is not ELF"); +getELFDynamicSymbolIterators(const SymbolicFile *Obj) { + return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators(); } -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, const SymbolRef &Sym, StringRef &Version, bool &IsDefault) { - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + return cast<ELFObjectFileBase>(Obj) + ->getSymbolVersion(Sym, Version, IsDefault); } } } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 84b603125a69..4bc0c7c2016e 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_ELF_TYPES_H -#define LLVM_OBJECT_ELF_TYPES_H +#ifndef LLVM_OBJECT_ELFTYPES_H +#define LLVM_OBJECT_ELFTYPES_H #include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" @@ -176,6 +176,7 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { template <class ELFT> struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { using Elf_Sym_Base<ELFT>::st_info; + using Elf_Sym_Base<ELFT>::st_other; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: @@ -186,6 +187,9 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { void setBindingAndType(unsigned char b, unsigned char t) { st_info = (b << 4) + (t & 0x0f); } + + /// Access to the STV_xxx flag stored in the first two bits of st_other. + unsigned char getVisibility() const { return st_other & 0x3; } }; /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index fc8cc9581655..b71946d98b5d 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -40,11 +40,12 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. @@ -63,7 +64,7 @@ struct Symbol { StringRef Section; llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Size; - ELF_STV Visibility; + uint8_t Other; }; struct LocalGlobalWeakSymbols { std::vector<Symbol> Local; @@ -175,6 +176,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_STV> { }; template <> +struct ScalarBitSetTraits<ELFYAML::ELF_STO> { + static void bitset(IO &IO, ELFYAML::ELF_STO &Value); +}; + +template <> struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 701da1272cd5..90c2bd74b43c 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -26,7 +26,8 @@ enum class object_error { arch_not_found, invalid_file_type, parse_failed, - unexpected_eof + unexpected_eof, + bitcode_section_not_found, }; inline std::error_code make_error_code(object_error e) { diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index b33cc263b9bd..74f46667ce64 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H -#define LLVM_OBJECT_IR_OBJECT_FILE_H +#ifndef LLVM_OBJECT_IROBJECTFILE_H +#define LLVM_OBJECT_IROBJECTFILE_H #include "llvm/Object/SymbolicFile.h" @@ -22,19 +22,24 @@ class Module; class GlobalValue; namespace object { +class ObjectFile; + class IRObjectFile : public SymbolicFile { std::unique_ptr<Module> M; std::unique_ptr<Mangler> Mang; std::vector<std::pair<std::string, uint32_t>> AsmSymbols; public: - IRObjectFile(std::unique_ptr<MemoryBuffer> Object, std::unique_ptr<Module> M); + IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M); ~IRObjectFile(); void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue *getSymbolGV(DataRefImpl Symb) const; + GlobalValue *getSymbolGV(DataRefImpl Symb); + const GlobalValue *getSymbolGV(DataRefImpl Symb) const { + return const_cast<IRObjectFile *>(this)->getSymbolGV(Symb); + } basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; @@ -44,14 +49,24 @@ public: Module &getModule() { return *M; } + std::unique_ptr<Module> takeModule(); static inline bool classof(const Binary *v) { return v->isIR(); } - static ErrorOr<IRObjectFile *> - createIRObjectFile(std::unique_ptr<MemoryBuffer> Object, - LLVMContext &Context); + /// \brief Finds and returns bitcode embedded in the given object file, or an + /// error code if not found. + static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); + + /// \brief Finds and returns bitcode in the given memory buffer (which may + /// be either a bitcode file or a native object file with embedded bitcode), + /// or an error code if not found. + static ErrorOr<MemoryBufferRef> + findBitcodeInMemBuffer(MemoryBufferRef Object); + + static ErrorOr<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 4835eb80bd65..bee1f6ce0b01 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -49,6 +49,141 @@ public: }; typedef content_iterator<DiceRef> dice_iterator; +/// ExportEntry encapsulates the current-state-of-the-walk used when doing a +/// non-recursive walk of the trie data structure. This allows you to iterate +/// across all exported symbols using: +/// for (const llvm::object::ExportEntry &AnExport : Obj->exports()) { +/// } +class ExportEntry { +public: + ExportEntry(ArrayRef<uint8_t> Trie); + + StringRef name() const; + uint64_t flags() const; + uint64_t address() const; + uint64_t other() const; + StringRef otherName() const; + uint32_t nodeOffset() const; + + bool operator==(const ExportEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(const uint8_t *&p); + void pushDownUntilBottom(); + void pushNode(uint64_t Offset); + + // Represents a node in the mach-o exports trie. + struct NodeState { + NodeState(const uint8_t *Ptr); + const uint8_t *Start; + const uint8_t *Current; + uint64_t Flags; + uint64_t Address; + uint64_t Other; + const char *ImportName; + unsigned ChildCount; + unsigned NextChildIndex; + unsigned ParentStringLength; + bool IsExportNode; + }; + + ArrayRef<uint8_t> Trie; + SmallString<256> CumulativeString; + SmallVector<NodeState, 16> Stack; + bool Malformed; + bool Done; +}; +typedef content_iterator<ExportEntry> export_iterator; + +/// MachORebaseEntry encapsulates the current state in the decompression of +/// rebasing opcodes. This allows you to iterate through the compressed table of +/// rebasing using: +/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { +/// } +class MachORebaseEntry { +public: + MachORebaseEntry(ArrayRef<uint8_t> opcodes, bool is64Bit); + + uint32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + + bool operator==(const MachORebaseEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(); + + ArrayRef<uint8_t> Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset; + uint32_t SegmentIndex; + uint64_t RemainingLoopCount; + uint64_t AdvanceAmount; + uint8_t RebaseType; + uint8_t PointerSize; + bool Malformed; + bool Done; +}; +typedef content_iterator<MachORebaseEntry> rebase_iterator; + +/// MachOBindEntry encapsulates the current state in the decompression of +/// binding opcodes. This allows you to iterate through the compressed table of +/// bindings using: +/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { +/// } +class MachOBindEntry { +public: + enum class Kind { Regular, Lazy, Weak }; + + MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); + + uint32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + StringRef symbolName() const; + uint32_t flags() const; + int64_t addend() const; + int ordinal() const; + + bool operator==(const MachOBindEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(); + int64_t readSLEB128(); + + ArrayRef<uint8_t> Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset; + uint32_t SegmentIndex; + StringRef SymbolName; + int Ordinal; + uint32_t Flags; + int64_t Addend; + uint64_t RemainingLoopCount; + uint64_t AdvanceAmount; + uint8_t BindType; + uint8_t PointerSize; + Kind TableKind; + bool Malformed; + bool Done; +}; +typedef content_iterator<MachOBindEntry> bind_iterator; + class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { @@ -56,8 +191,8 @@ public: MachO::load_command C; // The command itself. }; - MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, bool IsLittleEndian, - bool Is64Bits, std::error_code &EC); + MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + std::error_code &EC); void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code getSymbolName(DataRefImpl Symb, @@ -65,6 +200,7 @@ public: // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + unsigned getSectionType(SectionRef Sec) const; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; @@ -80,24 +216,16 @@ public: void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -118,13 +246,8 @@ public: std::error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; - std::error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const override; - std::error_code getLibraryPath(DataRefImpl LibData, - StringRef &Res) const override; - // MachO specific. - std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res); + std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; // TODO: Would be useful to have an iterator based version // of the load command interface too. @@ -138,21 +261,45 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; - uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - - StringRef getLoadName() const override; + Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const; relocation_iterator section_rel_begin(unsigned Index) const; relocation_iterator section_rel_end(unsigned Index) const; dice_iterator begin_dices() const; dice_iterator end_dices() const; + + /// For use iterating over all exported symbols. + iterator_range<export_iterator> exports() const; + + /// For use examining a trie not in a MachOObjectFile. + static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie); + + /// For use iterating over all rebase table entries. + iterator_range<rebase_iterator> rebaseTable() const; + + /// For use examining rebase opcodes not in a MachOObjectFile. + static iterator_range<rebase_iterator> rebaseTable(ArrayRef<uint8_t> Opcodes, + bool is64); + + /// For use iterating over all bind table entries. + iterator_range<bind_iterator> bindTable() const; + + /// For use iterating over all lazy bind table entries. + iterator_range<bind_iterator> lazyBindTable() const; + + /// For use iterating over all lazy bind table entries. + iterator_range<bind_iterator> weakBindTable() const; + + /// For use examining bind opcodes not in a MachOObjectFile. + static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes, + bool is64, + MachOBindEntry::Kind); + // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment @@ -173,6 +320,8 @@ public: const MachO::any_relocation_info &RE) const; uint32_t getScatteredRelocationValue( const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationType( + const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; @@ -197,12 +346,42 @@ public: getSegmentLoadCommand(const LoadCommandInfo &L) const; MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_options_command - getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::linker_option_command + getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; MachO::dylib_command getDylibIDLoadCommand(const LoadCommandInfo &L) const; + MachO::dyld_info_command + getDyldInfoLoadCommand(const LoadCommandInfo &L) const; + MachO::dylinker_command + getDylinkerCommand(const LoadCommandInfo &L) const; + MachO::uuid_command + getUuidCommand(const LoadCommandInfo &L) const; + MachO::rpath_command + getRpathCommand(const LoadCommandInfo &L) const; + MachO::source_version_command + getSourceVersionCommand(const LoadCommandInfo &L) const; + MachO::entry_point_command + getEntryPointCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command + getEncryptionInfoCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command_64 + getEncryptionInfoCommand64(const LoadCommandInfo &L) const; + MachO::sub_framework_command + getSubFrameworkCommand(const LoadCommandInfo &L) const; + MachO::sub_umbrella_command + getSubUmbrellaCommand(const LoadCommandInfo &L) const; + MachO::sub_library_command + getSubLibraryCommand(const LoadCommandInfo &L) const; + MachO::sub_client_command + getSubClientCommand(const LoadCommandInfo &L) const; + MachO::routines_command + getRoutinesCommand(const LoadCommandInfo &L) const; + MachO::routines_command_64 + getRoutinesCommand64(const LoadCommandInfo &L) const; + MachO::thread_command + getThreadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -216,6 +395,12 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const; + ArrayRef<uint8_t> getDyldInfoBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoExportsTrie() const; + ArrayRef<uint8_t> getUuid() const; StringRef getStringTableData() const; bool is64Bit() const; @@ -225,10 +410,19 @@ public: StringRef &Suffix); static Triple::ArchType getArch(uint32_t CPUType); - static Triple getArch(uint32_t CPUType, uint32_t CPUSubType); - static Triple getArch(StringRef ArchFlag); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr); + static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault, Triple *ThumbTriple); + static bool isValidArch(StringRef ArchFlag); static Triple getHostArch(); + bool isRelocatableObject() const override; + + bool hasPageZeroSegment() const { return HasPageZeroSegment; } + static bool classof(const Binary *v) { return v->isMachO(); } @@ -239,10 +433,13 @@ private: typedef SmallVector<const char*, 1> LibraryList; LibraryList Libraries; typedef SmallVector<StringRef, 1> LibraryShortName; - LibraryShortName LibrariesShortNames; + mutable LibraryShortName LibrariesShortNames; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *DyldInfoLoadCmd; + const char *UuidLoadCmd; + bool HasPageZeroSegment; }; /// DiceRef diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index e6677f5bf28b..93f665438821 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -16,8 +16,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/Binary.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" @@ -25,8 +25,6 @@ namespace llvm { namespace object { -class ObjectFile; - class MachOUniversalBinary : public Binary { virtual void anchor(); @@ -53,14 +51,18 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + uint32_t getCPUSubType() const { return Header.cpusubtype; } + uint32_t getOffset() const { return Header.offset; } + uint32_t getSize() const { return Header.size; } + uint32_t getAlign() const { return Header.align; } std::string getArchTypeName() const { Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); return T.getArchName(); } - ErrorOr<std::unique_ptr<ObjectFile>> getAsObjectFile() const; + ErrorOr<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; - std::error_code getAsArchive(std::unique_ptr<Archive> &Result) const; + ErrorOr<std::unique_ptr<Archive>> getAsArchive() const; }; class object_iterator { @@ -84,10 +86,9 @@ public: } }; - MachOUniversalBinary(std::unique_ptr<MemoryBuffer> Source, - std::error_code &ec); - static ErrorOr<MachOUniversalBinary *> - create(std::unique_ptr<MemoryBuffer> Source); + MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC); + static ErrorOr<std::unique_ptr<MachOUniversalBinary>> + create(MemoryBufferRef Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); @@ -103,7 +104,7 @@ public: return V->isMachOUniversalBinary(); } - ErrorOr<std::unique_ptr<ObjectFile>> + ErrorOr<std::unique_ptr<MachOObjectFile>> getObjectForArch(Triple::ArchType Arch) const; }; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index a4370a3f30d0..6aa985d7e67b 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -27,6 +27,8 @@ namespace llvm { namespace object { class ObjectFile; +class COFFObjectFile; +class MachOObjectFile; class SymbolRef; class symbol_iterator; @@ -93,23 +95,19 @@ public: void moveNext(); std::error_code getName(StringRef &Result) const; - std::error_code getAddress(uint64_t &Result) const; - std::error_code getSize(uint64_t &Result) const; + uint64_t getAddress() const; + uint64_t getSize() const; std::error_code getContents(StringRef &Result) const; /// @brief Get the alignment of this section as the actual value (not log 2). - std::error_code getAlignment(uint64_t &Result) const; + uint64_t getAlignment() const; - // FIXME: Move to the normalization layer when it's created. - std::error_code isText(bool &Result) const; - std::error_code isData(bool &Result) const; - std::error_code isBSS(bool &Result) const; - std::error_code isRequiredForExecution(bool &Result) const; - std::error_code isVirtual(bool &Result) const; - std::error_code isZeroInit(bool &Result) const; - std::error_code isReadOnlyData(bool &Result) const; + bool isText() const; + bool isData() const; + bool isBSS() const; + bool isVirtual() const; - std::error_code containsSymbol(SymbolRef S, bool &Result) const; + bool containsSymbol(SymbolRef S) const; relocation_iterator relocation_begin() const; relocation_iterator relocation_end() const; @@ -120,6 +118,7 @@ public: section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; }; /// SymbolRef - This is a value type class that represents a single symbol in @@ -176,30 +175,6 @@ public: } }; -/// LibraryRef - This is a value type class that represents a single library in -/// the list of libraries needed by a shared or dynamic object. -class LibraryRef { - friend class SectionRef; - DataRefImpl LibraryPimpl; - const ObjectFile *OwningObject; - -public: - LibraryRef() : OwningObject(nullptr) { } - - LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner); - - bool operator==(const LibraryRef &Other) const; - bool operator<(const LibraryRef &Other) const; - - std::error_code getNext(LibraryRef &Result) const; - - // Get the path to this library, as stored in the object file. - std::error_code getPath(StringRef &Result) const; - - DataRefImpl getRawDataRefImpl() const; -}; -typedef content_iterator<LibraryRef> library_iterator; - /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figures out which type to create. @@ -209,10 +184,10 @@ class ObjectFile : public SymbolicFile { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); + ObjectFile(unsigned int Type, MemoryBufferRef Source); const uint8_t *base() const { - return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); + return reinterpret_cast<const uint8_t *>(Data.getBufferStart()); } // These functions are for SymbolRef to call internally. The main goal of @@ -248,29 +223,18 @@ protected: virtual void moveSectionNext(DataRefImpl &Sec) const = 0; virtual std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; - virtual std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const = 0; - virtual std::error_code getSectionSize(DataRefImpl Sec, - uint64_t &Res) const = 0; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; virtual std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const = 0; - virtual std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const = 0; - virtual std::error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const = 0; + virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; + virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual bool isSectionData(DataRefImpl Sec) const = 0; + virtual bool isSectionBSS(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. - virtual std::error_code isSectionVirtual(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code isSectionZeroInit(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const = 0; + virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; + virtual bool sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -297,13 +261,6 @@ protected: return object_error::success; } - // Same for LibraryRef - friend class LibraryRef; - virtual std::error_code getLibraryNext(DataRefImpl Lib, - LibraryRef &Res) const = 0; - virtual std::error_code getLibraryPath(DataRefImpl Lib, - StringRef &Res) const = 0; - public: typedef iterator_range<symbol_iterator> symbol_iterator_range; symbol_iterator_range symbols() const { @@ -318,9 +275,6 @@ public: return section_iterator_range(section_begin(), section_end()); } - virtual library_iterator needed_library_begin() const = 0; - virtual library_iterator needed_library_end() const = 0; - /// @brief The number of bytes used to represent an address in this object /// file format. virtual uint8_t getBytesInAddress() const = 0; @@ -328,27 +282,26 @@ public: virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; - /// For shared objects, returns the name which this object should be - /// loaded from at runtime. This corresponds to DT_SONAME on ELF and - /// LC_ID_DYLIB (install name) on MachO. - virtual StringRef getLoadName() const = 0; - /// Returns platform-specific object flags, if any. virtual std::error_code getPlatformFlags(unsigned &Result) const { Result = 0; return object_error::invalid_file_type; } + /// True if this is a relocatable object (.o/.obj). + virtual bool isRelocatableObject() const = 0; + /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. /// @brief Create ObjectFile from path. - static ErrorOr<ObjectFile *> createObjectFile(StringRef ObjectPath); - static ErrorOr<ObjectFile *> - createObjectFile(std::unique_ptr<MemoryBuffer> &Object, - sys::fs::file_magic Type); - static ErrorOr<ObjectFile *> - createObjectFile(std::unique_ptr<MemoryBuffer> &Object) { + static ErrorOr<OwningBinary<ObjectFile>> + createObjectFile(StringRef ObjectPath); + + static ErrorOr<std::unique_ptr<ObjectFile>> + createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type); + static ErrorOr<std::unique_ptr<ObjectFile>> + createObjectFile(MemoryBufferRef Object) { return createObjectFile(Object, sys::fs::file_magic::unknown); } @@ -357,13 +310,14 @@ public: return v->isObject(); } -public: - static ErrorOr<ObjectFile *> - createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object); - static ErrorOr<ObjectFile *> - createELFObjectFile(std::unique_ptr<MemoryBuffer> &Object); - static ErrorOr<ObjectFile *> - createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Object); + static ErrorOr<std::unique_ptr<COFFObjectFile>> + createCOFFObjectFile(MemoryBufferRef Object); + + static ErrorOr<std::unique_ptr<ObjectFile>> + createELFObjectFile(MemoryBufferRef Object); + + static ErrorOr<std::unique_ptr<MachOObjectFile>> + createMachOObjectFile(MemoryBufferRef Object); }; // Inline function definitions. @@ -430,54 +384,41 @@ inline std::error_code SectionRef::getName(StringRef &Result) const { return OwningObject->getSectionName(SectionPimpl, Result); } -inline std::error_code SectionRef::getAddress(uint64_t &Result) const { - return OwningObject->getSectionAddress(SectionPimpl, Result); +inline uint64_t SectionRef::getAddress() const { + return OwningObject->getSectionAddress(SectionPimpl); } -inline std::error_code SectionRef::getSize(uint64_t &Result) const { - return OwningObject->getSectionSize(SectionPimpl, Result); +inline uint64_t SectionRef::getSize() const { + return OwningObject->getSectionSize(SectionPimpl); } inline std::error_code SectionRef::getContents(StringRef &Result) const { return OwningObject->getSectionContents(SectionPimpl, Result); } -inline std::error_code SectionRef::getAlignment(uint64_t &Result) const { - return OwningObject->getSectionAlignment(SectionPimpl, Result); +inline uint64_t SectionRef::getAlignment() const { + return OwningObject->getSectionAlignment(SectionPimpl); } -inline std::error_code SectionRef::isText(bool &Result) const { - return OwningObject->isSectionText(SectionPimpl, Result); +inline bool SectionRef::isText() const { + return OwningObject->isSectionText(SectionPimpl); } -inline std::error_code SectionRef::isData(bool &Result) const { - return OwningObject->isSectionData(SectionPimpl, Result); +inline bool SectionRef::isData() const { + return OwningObject->isSectionData(SectionPimpl); } -inline std::error_code SectionRef::isBSS(bool &Result) const { - return OwningObject->isSectionBSS(SectionPimpl, Result); +inline bool SectionRef::isBSS() const { + return OwningObject->isSectionBSS(SectionPimpl); } -inline std::error_code SectionRef::isRequiredForExecution(bool &Result) const { - return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result); +inline bool SectionRef::isVirtual() const { + return OwningObject->isSectionVirtual(SectionPimpl); } -inline std::error_code SectionRef::isVirtual(bool &Result) const { - return OwningObject->isSectionVirtual(SectionPimpl, Result); -} - -inline std::error_code SectionRef::isZeroInit(bool &Result) const { - return OwningObject->isSectionZeroInit(SectionPimpl, Result); -} - -inline std::error_code SectionRef::isReadOnlyData(bool &Result) const { - return OwningObject->isSectionReadOnlyData(SectionPimpl, Result); -} - -inline std::error_code SectionRef::containsSymbol(SymbolRef S, - bool &Result) const { +inline bool SectionRef::containsSymbol(SymbolRef S) const { return OwningObject->sectionContainsSymbol(SectionPimpl, - S.getRawDataRefImpl(), Result); + S.getRawDataRefImpl()); } inline relocation_iterator SectionRef::relocation_begin() const { @@ -496,6 +437,10 @@ inline DataRefImpl SectionRef::getRawDataRefImpl() const { return SectionPimpl; } +inline const ObjectFile *SectionRef::getObject() const { + return OwningObject; +} + /// RelocationRef inline RelocationRef::RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner) @@ -548,26 +493,6 @@ inline const ObjectFile *RelocationRef::getObjectFile() const { return OwningObject; } -// Inline function definitions. -inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) - : LibraryPimpl(LibraryP) - , OwningObject(Owner) {} - -inline bool LibraryRef::operator==(const LibraryRef &Other) const { - return LibraryPimpl == Other.LibraryPimpl; -} - -inline bool LibraryRef::operator<(const LibraryRef &Other) const { - return LibraryPimpl < Other.LibraryPimpl; -} - -inline std::error_code LibraryRef::getNext(LibraryRef &Result) const { - return OwningObject->getLibraryNext(LibraryPimpl, Result); -} - -inline std::error_code LibraryRef::getPath(StringRef &Result) const { - return OwningObject->getLibraryPath(LibraryPimpl, Result); -} } // end namespace object } // end namespace llvm diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 5ca245057a55..91eafd55ad76 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,6 +17,7 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" @@ -40,22 +41,39 @@ struct RelocToApply { /// @brief Base class for object file relocation visitors. class RelocVisitor { public: - explicit RelocVisitor(StringRef FileFormat) - : FileFormat(FileFormat), HasError(false) {} + explicit RelocVisitor(const ObjectFile &Obj) + : ObjToVisit(Obj), HasError(false) {} // TODO: Should handle multiple applied relocations via either passing in the // previously computed value or just count paired relocations as a single // visit. - RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, - uint64_t Value = 0) { - if (FileFormat == "ELF64-x86-64") { - switch (RelocType) { + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) { + if (isa<ELFObjectFileBase>(ObjToVisit)) + return visitELF(RelocType, R, Value); + if (isa<COFFObjectFile>(ObjToVisit)) + return visitCOFF(RelocType, R, Value); + + HasError = true; + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + const ObjectFile &ObjToVisit; + bool HasError; + + RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file + switch (ObjToVisit.getArch()) { + case Triple::x86_64: + switch (RelocType) { case llvm::ELF::R_X86_64_NONE: return visitELF_X86_64_NONE(R); case llvm::ELF::R_X86_64_64: return visitELF_X86_64_64(R, Value); case llvm::ELF::R_X86_64_PC32: - return visitELF_X86_64_PC32(R, Value, SecAddr); + return visitELF_X86_64_PC32(R, Value); case llvm::ELF::R_X86_64_32: return visitELF_X86_64_32(R, Value); case llvm::ELF::R_X86_64_32S: @@ -63,116 +81,147 @@ public: default: HasError = true; return RelocToApply(); - } - } else if (FileFormat == "ELF32-i386") { - switch (RelocType) { - case llvm::ELF::R_386_NONE: - return visitELF_386_NONE(R); - case llvm::ELF::R_386_32: - return visitELF_386_32(R, Value); - case llvm::ELF::R_386_PC32: - return visitELF_386_PC32(R, Value, SecAddr); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-ppc64") { - switch (RelocType) { - case llvm::ELF::R_PPC64_ADDR32: - return visitELF_PPC64_ADDR32(R, Value); - case llvm::ELF::R_PPC64_ADDR64: - return visitELF_PPC64_ADDR64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF32-ppc") { - switch (RelocType) { - case llvm::ELF::R_PPC_ADDR32: - return visitELF_PPC_ADDR32(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF32-mips") { - switch (RelocType) { - case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-mips") { - switch (RelocType) { - case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); - case llvm::ELF::R_MIPS_64: - return visitELF_MIPS_64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-aarch64") { - switch (RelocType) { - case llvm::ELF::R_AARCH64_ABS32: - return visitELF_AARCH64_ABS32(R, Value); - case llvm::ELF::R_AARCH64_ABS64: - return visitELF_AARCH64_ABS64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-s390") { - switch (RelocType) { - case llvm::ELF::R_390_32: - return visitELF_390_32(R, Value); - case llvm::ELF::R_390_64: - return visitELF_390_64(R, Value); + } + case Triple::aarch64: + switch (RelocType) { + case llvm::ELF::R_AARCH64_ABS32: + return visitELF_AARCH64_ABS32(R, Value); + case llvm::ELF::R_AARCH64_ABS64: + return visitELF_AARCH64_ABS64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::mips64el: + case Triple::mips64: + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + case llvm::ELF::R_MIPS_64: + return visitELF_MIPS_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::ppc64le: + case Triple::ppc64: + switch (RelocType) { + case llvm::ELF::R_PPC64_ADDR32: + return visitELF_PPC64_ADDR32(R, Value); + case llvm::ELF::R_PPC64_ADDR64: + return visitELF_PPC64_ADDR64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::systemz: + switch (RelocType) { + case llvm::ELF::R_390_32: + return visitELF_390_32(R, Value); + case llvm::ELF::R_390_64: + return visitELF_390_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::sparcv9: + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARCV9_32(R, Value); + case llvm::ELF::R_SPARC_64: + case llvm::ELF::R_SPARC_UA64: + return visitELF_SPARCV9_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); } - } else if (FileFormat == "ELF32-sparc") { - switch (RelocType) { - case llvm::ELF::R_SPARC_32: - case llvm::ELF::R_SPARC_UA32: - return visitELF_SPARC_32(R, Value); + } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file + switch (ObjToVisit.getArch()) { + case Triple::x86: + switch (RelocType) { + case llvm::ELF::R_386_NONE: + return visitELF_386_NONE(R); + case llvm::ELF::R_386_32: + return visitELF_386_32(R, Value); + case llvm::ELF::R_386_PC32: + return visitELF_386_PC32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::ppc: + switch (RelocType) { + case llvm::ELF::R_PPC_ADDR32: + return visitELF_PPC_ADDR32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::arm: + case Triple::armeb: + switch (RelocType) { + default: + HasError = true; + return RelocToApply(); + case llvm::ELF::R_ARM_ABS32: + return visitELF_ARM_ABS32(R, Value); + } + case Triple::mipsel: + case Triple::mips: + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::sparc: + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARC_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); } - } else if (FileFormat == "ELF64-sparc") { + } else { + report_fatal_error("Invalid word size in object file"); + } + } + + RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + case Triple::x86: switch (RelocType) { - case llvm::ELF::R_SPARC_32: - case llvm::ELF::R_SPARC_UA32: - return visitELF_SPARCV9_32(R, Value); - case llvm::ELF::R_SPARC_64: - case llvm::ELF::R_SPARC_UA64: - return visitELF_SPARCV9_64(R, Value); - default: - HasError = true; - return RelocToApply(); + case COFF::IMAGE_REL_I386_SECREL: + return visitCOFF_I386_SECREL(R, Value); + case COFF::IMAGE_REL_I386_DIR32: + return visitCOFF_I386_DIR32(R, Value); } - } else if (FileFormat == "ELF32-arm") { + break; + case Triple::x86_64: switch (RelocType) { - default: - HasError = true; - return RelocToApply(); - case llvm::ELF::R_ARM_ABS32: - return visitELF_ARM_ABS32(R, Value); + case COFF::IMAGE_REL_AMD64_SECREL: + return visitCOFF_AMD64_SECREL(R, Value); + case COFF::IMAGE_REL_AMD64_ADDR64: + return visitCOFF_AMD64_ADDR64(R, Value); } + break; } HasError = true; return RelocToApply(); } - bool error() { return HasError; } - -private: - StringRef FileFormat; - bool HasError; - - int64_t getAddend32LE(RelocationRef R) { + int64_t getELFAddend32LE(RelocationRef R) { const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -180,7 +229,7 @@ private: return Addend; } - int64_t getAddend64LE(RelocationRef R) { + int64_t getELFAddend64LE(RelocationRef R) { const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -188,7 +237,7 @@ private: return Addend; } - int64_t getAddend32BE(RelocationRef R) { + int64_t getELFAddend32BE(RelocationRef R) { const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -196,7 +245,7 @@ private: return Addend; } - int64_t getAddend64BE(RelocationRef R) { + int64_t getELFAddend64BE(RelocationRef R) { const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -213,13 +262,12 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); + int64_t Addend = getELFAddend32LE(R); return RelocToApply(Value + Addend, 4); } - RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend32LE(R); + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -230,23 +278,22 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); return RelocToApply(Value + Addend, 8); } - RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend64LE(R); + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -266,7 +313,7 @@ private: /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32BE(R); + int64_t Addend = getELFAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -288,7 +335,8 @@ private: // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -299,13 +347,14 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -316,30 +365,54 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { - int32_t Addend = getAddend32BE(R); + int32_t Addend = getELFAddend32BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { - int32_t Addend = getAddend64BE(R); + int32_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); - return RelocToApply(Value + Addend, 4); + int64_t Addend; + getELFRelocationAddend(R, Addend); + int64_t Res = Value + Addend; + + // Overflow check allows for both signed and unsigned interpretation. + if (Res < INT32_MIN || Res > UINT32_MAX) + HasError = true; + + return RelocToApply(static_cast<uint32_t>(Res), 4); } + /// I386 COFF + RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); + } + + /// AMD64 COFF + RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { + return RelocToApply(Value, /*Width=*/8); + } }; } diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 77eef4a546aa..435799a34ebc 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H -#define LLVM_OBJECT_SYMBOLIC_FILE_H +#ifndef LLVM_OBJECT_SYMBOLICFILE_H +#define LLVM_OBJECT_SYMBOLICFILE_H #include "llvm/Object/Binary.h" @@ -87,8 +87,9 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6 // Specific to the object file format + SF_FormatSpecific = 1U << 6, // Specific to the object file format // (e.g. section symbols) + SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary }; BasicSymbolRef() : OwningObject(nullptr) { } @@ -115,7 +116,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL; class SymbolicFile : public Binary { public: virtual ~SymbolicFile(); - SymbolicFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); + SymbolicFile(unsigned int Type, MemoryBufferRef Source); // virtual interface. virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; @@ -142,15 +143,16 @@ public: } // construction aux. - static ErrorOr<SymbolicFile *> - createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object, - sys::fs::file_magic Type, LLVMContext *Context); + static ErrorOr<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object, sys::fs::file_magic Type, + LLVMContext *Context); - static ErrorOr<SymbolicFile *> - createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object) { + static ErrorOr<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object) { return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr); } - static ErrorOr<SymbolicFile *> createSymbolicFile(StringRef ObjectPath); + static ErrorOr<OwningBinary<SymbolicFile>> + createSymbolicFile(StringRef ObjectPath); static inline bool classof(const Binary *v) { return v->isSymbolic(); diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index d46b0e892faf..3f8547e7fe41 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -187,6 +187,7 @@ public: /// /// \p Claim Whether the argument should be claimed, if it exists. Arg *getLastArgNoClaim(OptSpecifier Id) const; + Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const; Arg *getLastArg(OptSpecifier Id) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 1558c51bde48..8c28ef5e7e61 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -42,61 +42,51 @@ class PassRegistry { mutable sys::SmartRWMutex<true> Lock; /// PassInfoMap - Keep track of the PassInfo object for each registered pass. - typedef DenseMap<const void*, const PassInfo*> MapType; + typedef DenseMap<const void *, const PassInfo *> MapType; MapType PassInfoMap; - - typedef StringMap<const PassInfo*> StringMapType; + + typedef StringMap<const PassInfo *> StringMapType; StringMapType PassInfoStringMap; - - /// AnalysisGroupInfo - Keep track of information for each analysis group. - struct AnalysisGroupInfo { - SmallPtrSet<const PassInfo *, 8> Implementations; - }; - DenseMap<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap; - + std::vector<std::unique_ptr<const PassInfo>> ToFree; - std::vector<PassRegistrationListener*> Listeners; - + std::vector<PassRegistrationListener *> Listeners; + public: - PassRegistry() { } + PassRegistry() {} ~PassRegistry(); - - /// getPassRegistry - Access the global registry object, which is + + /// getPassRegistry - Access the global registry object, which is /// automatically initialized at application launch and destroyed by /// llvm_shutdown. static PassRegistry *getPassRegistry(); - + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' /// type identifier (&MyPass::ID). const PassInfo *getPassInfo(const void *TI) const; - + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' /// argument string. const PassInfo *getPassInfo(StringRef Arg) const; - - /// registerPass - Register a pass (by means of its PassInfo) with the + + /// registerPass - Register a pass (by means of its PassInfo) with the /// registry. Required in order to use the pass with a PassManager. void registerPass(const PassInfo &PI, bool ShouldFree = false); - - /// registerPass - Unregister a pass (by means of its PassInfo) with the - /// registry. - void unregisterPass(const PassInfo &PI); - + /// registerAnalysisGroup - Register an analysis group (or a pass implementing - // an analysis group) with the registry. Like registerPass, this is required + // an analysis group) with the registry. Like registerPass, this is required // in order for a PassManager to be able to use this group/pass. void registerAnalysisGroup(const void *InterfaceID, const void *PassID, - PassInfo& Registeree, bool isDefault, + PassInfo &Registeree, bool isDefault, bool ShouldFree = false); - + /// enumerateWith - Enumerate the registered passes, calling the provided /// PassRegistrationListener's passEnumerate() callback on each of them. void enumerateWith(PassRegistrationListener *L); - + /// addRegistrationListener - Register the given PassRegistrationListener /// to receive passRegistered() callbacks whenever a new pass is registered. void addRegistrationListener(PassRegistrationListener *L); - + /// removeRegistrationListener - Unregister a PassRegistrationListener so that /// it no longer receives passRegistered() callbacks. void removeRegistrationListener(PassRegistrationListener *L); diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index 449bc9281084..6cb6516412e8 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -82,6 +82,15 @@ class TargetMachine; CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ } +#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + INITIALIZE_PASS_END(PassName, Arg, Name, Cfg, Analysis) + +#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + template<typename PassName> Pass *callDefaultCtor() { return new PassName(); } diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h new file mode 100644 index 000000000000..38fc8ca7c77c --- /dev/null +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -0,0 +1,448 @@ +//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Code coverage mapping data is generated by clang and read by +// llvm-cov to show code coverage statistics for a file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_ +#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_ + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/raw_ostream.h" +#include <system_error> + +namespace llvm { +class IndexedInstrProfReader; +namespace coverage { + +class ObjectFileCoverageMappingReader; + +class CoverageMapping; +struct CounterExpressions; + +enum CoverageMappingVersion { CoverageMappingVersion1 }; + +/// \brief A Counter is an abstract value that describes how to compute the +/// execution count for a region of code using the collected profile count data. +struct Counter { + enum CounterKind { Zero, CounterValueReference, Expression }; + static const unsigned EncodingTagBits = 2; + static const unsigned EncodingTagMask = 0x3; + static const unsigned EncodingCounterTagAndExpansionRegionTagBits = + EncodingTagBits + 1; + +private: + CounterKind Kind; + unsigned ID; + + Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} + +public: + Counter() : Kind(Zero), ID(0) {} + + CounterKind getKind() const { return Kind; } + + bool isZero() const { return Kind == Zero; } + + bool isExpression() const { return Kind == Expression; } + + unsigned getCounterID() const { return ID; } + + unsigned getExpressionID() const { return ID; } + + bool operator==(const Counter &Other) const { + return Kind == Other.Kind && ID == Other.ID; + } + + friend bool operator<(const Counter &LHS, const Counter &RHS) { + return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); + } + + /// \brief Return the counter that represents the number zero. + static Counter getZero() { return Counter(); } + + /// \brief Return the counter that corresponds to a specific profile counter. + static Counter getCounter(unsigned CounterId) { + return Counter(CounterValueReference, CounterId); + } + + /// \brief Return the counter that corresponds to a specific + /// addition counter expression. + static Counter getExpression(unsigned ExpressionId) { + return Counter(Expression, ExpressionId); + } +}; + +/// \brief A Counter expression is a value that represents an arithmetic +/// operation with two counters. +struct CounterExpression { + enum ExprKind { Subtract, Add }; + ExprKind Kind; + Counter LHS, RHS; + + CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) + : Kind(Kind), LHS(LHS), RHS(RHS) {} +}; + +/// \brief A Counter expression builder is used to construct the +/// counter expressions. It avoids unecessary duplication +/// and simplifies algebraic expressions. +class CounterExpressionBuilder { + /// \brief A list of all the counter expressions + std::vector<CounterExpression> Expressions; + /// \brief A lookup table for the index of a given expression. + llvm::DenseMap<CounterExpression, unsigned> ExpressionIndices; + + /// \brief Return the counter which corresponds to the given expression. + /// + /// If the given expression is already stored in the builder, a counter + /// that references that expression is returned. Otherwise, the given + /// expression is added to the builder's collection of expressions. + Counter get(const CounterExpression &E); + + /// \brief Gather the terms of the expression tree for processing. + /// + /// This collects each addition and subtraction referenced by the counter into + /// a sequence that can be sorted and combined to build a simplified counter + /// expression. + void extractTerms(Counter C, int Sign, + SmallVectorImpl<std::pair<unsigned, int>> &Terms); + + /// \brief Simplifies the given expression tree + /// by getting rid of algebraically redundant operations. + Counter simplify(Counter ExpressionTree); + +public: + ArrayRef<CounterExpression> getExpressions() const { return Expressions; } + + /// \brief Return a counter that represents the expression + /// that adds LHS and RHS. + Counter add(Counter LHS, Counter RHS); + + /// \brief Return a counter that represents the expression + /// that subtracts RHS from LHS. + Counter subtract(Counter LHS, Counter RHS); +}; + +/// \brief A Counter mapping region associates a source range with +/// a specific counter. +struct CounterMappingRegion { + enum RegionKind { + /// \brief A CodeRegion associates some code with a counter + CodeRegion, + + /// \brief An ExpansionRegion represents a file expansion region that + /// associates a source range with the expansion of a virtual source file, + /// such as for a macro instantiation or #include file. + ExpansionRegion, + + /// \brief A SkippedRegion represents a source range with code that + /// was skipped by a preprocessor or similar means. + SkippedRegion + }; + + static const unsigned EncodingHasCodeBeforeBits = 1; + + Counter Count; + unsigned FileID, ExpandedFileID; + unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; + RegionKind Kind; + /// \brief A flag that is set to true when there is already code before + /// this region on the same line. + /// This is useful to accurately compute the execution counts for a line. + bool HasCodeBefore; + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, + unsigned ColumnEnd, bool HasCodeBefore = false, + RegionKind Kind = CodeRegion) + : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), + ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), + Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + inline std::pair<unsigned, unsigned> startLoc() const { + return std::pair<unsigned, unsigned>(LineStart, ColumnStart); + } + + inline std::pair<unsigned, unsigned> endLoc() const { + return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd); + } + + bool operator<(const CounterMappingRegion &Other) const { + if (FileID != Other.FileID) + return FileID < Other.FileID; + return startLoc() < Other.startLoc(); + } + + bool contains(const CounterMappingRegion &Other) const { + if (FileID != Other.FileID) + return false; + if (startLoc() > Other.startLoc()) + return false; + if (endLoc() < Other.endLoc()) + return false; + return true; + } +}; + +/// \brief Associates a source range with an execution count. +struct CountedRegion : public CounterMappingRegion { + uint64_t ExecutionCount; + + CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) + : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {} +}; + +/// \brief A Counter mapping context is used to connect the counters, +/// expressions and the obtained counter values. +class CounterMappingContext { + ArrayRef<CounterExpression> Expressions; + ArrayRef<uint64_t> CounterValues; + +public: + CounterMappingContext(ArrayRef<CounterExpression> Expressions, + ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>()) + : Expressions(Expressions), CounterValues(CounterValues) {} + + void dump(const Counter &C, llvm::raw_ostream &OS) const; + void dump(const Counter &C) const { dump(C, llvm::outs()); } + + /// \brief Return the number of times that a region of code associated with + /// this counter was executed. + ErrorOr<int64_t> evaluate(const Counter &C) const; +}; + +/// \brief Code coverage information for a single function. +struct FunctionRecord { + /// \brief Raw function name. + std::string Name; + /// \brief Associated files. + std::vector<std::string> Filenames; + /// \brief Regions in the function along with their counts. + std::vector<CountedRegion> CountedRegions; + /// \brief The number of times this function was executed. + uint64_t ExecutionCount; + + FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames, + uint64_t ExecutionCount) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()), + ExecutionCount(ExecutionCount) {} +}; + +/// \brief Iterator over Functions, optionally filtered to a single file. +class FunctionRecordIterator + : public iterator_facade_base<FunctionRecordIterator, + std::forward_iterator_tag, FunctionRecord> { + ArrayRef<FunctionRecord> Records; + ArrayRef<FunctionRecord>::iterator Current; + StringRef Filename; + + /// \brief Skip records whose primary file is not \c Filename. + void skipOtherFiles(); + +public: + FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, + StringRef Filename = "") + : Records(Records_), Current(Records.begin()), Filename(Filename) { + skipOtherFiles(); + } + + FunctionRecordIterator() : Current(Records.begin()) {} + + bool operator==(const FunctionRecordIterator &RHS) const { + return Current == RHS.Current && Filename == RHS.Filename; + } + + const FunctionRecord &operator*() const { return *Current; } + + FunctionRecordIterator &operator++() { + assert(Current != Records.end() && "incremented past end"); + ++Current; + skipOtherFiles(); + return *this; + } +}; + +/// \brief Coverage information for a macro expansion or #included file. +/// +/// When covered code has pieces that can be expanded for more detail, such as a +/// preprocessor macro use and its definition, these are represented as +/// expansions whose coverage can be looked up independently. +struct ExpansionRecord { + /// \brief The abstract file this expansion covers. + unsigned FileID; + /// \brief The region that expands to this record. + const CountedRegion &Region; + /// \brief Coverage for the expansion. + const FunctionRecord &Function; + + ExpansionRecord(const CountedRegion &Region, + const FunctionRecord &Function) + : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} +}; + +/// \brief The execution count information starting at a point in a file. +/// +/// A sequence of CoverageSegments gives execution counts for a file in format +/// that's simple to iterate through for processing. +struct CoverageSegment { + /// \brief The line where this segment begins. + unsigned Line; + /// \brief The column where this segment begins. + unsigned Col; + /// \brief The execution count, or zero if no count was recorded. + uint64_t Count; + /// \brief When false, the segment was uninstrumented or skipped. + bool HasCount; + /// \brief Whether this enters a new region or returns to a previous count. + bool IsRegionEntry; + + CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) + : Line(Line), Col(Col), Count(0), HasCount(false), + IsRegionEntry(IsRegionEntry) {} + void setCount(uint64_t NewCount) { + Count = NewCount; + HasCount = true; + } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } +}; + +/// \brief Coverage information to be processed or displayed. +/// +/// This represents the coverage of an entire file, expansion, or function. It +/// provides a sequence of CoverageSegments to iterate through, as well as the +/// list of expansions that can be further processed. +class CoverageData { + std::string Filename; + std::vector<CoverageSegment> Segments; + std::vector<ExpansionRecord> Expansions; + friend class CoverageMapping; + +public: + CoverageData() {} + + CoverageData(StringRef Filename) : Filename(Filename) {} + + CoverageData(CoverageData &&RHS) + : Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)), + Expansions(std::move(RHS.Expansions)) {} + + /// \brief Get the name of the file this data covers. + StringRef getFilename() { return Filename; } + + std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); } + std::vector<CoverageSegment>::iterator end() { return Segments.end(); } + bool empty() { return Segments.empty(); } + + /// \brief Expansions that can be further processed. + std::vector<ExpansionRecord> getExpansions() { return Expansions; } +}; + +/// \brief The mapping of profile information to coverage data. +/// +/// This is the main interface to get coverage information, using a profile to +/// fill out execution counts. +class CoverageMapping { + std::vector<FunctionRecord> Functions; + unsigned MismatchedFunctionCount; + + CoverageMapping() : MismatchedFunctionCount(0) {} + +public: + /// \brief Load the coverage mapping using the given readers. + static ErrorOr<std::unique_ptr<CoverageMapping>> + load(ObjectFileCoverageMappingReader &CoverageReader, + IndexedInstrProfReader &ProfileReader); + + /// \brief Load the coverage mapping from the given files. + static ErrorOr<std::unique_ptr<CoverageMapping>> + load(StringRef ObjectFilename, StringRef ProfileFilename); + + /// \brief The number of functions that couldn't have their profiles mapped. + /// + /// This is a count of functions whose profile is out of date or otherwise + /// can't be associated with any coverage information. + unsigned getMismatchedCount() { return MismatchedFunctionCount; } + + /// \brief Returns the list of files that are covered. + std::vector<StringRef> getUniqueSourceFiles() const; + + /// \brief Get the coverage for a particular file. + /// + /// The given filename must be the name as recorded in the coverage + /// information. That is, only names returned from getUniqueSourceFiles will + /// yield a result. + CoverageData getCoverageForFile(StringRef Filename); + + /// \brief Gets all of the functions covered by this profile. + iterator_range<FunctionRecordIterator> getCoveredFunctions() const { + return make_range(FunctionRecordIterator(Functions), + FunctionRecordIterator()); + } + + /// \brief Gets all of the functions in a particular file. + iterator_range<FunctionRecordIterator> + getCoveredFunctions(StringRef Filename) const { + return make_range(FunctionRecordIterator(Functions, Filename), + FunctionRecordIterator()); + } + + /// \brief Get the list of function instantiations in the file. + /// + /// Fucntions that are instantiated more than once, such as C++ template + /// specializations, have distinct coverage records for each instantiation. + std::vector<const FunctionRecord *> getInstantiations(StringRef Filename); + + /// \brief Get the coverage for a particular function. + CoverageData getCoverageForFunction(const FunctionRecord &Function); + + /// \brief Get the coverage for an expansion within a coverage set. + CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion); +}; + +} // end namespace coverage + +/// \brief Provide DenseMapInfo for CounterExpression +template<> struct DenseMapInfo<coverage::CounterExpression> { + static inline coverage::CounterExpression getEmptyKey() { + using namespace coverage; + return CounterExpression(CounterExpression::ExprKind::Subtract, + Counter::getCounter(~0U), + Counter::getCounter(~0U)); + } + + static inline coverage::CounterExpression getTombstoneKey() { + using namespace coverage; + return CounterExpression(CounterExpression::ExprKind::Add, + Counter::getCounter(~0U), + Counter::getCounter(~0U)); + } + + static unsigned getHashValue(const coverage::CounterExpression &V) { + return static_cast<unsigned>( + hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), + V.RHS.getKind(), V.RHS.getCounterID())); + } + + static bool isEqual(const coverage::CounterExpression &LHS, + const coverage::CounterExpression &RHS) { + return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; + } +}; + + +} // end namespace llvm + +#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h new file mode 100644 index 000000000000..5a6b44b8d9ef --- /dev/null +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -0,0 +1,208 @@ +//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for reading coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H +#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include <iterator> + +namespace llvm { +namespace coverage { + +class ObjectFileCoverageMappingReader; + +/// \brief Coverage mapping information for a single function. +struct CoverageMappingRecord { + StringRef FunctionName; + uint64_t FunctionHash; + ArrayRef<StringRef> Filenames; + ArrayRef<CounterExpression> Expressions; + ArrayRef<CounterMappingRegion> MappingRegions; +}; + +/// \brief A file format agnostic iterator over coverage mapping data. +class CoverageMappingIterator + : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { + ObjectFileCoverageMappingReader *Reader; + CoverageMappingRecord Record; + + void increment(); + +public: + CoverageMappingIterator() : Reader(nullptr) {} + CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) + : Reader(Reader) { + increment(); + } + + CoverageMappingIterator &operator++() { + increment(); + return *this; + } + bool operator==(const CoverageMappingIterator &RHS) { + return Reader == RHS.Reader; + } + bool operator!=(const CoverageMappingIterator &RHS) { + return Reader != RHS.Reader; + } + CoverageMappingRecord &operator*() { return Record; } + CoverageMappingRecord *operator->() { return &Record; } +}; + +/// \brief Base class for the raw coverage mapping and filenames data readers. +class RawCoverageReader { +protected: + StringRef Data; + + /// \brief Return the error code. + std::error_code error(std::error_code EC) { return EC; } + + /// \brief Clear the current error code and return a successful one. + std::error_code success() { return error(instrprof_error::success); } + + RawCoverageReader(StringRef Data) : Data(Data) {} + + std::error_code readULEB128(uint64_t &Result); + std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1); + std::error_code readSize(uint64_t &Result); + std::error_code readString(StringRef &Result); +}; + +/// \brief Reader for the raw coverage filenames. +class RawCoverageFilenamesReader : public RawCoverageReader { + std::vector<StringRef> &Filenames; + + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) + LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader & + operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + +public: + RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) + : RawCoverageReader(Data), Filenames(Filenames) {} + + std::error_code read(); +}; + +/// \brief Reader for the raw coverage mapping data. +class RawCoverageMappingReader : public RawCoverageReader { + StringRef FunctionName; + ArrayRef<StringRef> TranslationUnitFilenames; + std::vector<StringRef> &Filenames; + std::vector<CounterExpression> &Expressions; + std::vector<CounterMappingRegion> &MappingRegions; + + RawCoverageMappingReader(const RawCoverageMappingReader &) + LLVM_DELETED_FUNCTION; + RawCoverageMappingReader & + operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + +public: + RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + ArrayRef<StringRef> TranslationUnitFilenames, + std::vector<StringRef> &Filenames, + std::vector<CounterExpression> &Expressions, + std::vector<CounterMappingRegion> &MappingRegions) + : RawCoverageReader(MappingData), FunctionName(FunctionName), + TranslationUnitFilenames(TranslationUnitFilenames), + Filenames(Filenames), Expressions(Expressions), + MappingRegions(MappingRegions) {} + + std::error_code read(CoverageMappingRecord &Record); + +private: + std::error_code decodeCounter(unsigned Value, Counter &C); + std::error_code readCounter(Counter &C); + std::error_code + readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions, + unsigned InferredFileID, size_t NumFileIDs); +}; + +/// \brief Reader for the coverage mapping data that is emitted by the +/// frontend and stored in an object file. +class ObjectFileCoverageMappingReader { +public: + struct ProfileMappingRecord { + CoverageMappingVersion Version; + StringRef FunctionName; + uint64_t FunctionHash; + StringRef CoverageMapping; + size_t FilenamesBegin; + size_t FilenamesSize; + + ProfileMappingRecord(CoverageMappingVersion Version, StringRef FunctionName, + uint64_t FunctionHash, StringRef CoverageMapping, + size_t FilenamesBegin, size_t FilenamesSize) + : Version(Version), FunctionName(FunctionName), + FunctionHash(FunctionHash), CoverageMapping(CoverageMapping), + FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} + }; + +private: + std::error_code LastError; + object::OwningBinary<object::ObjectFile> Object; + std::vector<StringRef> Filenames; + std::vector<ProfileMappingRecord> MappingRecords; + size_t CurrentRecord; + std::vector<StringRef> FunctionsFilenames; + std::vector<CounterExpression> Expressions; + std::vector<CounterMappingRegion> MappingRegions; + + ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) + LLVM_DELETED_FUNCTION; + ObjectFileCoverageMappingReader & + operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; + + /// \brief Set the current error_code and return same. + std::error_code error(std::error_code EC) { + LastError = EC; + return EC; + } + + /// \brief Clear the current error code and return a successful one. + std::error_code success() { return error(instrprof_error::success); } + +public: + ObjectFileCoverageMappingReader(StringRef FileName); + ObjectFileCoverageMappingReader( + std::unique_ptr<MemoryBuffer> &ObjectBuffer, + sys::fs::file_magic Type = sys::fs::file_magic::unknown); + + std::error_code readHeader(); + std::error_code readNextRecord(CoverageMappingRecord &Record); + + /// Iterator over profile data. + CoverageMappingIterator begin() { return CoverageMappingIterator(this); } + CoverageMappingIterator end() { return CoverageMappingIterator(); } + + /// \brief Return true if the reader has finished reading the profile data. + bool isEOF() { return LastError == instrprof_error::eof; } + /// \brief Return true if the reader encountered an error reading profiling + /// data. + bool hasError() { return LastError && !isEOF(); } + /// \brief Get the current error code. + std::error_code getError() { return LastError; } +}; + +} // end namespace coverage +} // end namespace llvm + +#endif diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/CoverageMappingWriter.h new file mode 100644 index 000000000000..2e3b0378d032 --- /dev/null +++ b/include/llvm/ProfileData/CoverageMappingWriter.h @@ -0,0 +1,63 @@ +//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H +#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace coverage { + +/// \brief Writer of the filenames section for the instrumentation +/// based code coverage. +class CoverageFilenamesSectionWriter { + ArrayRef<StringRef> Filenames; + +public: + CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames) + : Filenames(Filenames) {} + + /// \brief Write encoded filenames to the given output stream. + void write(raw_ostream &OS); +}; + +/// \brief Writer for instrumentation based coverage mapping data. +class CoverageMappingWriter { + ArrayRef<unsigned> VirtualFileMapping; + ArrayRef<CounterExpression> Expressions; + MutableArrayRef<CounterMappingRegion> MappingRegions; + +public: + CoverageMappingWriter(ArrayRef<unsigned> VirtualFileMapping, + ArrayRef<CounterExpression> Expressions, + MutableArrayRef<CounterMappingRegion> MappingRegions) + : VirtualFileMapping(VirtualFileMapping), Expressions(Expressions), + MappingRegions(MappingRegions) {} + + CoverageMappingWriter(ArrayRef<CounterExpression> Expressions, + MutableArrayRef<CounterMappingRegion> MappingRegions) + : Expressions(Expressions), MappingRegions(MappingRegions) {} + + /// \brief Write encoded coverage mapping data to the given output stream. + void write(raw_ostream &OS); +}; + +} // end namespace coverage +} // end namespace llvm + +#endif diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 7a5a71dc6a31..9655d66edc92 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -12,17 +12,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_READER_H_ -#define LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H +#define LLVM_PROFILEDATA_INSTRPROFREADER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" - #include <iterator> namespace llvm { @@ -94,8 +94,7 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. - static std::error_code create(std::string Path, - std::unique_ptr<InstrProfReader> &Result); + static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path); }; /// Reader for the simple text based instrprof format. @@ -120,7 +119,7 @@ private: LLVM_DELETED_FUNCTION; public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {} + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} /// Read the header. std::error_code readHeader() override { return success(); } @@ -206,12 +205,17 @@ enum class HashT : uint32_t; /// Trait for lookups into the on-disk hash table for the binary instrprof /// format. class InstrProfLookupTrait { - std::vector<uint64_t> CountBuffer; + std::vector<uint64_t> DataBuffer; IndexedInstrProf::HashT HashType; public: InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {} - typedef InstrProfRecord data_type; + struct data_type { + data_type(StringRef Name, ArrayRef<uint64_t> Data) + : Name(Name), Data(Data) {} + StringRef Name; + ArrayRef<uint64_t> Data; + }; typedef StringRef internal_key_type; typedef StringRef external_key_type; typedef uint64_t hash_value_type; @@ -234,25 +238,20 @@ public: return StringRef((const char *)D, N); } - InstrProfRecord ReadData(StringRef K, const unsigned char *D, offset_type N) { - if (N < 2 * sizeof(uint64_t) || N % sizeof(uint64_t)) { + data_type ReadData(StringRef K, const unsigned char *D, offset_type N) { + DataBuffer.clear(); + if (N % sizeof(uint64_t)) // The data is corrupt, don't try to read it. - CountBuffer.clear(); - return InstrProfRecord("", 0, CountBuffer); - } + return data_type("", DataBuffer); using namespace support; - - // The first stored value is the hash. - uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); - // Each counter follows. - unsigned NumCounters = N / sizeof(uint64_t) - 1; - CountBuffer.clear(); - CountBuffer.reserve(NumCounters - 1); - for (unsigned I = 0; I < NumCounters; ++I) - CountBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); - - return InstrProfRecord(K, Hash, CountBuffer); + // We just treat the data as opaque here. It's simpler to handle in + // IndexedInstrProfReader. + unsigned NumEntries = N / sizeof(uint64_t); + DataBuffer.reserve(NumEntries); + for (unsigned I = 0; I < NumEntries; ++I) + DataBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); + return data_type(K, DataBuffer); } }; typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait> @@ -267,7 +266,11 @@ private: std::unique_ptr<InstrProfReaderIndex> Index; /// Iterator over the profile data. InstrProfReaderIndex::data_iterator RecordIterator; - /// The maximal execution count among all fucntions. + /// Offset into our current data set. + size_t CurrentOffset; + /// The file format version of the profile data. + uint64_t FormatVersion; + /// The maximal execution count among all functions. uint64_t MaxFunctionCount; IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; @@ -275,8 +278,7 @@ private: LLVM_DELETED_FUNCTION; public: IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) - : DataBuffer(std::move(DataBuffer)), Index(nullptr), - RecordIterator(InstrProfReaderIndex::data_iterator()) {} + : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} /// Return true if the given buffer is in an indexed instrprof format. static bool hasFormat(const MemoryBuffer &DataBuffer); @@ -287,7 +289,7 @@ public: std::error_code readNextRecord(InstrProfRecord &Record) override; /// Fill Counts with the profile data for the given function name. - std::error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, + std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector<uint64_t> &Counts); /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } @@ -299,4 +301,4 @@ public: } // end namespace llvm -#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#endif diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index 6e68bee30eb8..a23c56772a2f 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -12,15 +12,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ -#define LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ +#ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H +#define LLVM_PROFILEDATA_INSTRPROFWRITER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" - #include <vector> namespace llvm { @@ -28,13 +28,13 @@ namespace llvm { /// Writer for instrumentation based profile data. class InstrProfWriter { public: - struct CounterData { - uint64_t Hash; - std::vector<uint64_t> Counts; - }; + typedef SmallDenseMap<uint64_t, std::vector<uint64_t>, 1> CounterData; private: StringMap<CounterData> FunctionData; + uint64_t MaxFunctionCount; public: + InstrProfWriter() : MaxFunctionCount(0) {} + /// Add function counts for the given function. If there are already counts /// for this function and the hash and number of counts match, each counter is /// summed. @@ -47,4 +47,4 @@ public: } // end namespace llvm -#endif // LLVM_PROFILE_INSTRPROF_WRITER_H_ +#endif diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h new file mode 100644 index 000000000000..df0a055c2a79 --- /dev/null +++ b/include/llvm/ProfileData/SampleProf.h @@ -0,0 +1,247 @@ +//=-- SampleProf.h - Sampling profiling format support --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains common definitions used in the reading and writing of +// sample profile data. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ +#define LLVM_PROFILEDATA_SAMPLEPROF_H_ + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <system_error> + +namespace llvm { + +const std::error_category &sampleprof_category(); + +enum class sampleprof_error { + success = 0, + bad_magic, + unsupported_version, + too_large, + truncated, + malformed, + unrecognized_format +}; + +inline std::error_code make_error_code(sampleprof_error E) { + return std::error_code(static_cast<int>(E), sampleprof_category()); +} + +} // end namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {}; +} + +namespace llvm { + +namespace sampleprof { + +static inline uint64_t SPMagic() { + return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) | + uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) | + uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) | + uint64_t('2') << (64 - 56) | uint64_t(0xff); +} + +static inline uint64_t SPVersion() { return 100; } + +/// \brief Represents the relative location of an instruction. +/// +/// Instruction locations are specified by the line offset from the +/// beginning of the function (marked by the line where the function +/// header is) and the discriminator value within that line. +/// +/// The discriminator value is useful to distinguish instructions +/// that are on the same line but belong to different basic blocks +/// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). +struct LineLocation { + LineLocation(int L, unsigned D) : LineOffset(L), Discriminator(D) {} + int LineOffset; + unsigned Discriminator; +}; + +} // End namespace sampleprof + +template <> struct DenseMapInfo<sampleprof::LineLocation> { + typedef DenseMapInfo<int> OffsetInfo; + typedef DenseMapInfo<unsigned> DiscriminatorInfo; + static inline sampleprof::LineLocation getEmptyKey() { + return sampleprof::LineLocation(OffsetInfo::getEmptyKey(), + DiscriminatorInfo::getEmptyKey()); + } + static inline sampleprof::LineLocation getTombstoneKey() { + return sampleprof::LineLocation(OffsetInfo::getTombstoneKey(), + DiscriminatorInfo::getTombstoneKey()); + } + static inline unsigned getHashValue(sampleprof::LineLocation Val) { + return DenseMapInfo<std::pair<int, unsigned>>::getHashValue( + std::pair<int, unsigned>(Val.LineOffset, Val.Discriminator)); + } + static inline bool isEqual(sampleprof::LineLocation LHS, + sampleprof::LineLocation RHS) { + return LHS.LineOffset == RHS.LineOffset && + LHS.Discriminator == RHS.Discriminator; + } +}; + +namespace sampleprof { + +/// \brief Representation of a single sample record. +/// +/// A sample record is represented by a positive integer value, which +/// indicates how frequently was the associated line location executed. +/// +/// Additionally, if the associated location contains a function call, +/// the record will hold a list of all the possible called targets. For +/// direct calls, this will be the exact function being invoked. For +/// indirect calls (function pointers, virtual table dispatch), this +/// will be a list of one or more functions. +class SampleRecord { +public: + typedef StringMap<unsigned> CallTargetMap; + + SampleRecord() : NumSamples(0), CallTargets() {} + + /// \brief Increment the number of samples for this record by \p S. + /// + /// Sample counts accumulate using saturating arithmetic, to avoid wrapping + /// around unsigned integers. + void addSamples(unsigned S) { + if (NumSamples <= std::numeric_limits<unsigned>::max() - S) + NumSamples += S; + else + NumSamples = std::numeric_limits<unsigned>::max(); + } + + /// \brief Add called function \p F with samples \p S. + /// + /// Sample counts accumulate using saturating arithmetic, to avoid wrapping + /// around unsigned integers. + void addCalledTarget(StringRef F, unsigned S) { + unsigned &TargetSamples = CallTargets[F]; + if (TargetSamples <= std::numeric_limits<unsigned>::max() - S) + TargetSamples += S; + else + TargetSamples = std::numeric_limits<unsigned>::max(); + } + + /// \brief Return true if this sample record contains function calls. + bool hasCalls() const { return CallTargets.size() > 0; } + + unsigned getSamples() const { return NumSamples; } + const CallTargetMap &getCallTargets() const { return CallTargets; } + + /// \brief Merge the samples in \p Other into this record. + void merge(const SampleRecord &Other) { + addSamples(Other.getSamples()); + for (const auto &I : Other.getCallTargets()) + addCalledTarget(I.first(), I.second); + } + +private: + unsigned NumSamples; + CallTargetMap CallTargets; +}; + +typedef DenseMap<LineLocation, SampleRecord> BodySampleMap; + +/// \brief Representation of the samples collected for a function. +/// +/// This data structure contains all the collected samples for the body +/// of a function. Each sample corresponds to a LineLocation instance +/// within the body of the function. +class FunctionSamples { +public: + FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {} + void print(raw_ostream &OS = dbgs()); + void addTotalSamples(unsigned Num) { TotalSamples += Num; } + void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; } + void addBodySamples(int LineOffset, unsigned Discriminator, unsigned Num) { + assert(LineOffset >= 0); + // When dealing with instruction weights, we use the value + // zero to indicate the absence of a sample. If we read an + // actual zero from the profile file, use the value 1 to + // avoid the confusion later on. + if (Num == 0) + Num = 1; + BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num); + } + void addCalledTargetSamples(int LineOffset, unsigned Discriminator, + std::string FName, unsigned Num) { + assert(LineOffset >= 0); + BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(FName, + Num); + } + + /// \brief Return the sample record at the given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + SampleRecord &sampleRecordAt(const LineLocation &Loc) { + return BodySamples[Loc]; + } + + /// \brief Return the number of samples collected at the given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + unsigned samplesAt(int LineOffset, unsigned Discriminator) { + return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples(); + } + + bool empty() const { return BodySamples.empty(); } + + /// \brief Return the total number of samples collected inside the function. + unsigned getTotalSamples() const { return TotalSamples; } + + /// \brief Return the total number of samples collected at the head of the + /// function. + unsigned getHeadSamples() const { return TotalHeadSamples; } + + /// \brief Return all the samples collected in the body of the function. + const BodySampleMap &getBodySamples() const { return BodySamples; } + + /// \brief Merge the samples in \p Other into this one. + void merge(const FunctionSamples &Other) { + addTotalSamples(Other.getTotalSamples()); + addHeadSamples(Other.getHeadSamples()); + for (const auto &I : Other.getBodySamples()) { + const LineLocation &Loc = I.first; + const SampleRecord &Rec = I.second; + sampleRecordAt(Loc).merge(Rec); + } + } + +private: + /// \brief Total number of samples collected inside this function. + /// + /// Samples are cumulative, they include all the samples collected + /// inside this function and all its inlined callees. + unsigned TotalSamples; + + /// \brief Total number of samples collected at the head of the function. + unsigned TotalHeadSamples; + + /// \brief Map instruction locations to collected samples. + /// + /// Each entry in this map contains the number of samples + /// collected at the corresponding line offset. All line locations + /// are an offset from the start of the function. + BodySampleMap BodySamples; +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_ diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h new file mode 100644 index 000000000000..c082a1abe951 --- /dev/null +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -0,0 +1,170 @@ +//===- SampleProfReader.h - Read LLVM sample profile data -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions needed for reading sample profiles. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H +#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +namespace sampleprof { + +/// \brief Sample-based profile reader. +/// +/// Each profile contains sample counts for all the functions +/// executed. Inside each function, statements are annotated with the +/// collected samples on all the instructions associated with that +/// statement. +/// +/// For this to produce meaningful data, the program needs to be +/// compiled with some debug information (at minimum, line numbers: +/// -gline-tables-only). Otherwise, it will be impossible to match IR +/// instructions to the line numbers collected by the profiler. +/// +/// From the profile file, we are interested in collecting the +/// following information: +/// +/// * A list of functions included in the profile (mangled names). +/// +/// * For each function F: +/// 1. The total number of samples collected in F. +/// +/// 2. The samples collected at each line in F. To provide some +/// protection against source code shuffling, line numbers should +/// be relative to the start of the function. +/// +/// The reader supports two file formats: text and binary. The text format +/// is useful for debugging and testing, while the binary format is more +/// compact. They can both be used interchangeably. +class SampleProfileReader { +public: + SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) + : Profiles(0), Ctx(C), Buffer(std::move(B)) {} + + virtual ~SampleProfileReader() {} + + /// \brief Read and validate the file header. + virtual std::error_code readHeader() = 0; + + /// \brief Read sample profiles from the associated file. + virtual std::error_code read() = 0; + + /// \brief Print the profile for \p FName on stream \p OS. + void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs()); + + /// \brief Print all the profiles on stream \p OS. + void dump(raw_ostream &OS = dbgs()); + + /// \brief Return the samples collected for function \p F. + FunctionSamples *getSamplesFor(const Function &F) { + return &Profiles[F.getName()]; + } + + /// \brief Return all the profiles. + StringMap<FunctionSamples> &getProfiles() { return Profiles; } + + /// \brief Report a parse error message. + void reportParseError(int64_t LineNumber, Twine Msg) const { + Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(), + LineNumber, Msg)); + } + + /// \brief Create a sample profile reader appropriate to the file format. + static ErrorOr<std::unique_ptr<SampleProfileReader>> + create(StringRef Filename, LLVMContext &C); + +protected: + /// \brief Map every function to its associated profile. + /// + /// The profile of every function executed at runtime is collected + /// in the structure FunctionSamples. This maps function objects + /// to their corresponding profiles. + StringMap<FunctionSamples> Profiles; + + /// \brief LLVM context used to emit diagnostics. + LLVMContext &Ctx; + + /// \brief Memory buffer holding the profile file. + std::unique_ptr<MemoryBuffer> Buffer; +}; + +class SampleProfileReaderText : public SampleProfileReader { +public: + SampleProfileReaderText(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) + : SampleProfileReader(std::move(B), C) {} + + /// \brief Read and validate the file header. + std::error_code readHeader() override { return sampleprof_error::success; } + + /// \brief Read sample profiles from the associated file. + std::error_code read() override; +}; + +class SampleProfileReaderBinary : public SampleProfileReader { +public: + SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) + : SampleProfileReader(std::move(B), C), Data(nullptr), End(nullptr) {} + + /// \brief Read and validate the file header. + std::error_code readHeader() override; + + /// \brief Read sample profiles from the associated file. + std::error_code read() override; + + /// \brief Return true if \p Buffer is in the format supported by this class. + static bool hasFormat(const MemoryBuffer &Buffer); + +protected: + /// \brief Read a numeric value of type T from the profile. + /// + /// If an error occurs during decoding, a diagnostic message is emitted and + /// EC is set. + /// + /// \returns the read value. + template <typename T> ErrorOr<T> readNumber(); + + /// \brief Read a string from the profile. + /// + /// If an error occurs during decoding, a diagnostic message is emitted and + /// EC is set. + /// + /// \returns the read value. + ErrorOr<StringRef> readString(); + + /// \brief Return true if we've reached the end of file. + bool at_eof() const { return Data >= End; } + + /// \brief Points to the current location in the buffer. + const uint8_t *Data; + + /// \brief Points to the end of the buffer. + const uint8_t *End; +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h new file mode 100644 index 000000000000..302a82d32861 --- /dev/null +++ b/include/llvm/ProfileData/SampleProfWriter.h @@ -0,0 +1,110 @@ +//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions needed for writing sample profiles. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H +#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +namespace sampleprof { + +enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC }; + +/// \brief Sample-based profile writer. Base class. +class SampleProfileWriter { +public: + SampleProfileWriter(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags) + : OS(Filename, EC, Flags) {} + virtual ~SampleProfileWriter() {} + + /// \brief Write sample profiles in \p S for function \p FName. + /// + /// \returns true if the file was updated successfully. False, otherwise. + virtual bool write(StringRef FName, const FunctionSamples &S) = 0; + + /// \brief Write sample profiles in \p S for function \p F. + bool write(const Function &F, const FunctionSamples &S) { + return write(F.getName(), S); + } + + /// \brief Write all the sample profiles for all the functions in \p M. + /// + /// \returns true if the file was updated successfully. False, otherwise. + bool write(const Module &M, StringMap<FunctionSamples> &P) { + for (const auto &F : M) { + StringRef Name = F.getName(); + if (!write(Name, P[Name])) + return false; + } + return true; + } + + /// \brief Write all the sample profiles in the given map of samples. + /// + /// \returns true if the file was updated successfully. False, otherwise. + bool write(StringMap<FunctionSamples> &ProfileMap) { + for (auto &I : ProfileMap) { + StringRef FName = I.first(); + FunctionSamples &Profile = I.second; + if (!write(FName, Profile)) + return false; + } + return true; + } + + /// \brief Profile writer factory. Create a new writer based on the value of + /// \p Format. + static ErrorOr<std::unique_ptr<SampleProfileWriter>> + create(StringRef Filename, SampleProfileFormat Format); + +protected: + /// \brief Output stream where to emit the profile to. + raw_fd_ostream OS; +}; + +/// \brief Sample-based profile writer (text format). +class SampleProfileWriterText : public SampleProfileWriter { +public: + SampleProfileWriterText(StringRef F, std::error_code &EC) + : SampleProfileWriter(F, EC, sys::fs::F_Text) {} + + bool write(StringRef FName, const FunctionSamples &S) override; + bool write(const Module &M, StringMap<FunctionSamples> &P) { + return SampleProfileWriter::write(M, P); + } +}; + +/// \brief Sample-based profile writer (binary format). +class SampleProfileWriterBinary : public SampleProfileWriter { +public: + SampleProfileWriterBinary(StringRef F, std::error_code &EC); + + bool write(StringRef F, const FunctionSamples &S) override; + bool write(const Module &M, StringMap<FunctionSamples> &P) { + return SampleProfileWriter::write(M, P); + } +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index f63e0a61f639..96a8219bfb85 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H -#define LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H +#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H namespace llvm { class StringRef; @@ -146,6 +146,12 @@ enum { AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + // Tag_ABI_PCS_R9_use, (=14), uleb128 + R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) + R9IsSB = 1, // R9 used as a global static base rgister + R9IsTLSPointer = 2, // R9 used as a thread local storage pointer + R9Reserved = 3, // R9 not used by code associated with attributed entity + // Tag_ABI_PCS_RW_data, (=15), uleb128 AddressRWPCRel = 1, // Address RW static data PC-relative AddressRWSBRel = 2, // Address RW static data SB-relative @@ -165,6 +171,8 @@ enum { WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 // Tag_ABI_FP_denormal, (=20), uleb128 + PositiveZero = 0, + IEEEDenormals = 1, PreserveFPSign = 2, // sign when flushed-to-zero is preserved // Tag_ABI_FP_number_model, (=23), uleb128 @@ -192,6 +200,9 @@ enum { // Tag_FP_HP_extension, (=36), uleb128 AllowHPFP = 1, // Allow use of Half Precision FP + // Tag_FP_16bit_format, (=38), uleb128 + FP16FormatIEEE = 1, + // Tag_MPextension_use, (=42), uleb128 AllowMP = 1, // Allow use of MP extensions @@ -214,4 +225,4 @@ enum { } // namespace ARMBuildAttrs } // namespace llvm -#endif // LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#endif diff --git a/include/llvm/Support/ARMEHABI.h b/include/llvm/Support/ARMEHABI.h index c7ac54aeb6de..9b052df0a908 100644 --- a/include/llvm/Support/ARMEHABI.h +++ b/include/llvm/Support/ARMEHABI.h @@ -19,8 +19,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARM_EHABI_H -#define LLVM_SUPPORT_ARM_EHABI_H +#ifndef LLVM_SUPPORT_ARMEHABI_H +#define LLVM_SUPPORT_ARMEHABI_H namespace llvm { namespace ARM { @@ -131,4 +131,4 @@ namespace EHABI { } } -#endif // ARM_UNWIND_OP_H +#endif diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h index 78deb8d36a98..1463629f45dc 100644 --- a/include/llvm/Support/ARMWinEH.h +++ b/include/llvm/Support/ARMWinEH.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_WINARMEH_H -#define LLVM_SUPPORT_WINARMEH_H +#ifndef LLVM_SUPPORT_ARMWINEH_H +#define LLVM_SUPPORT_ARMWINEH_H #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" @@ -350,16 +350,15 @@ struct ExceptionDataRecord { ArrayRef<support::ulittle32_t> EpilogueScopes() const { assert(E() == 0 && "epilogue scopes are only present when the E bit is 0"); size_t Offset = HeaderWords(*this); - return ArrayRef<support::ulittle32_t>(&Data[Offset], EpilogueCount()); + return makeArrayRef(&Data[Offset], EpilogueCount()); } - ArrayRef<support::ulittle8_t> UnwindByteCode() const { + ArrayRef<uint8_t> UnwindByteCode() const { const size_t Offset = HeaderWords(*this) + (E() ? 0 : EpilogueCount()); - const support::ulittle8_t *ByteCode = - reinterpret_cast<const support::ulittle8_t *>(&Data[Offset]); - return ArrayRef<support::ulittle8_t>(ByteCode, - CodeWords() * sizeof(uint32_t)); + const uint8_t *ByteCode = + reinterpret_cast<const uint8_t *>(&Data[Offset]); + return makeArrayRef(ByteCode, CodeWords() * sizeof(uint32_t)); } uint32_t ExceptionHandlerRVA() const { @@ -381,4 +380,3 @@ inline size_t HeaderWords(const ExceptionDataRecord &XR) { } #endif - diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 7a7e4c0a13e2..de317719714d 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -90,7 +90,10 @@ class MallocAllocator : public AllocatorBase<MallocAllocator> { public: void Reset() {} - void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } + LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, + size_t /*Alignment*/) { + return malloc(Size); + } // Pull in base class overloads. using AllocatorBase<MallocAllocator>::Allocate; @@ -116,8 +119,8 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, /// \brief Allocate memory in an ever growing pool, as if by bump-pointer. /// /// This isn't strictly a bump-pointer allocator as it uses backing slabs of -/// memory rather than relying on boundless contiguous heap. However, it has -/// bump-pointer semantics in that is a monotonically growing pool of memory +/// memory rather than relying on a boundless contiguous heap. However, it has +/// bump-pointer semantics in that it is a monotonically growing pool of memory /// where every allocation is found by merely allocating the next N bytes in /// the slab, or the next N bytes in the next slab. /// @@ -200,28 +203,24 @@ public: } /// \brief Allocate space at the specified alignment. - void *Allocate(size_t Size, size_t Alignment) { - if (!CurPtr) // Start a new slab if we haven't allocated one already. - StartNewSlab(); + LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { + assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); // Keep track of how many bytes we've allocated. BytesAllocated += Size; - // 0-byte alignment means 1-byte alignment. - if (Alignment == 0) - Alignment = 1; - - // Allocate the aligned space, going forwards from CurPtr. - char *Ptr = alignPtr(CurPtr, Alignment); + size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); + assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); - // Check if we can hold it. - if (Ptr + Size <= End) { - CurPtr = Ptr + Size; + // Check if we have enough space. + if (Adjustment + Size <= size_t(End - CurPtr)) { + char *AlignedPtr = CurPtr + Adjustment; + CurPtr = AlignedPtr + Size; // Update the allocation point of this memory block in MemorySanitizer. // Without this, MemorySanitizer messages for values originated from here // will point to the allocation of the entire slab. - __msan_allocated_memory(Ptr, Size); - return Ptr; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // If Size is really big, allocate a separate slab for it. @@ -230,19 +229,22 @@ public: void *NewSlab = Allocator.Allocate(PaddedSize, 0); CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); - Ptr = alignPtr((char *)NewSlab, Alignment); - assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + PaddedSize); - __msan_allocated_memory(Ptr, Size); - return Ptr; + uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); + char *AlignedPtr = (char*)AlignedAddr; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // Otherwise, start a new slab and try again. StartNewSlab(); - Ptr = alignPtr(CurPtr, Alignment); - CurPtr = Ptr + Size; - assert(CurPtr <= End && "Unable to allocate memory!"); - __msan_allocated_memory(Ptr, Size); - return Ptr; + uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)End && + "Unable to allocate memory!"); + char *AlignedPtr = (char*)AlignedAddr; + CurPtr = AlignedPtr + Size; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // Pull in base class overloads. @@ -320,8 +322,10 @@ private: #ifndef NDEBUG // Poison the memory so stale pointers crash sooner. Note we must // preserve the Size and NextPtr fields at the beginning. - sys::Memory::setRangeWritable(*I, AllocatedSlabSize); - memset(*I, 0xCD, AllocatedSlabSize); + if (AllocatedSlabSize != 0) { + sys::Memory::setRangeWritable(*I, AllocatedSlabSize); + memset(*I, 0xCD, AllocatedSlabSize); + } #endif Allocator.Deallocate(*I, AllocatedSlabSize); } @@ -373,7 +377,7 @@ public: /// all memory allocated so far. void DestroyAll() { auto DestroyElements = [](char *Begin, char *End) { - assert(Begin == alignPtr(Begin, alignOf<T>())); + assert(Begin == (char*)alignAddr(Begin, alignOf<T>())); for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) reinterpret_cast<T *>(Ptr)->~T(); }; @@ -382,7 +386,7 @@ public: ++I) { size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( std::distance(Allocator.Slabs.begin(), I)); - char *Begin = alignPtr((char *)*I, alignOf<T>()); + char *Begin = (char*)alignAddr(*I, alignOf<T>()); char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr : (char *)*I + AllocatedSlabSize; @@ -392,7 +396,7 @@ public: for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { void *Ptr = PtrAndSize.first; size_t Size = PtrAndSize.second; - DestroyElements(alignPtr((char *)Ptr, alignOf<T>()), (char *)Ptr + Size); + DestroyElements((char*)alignAddr(Ptr, alignOf<T>()), (char *)Ptr + Size); } Allocator.Reset(); diff --git a/include/llvm/Support/CBindingWrapping.h b/include/llvm/Support/CBindingWrapping.h index 51097b820220..786ba183b3b0 100644 --- a/include/llvm/Support/CBindingWrapping.h +++ b/include/llvm/Support/CBindingWrapping.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_C_BINDING_WRAPPING_H -#define LLVM_C_BINDING_WRAPPING_H +#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H +#define LLVM_SUPPORT_CBINDINGWRAPPING_H #include "llvm/Support/Casting.h" diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index e09ef07d81db..150bce50d9ae 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -31,23 +31,30 @@ namespace llvm { namespace COFF { // The maximum number of sections that a COFF object can have (inclusive). - const int MaxNumberOfSections = 65299; + const int32_t MaxNumberOfSections16 = 65279; // The PE signature bytes that follows the DOS stub header. static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; + static const char BigObjMagic[] = { + '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b', + '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8', + }; + // Sizes in bytes of various things in the COFF format. enum { - HeaderSize = 20, + Header16Size = 20, + Header32Size = 56, NameSize = 8, - SymbolSize = 18, + Symbol16Size = 18, + Symbol32Size = 20, SectionSize = 40, RelocationSize = 10 }; struct header { uint16_t Machine; - uint16_t NumberOfSections; + int32_t NumberOfSections; uint32_t TimeDateStamp; uint32_t PointerToSymbolTable; uint32_t NumberOfSymbols; @@ -55,6 +62,24 @@ namespace COFF { uint16_t Characteristics; }; + struct BigObjHeader { + enum : uint16_t { MinBigObjectVersion = 2 }; + + uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). + uint16_t Sig2; ///< Must be 0xFFFF. + uint16_t Version; + uint16_t Machine; + uint32_t TimeDateStamp; + uint8_t UUID[16]; + uint32_t unused1; + uint32_t unused2; + uint32_t unused3; + uint32_t unused4; + uint32_t NumberOfSections; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + }; + enum MachineTypes { MT_Invalid = 0xffff, @@ -124,7 +149,7 @@ namespace COFF { struct symbol { char Name[NameSize]; uint32_t Value; - uint16_t SectionNumber; + int32_t SectionNumber; uint16_t Type; uint8_t StorageClass; uint8_t NumberOfAuxSymbols; @@ -140,9 +165,9 @@ namespace COFF { SF_WeakExternal = 0x01000000 }; - enum SymbolSectionNumber { - IMAGE_SYM_DEBUG = 0xFFFE, - IMAGE_SYM_ABSOLUTE = 0xFFFF, + enum SymbolSectionNumber : int32_t { + IMAGE_SYM_DEBUG = -2, + IMAGE_SYM_ABSOLUTE = -1, IMAGE_SYM_UNDEFINED = 0 }; @@ -367,18 +392,14 @@ namespace COFF { IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 }; - struct AuxiliaryFile { - uint8_t FileName[18]; - }; - struct AuxiliarySectionDefinition { uint32_t Length; uint16_t NumberOfRelocations; uint16_t NumberOfLinenumbers; uint32_t CheckSum; - uint16_t Number; + uint32_t Number; uint8_t Selection; - char unused[3]; + char unused; }; struct AuxiliaryCLRToken { @@ -392,7 +413,6 @@ namespace COFF { AuxiliaryFunctionDefinition FunctionDefinition; AuxiliarybfAndefSymbol bfAndefSymbol; AuxiliaryWeakExternal WeakExternal; - AuxiliaryFile File; AuxiliarySectionDefinition SectionDefinition; }; @@ -495,12 +515,14 @@ namespace COFF { uint32_t SizeOfHeaders; uint32_t CheckSum; uint16_t Subsystem; + // FIXME: This should be DllCharacteristics to match the COFF spec. uint16_t DLLCharacteristics; uint32_t SizeOfStackReserve; uint32_t SizeOfStackCommit; uint32_t SizeOfHeapReserve; uint32_t SizeOfHeapCommit; uint32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec. uint32_t NumberOfRvaAndSize; }; @@ -524,7 +546,9 @@ namespace COFF { BOUND_IMPORT, IAT, DELAY_IMPORT_DESCRIPTOR, - CLR_RUNTIME_HEADER + CLR_RUNTIME_HEADER, + + NUM_DATA_DIRECTORIES }; enum WindowsSubsystem { @@ -642,13 +666,18 @@ namespace COFF { enum CodeViewLineTableIdentifiers { DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4 + DEBUG_INDEX_SUBSECTION = 0xF4, + + // Symbol subsections are split into records of different types. + DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; - inline bool isReservedSectionNumber(int N) { - return N == IMAGE_SYM_UNDEFINED || N > MaxNumberOfSections; + inline bool isReservedSectionNumber(int32_t SectionNumber) { + return SectionNumber <= 0; } } // End namespace COFF. diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index beed31a4084f..6ba5efa47554 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -243,6 +243,26 @@ inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { // accepted. // template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type +cast_or_null(const Y &Val) { + if (!Val) + return nullptr; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type +cast_or_null(Y &Val) { + if (!Val) + return nullptr; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + +template <class X, class Y> LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type cast_or_null(Y *Val) { if (!Val) return nullptr; @@ -282,6 +302,20 @@ dyn_cast(Y *Val) { // value is accepted. // template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type +dyn_cast_or_null(const Y &Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type +dyn_cast_or_null(Y &Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type dyn_cast_or_null(Y *Val) { return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h index 240eba6c8a41..243f2dd7498c 100644 --- a/include/llvm/Support/CodeGen.h +++ b/include/llvm/Support/CodeGen.h @@ -30,6 +30,10 @@ namespace llvm { enum Model { Default, JITDefault, Small, Kernel, Medium, Large }; } + namespace PICLevel { + enum Level { Default=0, Small=1, Large=2 }; + } + // TLS models. namespace TLSModel { enum Model { diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index fdd901200fe9..1c06bf5f8c07 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -40,7 +40,7 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, const char * const *argv, +void ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview = nullptr); //===----------------------------------------------------------------------===// @@ -66,7 +66,6 @@ void SetVersionPrinter(void (*func)()); /// information specific to the tool. void AddExtraVersionPrinter(void (*func)()); - // PrintOptionValues - Print option values. // With -print-options print the difference between option values and defaults. // With -print-all-options print all option values. @@ -80,11 +79,11 @@ void MarkOptionsChanged(); // Flags permitted to be passed to command line arguments // -enum NumOccurrencesFlag { // Flags for the number of occurrences allowed - Optional = 0x00, // Zero or One occurrence - ZeroOrMore = 0x01, // Zero or more occurrences allowed - Required = 0x02, // One occurrence required - OneOrMore = 0x03, // One or more occurrences required +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required // ConsumeAfter - Indicates that this option is fed anything that follows the // last positional argument required by the application (it is an error if @@ -93,20 +92,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed // found. Once a filename is found, all of the succeeding arguments are // passed, unprocessed, to the ConsumeAfter option. // - ConsumeAfter = 0x04 + ConsumeAfter = 0x04 }; -enum ValueExpected { // Is a value required for the option? +enum ValueExpected { // Is a value required for the option? // zero reserved for the unspecified value - ValueOptional = 0x01, // The value can appear... or not - ValueRequired = 0x02, // The value is required to appear! - ValueDisallowed = 0x03 // A value may not be specified (for flags) + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) }; -enum OptionHidden { // Control whether -help shows this option - NotHidden = 0x00, // Option included in -help & -help-hidden - Hidden = 0x01, // -help doesn't, but -help-hidden does - ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg }; // Formatting flags - This controls special features that the option might have @@ -125,16 +124,16 @@ enum OptionHidden { // Control whether -help shows this option // enum FormattingFlags { - NormalFormatting = 0x00, // Nothing special - Positional = 0x01, // Is a positional argument, no '-' required - Prefix = 0x02, // Can this option directly prefix its value? - Grouping = 0x03 // Can this option group with other options? + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? }; -enum MiscFlags { // Miscellaneous flags to adjust argument - CommaSeparated = 0x01, // Should this cl::list split between commas? - PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? - Sink = 0x04 // Should this cl::list eat all unknown options? +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? }; //===----------------------------------------------------------------------===// @@ -145,9 +144,13 @@ private: const char *const Name; const char *const Description; void registerCategory(); + public: - OptionCategory(const char *const Name, const char *const Description = nullptr) - : Name(Name), Description(Description) { registerCategory(); } + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } const char *getName() const { return Name; } const char *getDescription() const { return Description; } }; @@ -176,7 +179,7 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences; // The number of times specified + int NumOccurrences; // The number of times specified // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid // problems with signed enums in bitfields. unsigned Occurrences : 3; // enum NumOccurrencesFlag @@ -186,9 +189,9 @@ class Option { unsigned HiddenFlag : 2; // enum OptionHidden unsigned Formatting : 2; // enum FormattingFlags unsigned Misc : 3; - unsigned Position; // Position of last occurrence of the option - unsigned AdditionalVals;// Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. + Option *NextRegistered; // Singly linked list of registered options. public: const char *ArgStr; // The argument string itself (ex: "help", "o") @@ -200,8 +203,7 @@ public: return (enum NumOccurrencesFlag)Occurrences; } inline enum ValueExpected getValueExpectedFlag() const { - return Value ? ((enum ValueExpected)Value) - : getValueExpectedFlagDefault(); + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); } inline enum OptionHidden getOptionHiddenFlag() const { return (enum OptionHidden)HiddenFlag; @@ -209,9 +211,7 @@ public: inline enum FormattingFlags getFormattingFlag() const { return (enum FormattingFlags)Formatting; } - inline unsigned getMiscFlags() const { - return Misc; - } + inline unsigned getMiscFlags() const { return Misc; } inline unsigned getPosition() const { return Position; } inline unsigned getNumAdditionalVals() const { return AdditionalVals; } @@ -224,25 +224,24 @@ public: void setArgStr(const char *S) { ArgStr = S; } void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } - void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { - Occurrences = Val; - } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } void setCategory(OptionCategory &C) { Category = &C; } + protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), - HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(nullptr), - ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { - } + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), + ValueStr(""), Category(&GeneralCategory) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + public: // addArgument - Register this argument with the commandline system. // @@ -266,12 +265,12 @@ public: virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &) {} + virtual void getExtraOptionNames(SmallVectorImpl<const char *> &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - virtual bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -281,7 +280,6 @@ public: virtual ~Option() {} }; - //===----------------------------------------------------------------------===// // Command line option modifiers that can be used to modify the behavior of // command line option parsers... @@ -306,36 +304,31 @@ struct value_desc { // the default constructor for the argument type does not give you what you // want. This is only valid on "opt" arguments, not on "list" arguments. // -template<class Ty> -struct initializer { +template <class Ty> struct initializer { const Ty &Init; initializer(const Ty &Val) : Init(Val) {} - template<class Opt> - void apply(Opt &O) const { O.setInitialValue(Init); } + template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); } }; -template<class Ty> -initializer<Ty> init(const Ty &Val) { +template <class Ty> initializer<Ty> init(const Ty &Val) { return initializer<Ty>(Val); } - // location - Allow the user to specify which external variable they want to // store the results of the command line argument processing into, if they don't // want to store it in the option itself. // -template<class Ty> -struct LocationClass { +template <class Ty> struct LocationClass { Ty &Loc; LocationClass(Ty &L) : Loc(L) {} - template<class Opt> - void apply(Opt &O) const { O.setLocation(O, Loc); } + template <class Opt> void apply(Opt &O) const { O.setLocation(O, Loc); } }; -template<class Ty> -LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); } +template <class Ty> LocationClass<Ty> location(Ty &L) { + return LocationClass<Ty>(L); +} // cat - Specifiy the Option category for the command line argument to belong // to. @@ -343,11 +336,9 @@ struct cat { OptionCategory &Category; cat(OptionCategory &c) : Category(c) {} - template<class Opt> - void apply(Opt &O) const { O.setCategory(Category); } + template <class Opt> void apply(Opt &O) const { O.setCategory(Category); } }; - //===----------------------------------------------------------------------===// // OptionValue class @@ -360,11 +351,11 @@ private: virtual void anchor(); }; -template<class DataType> struct OptionValue; +template <class DataType> struct OptionValue; // The default value safely does nothing. Option value printing is only // best-effort. -template<class DataType, bool isClass> +template <class DataType, bool isClass> struct OptionValueBase : public GenericOptionValue { // Temporary storage for argument passing. typedef OptionValue<DataType> WrapperType; @@ -374,21 +365,20 @@ struct OptionValueBase : public GenericOptionValue { const DataType &getValue() const { llvm_unreachable("no default value"); } // Some options may take their value from a different data type. - template<class DT> - void setValue(const DT& /*V*/) {} + template <class DT> void setValue(const DT & /*V*/) {} - bool compare(const DataType &/*V*/) const { return false; } + bool compare(const DataType & /*V*/) const { return false; } - bool compare(const GenericOptionValue& /*V*/) const override { + bool compare(const GenericOptionValue & /*V*/) const override { return false; } }; // Simple copy of the option value. -template<class DataType> -class OptionValueCopy : public GenericOptionValue { +template <class DataType> class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; + public: OptionValueCopy() : Valid(false) {} @@ -399,37 +389,36 @@ public: return Value; } - void setValue(const DataType &V) { Valid = true; Value = V; } - - bool compare(const DataType &V) const { - return Valid && (Value != V); + void setValue(const DataType &V) { + Valid = true; + Value = V; } + bool compare(const DataType &V) const { return Valid && (Value != V); } + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy<DataType> &VC = - static_cast< const OptionValueCopy<DataType>& >(V); - if (!VC.hasValue()) return false; + static_cast<const OptionValueCopy<DataType> &>(V); + if (!VC.hasValue()) + return false; return compare(VC.getValue()); } }; // Non-class option values. -template<class DataType> +template <class DataType> struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { typedef DataType WrapperType; }; // Top-level option class. -template<class DataType> +template <class DataType> struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { OptionValue() {} - OptionValue(const DataType& V) { - this->setValue(V); - } + OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. - template<class DT> - OptionValue<DataType> &operator=(const DT& V) { + template <class DT> OptionValue<DataType> &operator=(const DT &V) { this->setValue(V); return *this; } @@ -437,36 +426,33 @@ struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; -template<> +template <> struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> { typedef cl::boolOrDefault WrapperType; OptionValue() {} - OptionValue(const cl::boolOrDefault& V) { - this->setValue(V); - } - OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault& V) { + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault &V) { setValue(V); return *this; } + private: void anchor() override; }; -template<> -struct OptionValue<std::string> : OptionValueCopy<std::string> { +template <> struct OptionValue<std::string> : OptionValueCopy<std::string> { typedef StringRef WrapperType; OptionValue() {} - OptionValue(const std::string& V) { - this->setValue(V); - } - OptionValue<std::string> &operator=(const std::string& V) { + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue<std::string> &operator=(const std::string &V) { setValue(V); return *this; } + private: void anchor() override; }; @@ -476,20 +462,20 @@ private: // #define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC #define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC -#define clEnumValEnd (reinterpret_cast<void*>(0)) +#define clEnumValEnd (reinterpret_cast<void *>(0)) // values - For custom data types, allow specifying a group of values together // as the values that go into the mapping that the option handler uses. Note // that the values list must always have a 0 at the end of the list to indicate // that the list has ended. // -template<class DataType> -class ValuesClass { +template <class DataType> class ValuesClass { // Use a vector instead of a map, because the lists should be short, // the overhead is less, and most importantly, it keeps them in the order // inserted so we can print our option out nicely. - SmallVector<std::pair<const char *, std::pair<int, const char *> >,4> Values; + SmallVector<std::pair<const char *, std::pair<int, const char *>>, 4> Values; void processValues(va_list Vals); + public: ValuesClass(const char *EnumName, DataType Val, const char *Desc, va_list ValueArgs) { @@ -500,27 +486,26 @@ public: while (const char *enumName = va_arg(ValueArgs, const char *)) { DataType EnumVal = static_cast<DataType>(va_arg(ValueArgs, int)); const char *EnumDesc = va_arg(ValueArgs, const char *); - Values.push_back(std::make_pair(enumName, // Add value to value map + Values.push_back(std::make_pair(enumName, // Add value to value map std::make_pair(EnumVal, EnumDesc))); } } - template<class Opt> - void apply(Opt &O) const { + template <class Opt> void apply(Opt &O) const { for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); } }; -template<class DataType> -ValuesClass<DataType> END_WITH_NULL values(const char *Arg, DataType Val, - const char *Desc, ...) { - va_list ValueArgs; - va_start(ValueArgs, Desc); - ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs); - va_end(ValueArgs); - return Vals; +template <class DataType> +ValuesClass<DataType> LLVM_END_WITH_NULL +values(const char *Arg, DataType Val, const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; } //===----------------------------------------------------------------------===// @@ -539,13 +524,14 @@ class generic_parser_base { protected: class GenericOptionInfo { public: - GenericOptionInfo(const char *name, const char *helpStr) : - Name(name), HelpStr(helpStr) {} + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} const char *Name; const char *HelpStr; }; + public: - virtual ~generic_parser_base() {} // Base class should have virtual-dtor + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to // indicate how many entries are in Values. @@ -576,7 +562,7 @@ public: // // Template definition ensures that the option and default have the same // DataType (via the same AnyOptionValue). - template<class AnyOptionValue> + template <class AnyOptionValue> void printOptionDiff(const Option &O, const AnyOptionValue &V, const AnyOptionValue &Default, size_t GlobalWidth) const { @@ -590,7 +576,7 @@ public: hasArgStr = O.hasArgStr(); } - void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. @@ -599,7 +585,6 @@ public: OptionNames.push_back(getOption(i)); } - enum ValueExpected getValueExpectedFlagDefault() const { // If there is an ArgStr specified, then we are of the form: // @@ -633,16 +618,16 @@ protected: // command line option for -help. Because this is a simple mapping parser, the // data type can be any unsupported type. // -template <class DataType> -class parser : public generic_parser_base { +template <class DataType> class parser : public generic_parser_base { protected: class OptionInfo : public GenericOptionInfo { public: - OptionInfo(const char *name, DataType v, const char *helpStr) : - GenericOptionInfo(name, helpStr), V(v) {} + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} OptionValue<DataType> V; }; SmallVector<OptionInfo, 8> Values; + public: typedef DataType parser_data_type; @@ -690,14 +675,14 @@ public: void removeLiteralOption(const char *Name) { unsigned N = findOption(Name); assert(N != Values.size() && "Option not found!"); - Values.erase(Values.begin()+N); + Values.erase(Values.begin() + N); } }; //-------------------------------------------------- // basic_parser - Super class of parsers to provide boilerplate code // -class basic_parser_impl { // non-template implementation of basic_parser<t> +class basic_parser_impl { // non-template implementation of basic_parser<t> public: virtual ~basic_parser_impl() {} @@ -705,7 +690,7 @@ public: return ValueRequired; } - void getExtraOptionNames(SmallVectorImpl<const char*> &) {} + void getExtraOptionNames(SmallVectorImpl<const char *> &) {} void initialize(Option &) {} @@ -735,8 +720,7 @@ protected: // basic_parser - The real basic parser is just a template wrapper that provides // a typedef for the provided data type. // -template<class DataType> -class basic_parser : public basic_parser_impl { +template <class DataType> class basic_parser : public basic_parser_impl { public: typedef DataType parser_data_type; typedef OptionValue<DataType> OptVal; @@ -745,18 +729,14 @@ public: //-------------------------------------------------- // parser<bool> // -template<> -class parser<bool> : public basic_parser<bool> { +template <> class parser<bool> : public basic_parser<bool> { const char *ArgStr; -public: +public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template <class Opt> - void initialize(Opt &O) { - ArgStr = O.ArgStr; - } + template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; } enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -776,8 +756,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); //-------------------------------------------------- // parser<boolOrDefault> -template<> -class parser<boolOrDefault> : public basic_parser<boolOrDefault> { +template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -801,8 +780,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); //-------------------------------------------------- // parser<int> // -template<> -class parser<int> : public basic_parser<int> { +template <> class parser<int> : public basic_parser<int> { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -819,12 +797,10 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); - //-------------------------------------------------- // parser<unsigned> // -template<> -class parser<unsigned> : public basic_parser<unsigned> { +template <> class parser<unsigned> : public basic_parser<unsigned> { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -844,7 +820,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); //-------------------------------------------------- // parser<unsigned long long> // -template<> +template <> class parser<unsigned long long> : public basic_parser<unsigned long long> { public: // parse - Return true on error. @@ -866,8 +842,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); //-------------------------------------------------- // parser<double> // -template<> -class parser<double> : public basic_parser<double> { +template <> class parser<double> : public basic_parser<double> { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -887,8 +862,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); //-------------------------------------------------- // parser<float> // -template<> -class parser<float> : public basic_parser<float> { +template <> class parser<float> : public basic_parser<float> { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -908,8 +882,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); //-------------------------------------------------- // parser<std::string> // -template<> -class parser<std::string> : public basic_parser<std::string> { +template <> class parser<std::string> : public basic_parser<std::string> { public: // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { @@ -932,8 +905,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); //-------------------------------------------------- // parser<char> // -template<> -class parser<char> : public basic_parser<char> { +template <> class parser<char> : public basic_parser<char> { public: // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { @@ -960,7 +932,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>); // parser to handle all the template nastiness. // This overloaded function is selected by the generic parser. -template<class ParserClass, class DT> +template <class ParserClass, class DT> void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, const OptionValue<DT> &Default, size_t GlobalWidth) { OptionValue<DT> OV = V; @@ -969,18 +941,16 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. -template<class ParserDT, class ValDT> -struct OptionDiffPrinter { - void print(const Option &O, const parser<ParserDT> P, const ValDT &/*V*/, - const OptionValue<ValDT> &/*Default*/, size_t GlobalWidth) { +template <class ParserDT, class ValDT> struct OptionDiffPrinter { + void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/, + const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } }; // This is instantiated for basic parsers when the parsed value has the same // type as the option value. -template<class DT> -struct OptionDiffPrinter<DT, DT> { +template <class DT> struct OptionDiffPrinter<DT, DT> { void print(const Option &O, const parser<DT> P, const DT &V, const OptionValue<DT> &Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); @@ -989,15 +959,14 @@ struct OptionDiffPrinter<DT, DT> { // This overloaded function is selected by the basic parser, which may parse a // different type than the option type. -template<class ParserClass, class ValDT> +template <class ParserClass, class ValDT> void printOptionDiff( - const Option &O, - const basic_parser<typename ParserClass::parser_data_type> &P, - const ValDT &V, const OptionValue<ValDT> &Default, - size_t GlobalWidth) { + const Option &O, + const basic_parser<typename ParserClass::parser_data_type> &P, + const ValDT &V, const OptionValue<ValDT> &Default, size_t GlobalWidth) { OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer; - printer.print(O, static_cast<const ParserClass&>(P), V, Default, + printer.print(O, static_cast<const ParserClass &>(P), V, Default, GlobalWidth); } @@ -1007,46 +976,47 @@ void printOptionDiff( // not correctly respond to the apply method). Because the syntax to use this // is a pain, we have the 'apply' method below to handle the nastiness... // -template<class Mod> struct applicator { - template<class Opt> - static void opt(const Mod &M, Opt &O) { M.apply(O); } +template <class Mod> struct applicator { + template <class Opt> static void opt(const Mod &M, Opt &O) { M.apply(O); } }; // Handle const char* as a special case... -template<unsigned n> struct applicator<char[n]> { - template<class Opt> - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <unsigned n> struct applicator<char[n]> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<unsigned n> struct applicator<const char[n]> { - template<class Opt> - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <unsigned n> struct applicator<const char[n]> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator<const char*> { - template<class Opt> - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <> struct applicator<const char *> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator<NumOccurrencesFlag> { +template <> struct applicator<NumOccurrencesFlag> { static void opt(NumOccurrencesFlag N, Option &O) { O.setNumOccurrencesFlag(N); } }; -template<> struct applicator<ValueExpected> { +template <> struct applicator<ValueExpected> { static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } }; -template<> struct applicator<OptionHidden> { +template <> struct applicator<OptionHidden> { static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } }; -template<> struct applicator<FormattingFlags> { +template <> struct applicator<FormattingFlags> { static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } }; -template<> struct applicator<MiscFlags> { +template <> struct applicator<MiscFlags> { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; // apply method - Apply a modifier to an option in a type safe way. -template<class Mod, class Opt> -void apply(const Mod &M, Opt *O) { +template <class Mod, class Opt> void apply(const Mod &M, Opt *O) { applicator<Mod>::opt(M, *O); } @@ -1057,16 +1027,17 @@ void apply(const Mod &M, Opt *O) { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template<class DataType, bool ExternalStorage, bool isClass> +template <class DataType, bool ExternalStorage, bool isClass> class opt_storage { - DataType *Location; // Where to store the object... + DataType *Location; // Where to store the object... OptionValue<DataType> Default; void check_location() const { assert(Location && "cl::location(...) not specified for a command " - "line option with external storage, " - "or cl::init specified before cl::location()!!"); + "line option with external storage, " + "or cl::init specified before cl::location()!!"); } + public: opt_storage() : Location(nullptr) {} @@ -1078,16 +1049,21 @@ public: return false; } - template<class T> - void setValue(const T &V, bool initial = false) { + template <class T> void setValue(const T &V, bool initial = false) { check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check_location(); return *Location; } - const DataType &getValue() const { check_location(); return *Location; } + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; + } operator DataType() const { return this->getValue(); } @@ -1098,13 +1074,12 @@ public: // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template<class DataType> -class opt_storage<DataType,false,true> : public DataType { +template <class DataType> +class opt_storage<DataType, false, true> : public DataType { public: OptionValue<DataType> Default; - template<class T> - void setValue(const T &V, bool initial = false) { + template <class T> void setValue(const T &V, bool initial = false) { DataType::operator=(V); if (initial) Default = V; @@ -1120,8 +1095,7 @@ public: // this case, we store an instance through containment, and overload operators // to get at the value. // -template<class DataType> -class opt_storage<DataType, false, false> { +template <class DataType> class opt_storage<DataType, false, false> { public: DataType Value; OptionValue<DataType> Default; @@ -1130,8 +1104,7 @@ public: // type. opt_storage() : Value(DataType()), Default(DataType()) {} - template<class T> - void setValue(const T &V, bool initial = false) { + template <class T> void setValue(const T &V, bool initial = false) { Value = V; if (initial) Default = V; @@ -1147,12 +1120,11 @@ public: DataType operator->() const { return Value; } }; - //===----------------------------------------------------------------------===// // opt - A scalar command line option. // template <class DataType, bool ExternalStorage = false, - class ParserClass = parser<DataType> > + class ParserClass = parser<DataType>> class opt : public Option, public opt_storage<DataType, ExternalStorage, std::is_class<DataType>::value> { @@ -1161,9 +1133,9 @@ class opt : public Option, bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse error! + return true; // Parse error! this->setValue(Val); this->setPosition(pos); return false; @@ -1172,20 +1144,23 @@ class opt : public Option, enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { - cl::printOptionDiff<ParserClass>( - *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); + cl::printOptionDiff<ParserClass>(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); } } @@ -1193,81 +1168,107 @@ class opt : public Option, addArgument(); Parser.initialize(*this); } + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } - template<class T> - DataType &operator=(const T &Val) { + template <class T> DataType &operator=(const T &Val) { this->setValue(Val); return this->getValue(); } // One option... - template<class M0t> - explicit opt(const M0t &M0) : Option(Optional, NotHidden) { + template <class M0t> + explicit opt(const M0t &M0) + : Option(Optional, NotHidden) { apply(M0, this); done(); } // Two options... - template<class M0t, class M1t> - opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); + template <class M0t, class M1t> + opt(const M0t &M0, const M1t &M1) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template<class M0t, class M1t, class M2t> - opt(const M0t &M0, const M1t &M1, - const M2t &M2) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + template <class M0t, class M1t, class M2t> + opt(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template<class M0t, class M1t, class M2t, class M3t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, - const M3t &M3) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template <class M0t, class M1t, class M2t, class M3t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template<class M0t, class M1t, class M2t, class M3t, class M4t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template <class M0t, class M1t, class M2t, class M3t, class M4t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, - const M6t &M6) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5, const M6t &M6) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t, class M7t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t, class M7t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5, const M6t &M6, const M7t &M7) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1285,9 +1286,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>); // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template<class DataType, class StorageClass> -class list_storage { - StorageClass *Location; // Where to store the object... +template <class DataType, class StorageClass> class list_storage { + StorageClass *Location; // Where to store the object... public: list_storage() : Location(0) {} @@ -1299,32 +1299,30 @@ public: return false; } - template<class T> - void addValue(const T &V) { + template <class T> void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); Location->push_back(V); } }; - // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template<class DataType> +template <class DataType> class list_storage<DataType, bool> : public std::vector<DataType> { public: - template<class T> - void addValue(const T &V) { std::vector<DataType>::push_back(V); } + template <class T> void addValue(const T &V) { + std::vector<DataType>::push_back(V); + } }; - //===----------------------------------------------------------------------===// // list - A list of command line options. // template <class DataType, class Storage = bool, - class ParserClass = parser<DataType> > + class ParserClass = parser<DataType>> class list : public Option, public list_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; @@ -1332,16 +1330,17 @@ class list : public Option, public list_storage<DataType, Storage> { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! list_storage<DataType, Storage>::addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1349,19 +1348,22 @@ class list : public Option, public list_storage<DataType, Storage> { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); Parser.initialize(*this); } + public: ParserClass &getParser() { return Parser; } @@ -1370,71 +1372,96 @@ public: return Positions[optnum]; } - void setNumAdditionalVals(unsigned n) { - Option::setNumAdditionalVals(n); - } + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } // One option... - template<class M0t> - explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) { + template <class M0t> + explicit list(const M0t &M0) + : Option(ZeroOrMore, NotHidden) { apply(M0, this); done(); } // Two options... - template<class M0t, class M1t> - list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); + template <class M0t, class M1t> + list(const M0t &M0, const M1t &M1) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template<class M0t, class M1t, class M2t> + template <class M0t, class M1t, class M2t> list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template<class M0t, class M1t, class M2t, class M3t> + template <class M0t, class M1t, class M2t, class M3t> list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template<class M0t, class M1t, class M2t, class M3t, class M4t> + template <class M0t, class M1t, class M2t, class M3t, class M4t> list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + const M4t &M4) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + const M4t &M4, const M5t &M5) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t> list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t, class M7t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t, class M7t> list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1445,10 +1472,11 @@ struct multi_val { explicit multi_val(unsigned N) : AdditionalVals(N) {} template <typename D, typename S, typename P> - void apply(list<D, S, P> &L) const { L.setNumAdditionalVals(AdditionalVals); } + void apply(list<D, S, P> &L) const { + L.setNumAdditionalVals(AdditionalVals); + } }; - //===----------------------------------------------------------------------===// // bits_storage class @@ -1456,15 +1484,13 @@ struct multi_val { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template<class DataType, class StorageClass> -class bits_storage { - unsigned *Location; // Where to store the bits... +template <class DataType, class StorageClass> class bits_storage { + unsigned *Location; // Where to store the bits... - template<class T> - static unsigned Bit(const T &V) { + template <class T> static unsigned Bit(const T &V) { unsigned BitPos = reinterpret_cast<unsigned>(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } @@ -1478,57 +1504,45 @@ public: return false; } - template<class T> - void addValue(const T &V) { + template <class T> void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); *Location |= Bit(V); } unsigned getBits() { return *Location; } - template<class T> - bool isSet(const T &V) { + template <class T> bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } }; - // Define how to hold bits. Since we can inherit from a class, we do so. // This makes us exactly compatible with the bits in all cases that it is used. // -template<class DataType> -class bits_storage<DataType, bool> { - unsigned Bits; // Where to store the bits... +template <class DataType> class bits_storage<DataType, bool> { + unsigned Bits; // Where to store the bits... - template<class T> - static unsigned Bit(const T &V) { + template <class T> static unsigned Bit(const T &V) { unsigned BitPos = (unsigned)V; assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - template<class T> - void addValue(const T &V) { - Bits |= Bit(V); - } + template <class T> void addValue(const T &V) { Bits |= Bit(V); } unsigned getBits() { return Bits; } - template<class T> - bool isSet(const T &V) { - return (Bits & Bit(V)) != 0; - } + template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; - //===----------------------------------------------------------------------===// // bits - A bit vector of command options. // template <class DataType, class Storage = bool, - class ParserClass = parser<DataType> > + class ParserClass = parser<DataType>> class bits : public Option, public bits_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; @@ -1536,16 +1550,17 @@ class bits : public Option, public bits_storage<DataType, Storage> { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! this->addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1553,19 +1568,22 @@ class bits : public Option, public bits_storage<DataType, Storage> { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); Parser.initialize(*this); } + public: ParserClass &getParser() { return Parser; } @@ -1575,66 +1593,93 @@ public: } // One option... - template<class M0t> - explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) { + template <class M0t> + explicit bits(const M0t &M0) + : Option(ZeroOrMore, NotHidden) { apply(M0, this); done(); } // Two options... - template<class M0t, class M1t> - bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); + template <class M0t, class M1t> + bits(const M0t &M0, const M1t &M1) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template<class M0t, class M1t, class M2t> + template <class M0t, class M1t, class M2t> bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template<class M0t, class M1t, class M2t, class M3t> + template <class M0t, class M1t, class M2t, class M3t> bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template<class M0t, class M1t, class M2t, class M3t, class M4t> + template <class M0t, class M1t, class M2t, class M3t, class M4t> bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + const M4t &M4) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + const M4t &M4, const M5t &M5) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t> bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template<class M0t, class M1t, class M2t, class M3t, - class M4t, class M5t, class M6t, class M7t> + template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, + class M6t, class M7t> bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1646,11 +1691,11 @@ public: class alias : public Option { Option *AliasFor; bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) override { + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } - bool addOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Value, bool MultiArg = false) override { + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); } // Handle printing stuff... @@ -1658,8 +1703,8 @@ class alias : public Option { void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } ValueExpected getValueExpectedFlagDefault() const override { return AliasFor->getValueExpectedFlag(); @@ -1670,8 +1715,9 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); - addArgument(); + addArgument(); } + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1680,30 +1726,37 @@ public: } // One option... - template<class M0t> - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { + template <class M0t> + explicit alias(const M0t &M0) + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); done(); } // Two options... - template<class M0t, class M1t> + template <class M0t, class M1t> alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template<class M0t, class M1t, class M2t> + template <class M0t, class M1t, class M2t> alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template<class M0t, class M1t, class M2t, class M3t> + template <class M0t, class M1t, class M2t, class M3t> alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } }; @@ -1720,8 +1773,8 @@ struct aliasopt { // printed to stderr at the end of the regular help, just before // exit is called. struct extrahelp { - const char * morehelp; - explicit extrahelp(const char* help); + const char *morehelp; + explicit extrahelp(const char *help); }; void PrintVersionMessage(); @@ -1733,8 +1786,7 @@ void PrintVersionMessage(); /// /// \param Hidden if true will print hidden options /// \param Categorized if true print options in categories -void PrintHelpMessage(bool Hidden=false, bool Categorized=false); - +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. @@ -1766,7 +1818,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap<Option*> &Map); +void getRegisteredOptions(StringMap<Option *> &Map); //===----------------------------------------------------------------------===// // Standalone command line processing utilities. @@ -1776,9 +1828,10 @@ void getRegisteredOptions(StringMap<Option*> &Map); /// raw character pointer. class StringSaver { virtual void anchor(); + public: virtual const char *SaveString(const char *Str) = 0; - virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor. + virtual ~StringSaver(){}; // Pacify -Wnon-virtual-dtor. }; /// \brief Tokenizes a command line that can contain escapes and quotes. @@ -1790,9 +1843,12 @@ public: /// /// \param [in] Source The string to be split on whitespace with quotes. /// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] MarkEOLs true if tokenizing a response file and you want end of +/// lines and end of the response file to be marked with a nullptr string. /// \param [out] NewArgv All parsed strings are appended to NewArgv. void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv); + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false); /// \brief Tokenizes a Windows command line which may contain quotes and escaped /// quotes. @@ -1802,25 +1858,36 @@ void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, /// /// \param [in] Source The string to be split on whitespace with quotes. /// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] MarkEOLs true if tokenizing a response file and you want end of +/// lines and end of the response file to be marked with a nullptr string. /// \param [out] NewArgv All parsed strings are appended to NewArgv. void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv); + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false); /// \brief String tokenization function type. Should be compatible with either /// Windows or Unix command line tokenizers. typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv); + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs); /// \brief Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. Argv should contain the command line -/// before expansion and will be modified in place. +/// before expansion and will be modified in place. If requested, Argv will +/// also be populated with nullptrs indicating where each response file line +/// ends, which is useful for the "/link" argument that needs to consume all +/// remaining arguments only until the next end of line, when in a response +/// file. /// /// \param [in] Saver Delegates back to the caller for saving parsed strings. /// \param [in] Tokenizer Tokenization strategy. Typically Unix or Windows. /// \param [in,out] Argv Command line into which to expand response files. +/// \param [in] MarkEOLs Mark end of lines and the end of the response file +/// with nullptrs in the Argv vector. /// \return true if all @files were expanded successfully or there were none. bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl<const char *> &Argv); + SmallVectorImpl<const char *> &Argv, + bool MarkEOLs = false); } // End namespace cl diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 25bf32ade5f8..d008fec89d64 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -33,14 +33,19 @@ # define __has_builtin(x) 0 #endif -/// \macro __GNUC_PREREQ -/// \brief Defines __GNUC_PREREQ if glibc's features.h isn't available. -#ifndef __GNUC_PREREQ -# if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +/// \macro LLVM_GNUC_PREREQ +/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't +/// available. +#ifndef LLVM_GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ + ((maj) << 20) + ((min) << 10) + (patch)) +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) # else -# define __GNUC_PREREQ(maj, min) 0 +# define LLVM_GNUC_PREREQ(maj, min, patch) 0 # endif #endif @@ -61,7 +66,7 @@ #define LLVM_MSC_PREREQ(version) 0 #endif -#ifndef _MSC_VER +#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) #define LLVM_NOEXCEPT noexcept #else #define LLVM_NOEXCEPT @@ -70,10 +75,8 @@ /// \brief Does the compiler support r-value reference *this? /// /// Sadly, this is separate from just r-value reference support because GCC -/// implemented everything but this thus far. No release of GCC yet has support -/// for this feature so it is enabled with Clang only. -/// FIXME: This should change to a version check when GCC grows support for it. -#if __has_feature(cxx_rvalue_references) +/// implemented this later than everything else. +#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) #define LLVM_HAS_RVALUE_REFERENCE_THIS 1 #else #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 @@ -128,20 +131,26 @@ /// not accessible from outside it. Can also be used to mark variables and /// functions, making them private to any shared library they are linked into. /// On PE/COFF targets, library visibility is the default, so this isn't needed. -#if (__has_attribute(visibility) || __GNUC_PREREQ(4, 0)) && \ +#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) #define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) #else #define LLVM_LIBRARY_VISIBILITY #endif -#if __has_attribute(used) || __GNUC_PREREQ(3, 1) +#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) +#define LLVM_END_WITH_NULL __attribute__((sentinel)) +#else +#define LLVM_END_WITH_NULL +#endif + +#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) #define LLVM_ATTRIBUTE_USED __attribute__((__used__)) #else #define LLVM_ATTRIBUTE_USED #endif -#if __has_attribute(warn_unused_result) || __GNUC_PREREQ(3, 4) +#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) #define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) #else #define LLVM_ATTRIBUTE_UNUSED_RESULT @@ -155,14 +164,14 @@ // more portable solution: // (void)unused_var_name; // Prefer cast-to-void wherever it is sufficient. -#if __has_attribute(unused) || __GNUC_PREREQ(3, 1) +#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) #define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) #else #define LLVM_ATTRIBUTE_UNUSED #endif // FIXME: Provide this for PE/COFF targets. -#if (__has_attribute(weak) || __GNUC_PREREQ(4, 0)) && \ +#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) #define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) #else @@ -185,7 +194,7 @@ #define LLVM_READONLY #endif -#if __has_builtin(__builtin_expect) || __GNUC_PREREQ(4, 0) +#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) #define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) #define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) #else @@ -208,7 +217,7 @@ /// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, /// mark a method "not for inlining". -#if __has_attribute(noinline) || __GNUC_PREREQ(3, 4) +#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) @@ -220,7 +229,7 @@ /// so, mark a method "always inline" because it is performance sensitive. GCC /// 3.4 supported this but is buggy in various cases and produces unimplemented /// errors, just use it in GCC 4.0 and later. -#if __has_attribute(always_inline) || __GNUC_PREREQ(4, 0) +#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) #define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline @@ -236,6 +245,12 @@ #define LLVM_ATTRIBUTE_NORETURN #endif +#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) +#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define LLVM_ATTRIBUTE_RETURNS_NONNULL +#endif + /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress /// pedantic diagnostics. #ifdef __GNUC__ @@ -262,7 +277,7 @@ /// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands /// to an expression which states that it is undefined behavior for the /// compiler to reach this point. Otherwise is not defined. -#if __has_builtin(__builtin_unreachable) || __GNUC_PREREQ(4, 5) +#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) # define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() #elif defined(_MSC_VER) # define LLVM_BUILTIN_UNREACHABLE __assume(false) @@ -270,7 +285,7 @@ /// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression /// which causes the program to exit abnormally. -#if __has_builtin(__builtin_trap) || __GNUC_PREREQ(4, 3) +#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) # define LLVM_BUILTIN_TRAP __builtin_trap() #else # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 @@ -278,7 +293,7 @@ /// \macro LLVM_ASSUME_ALIGNED /// \brief Returns a pointer with an assumed alignment. -#if __has_builtin(__builtin_assume_aligned) && __GNUC_PREREQ(4, 7) +#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) # define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) #elif defined(LLVM_BUILTIN_UNREACHABLE) // As of today, clang does not support __builtin_assume_aligned. diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index 8152b60eb098..88727fa3fcfc 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -14,9 +14,9 @@ #ifndef LLVM_SUPPORT_COMPRESSION_H #define LLVM_SUPPORT_COMPRESSION_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include <memory> -#include "llvm/ADT/SmallVector.h" namespace llvm { diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 3869ebdc4a93..1f3965c8ade4 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -10,9 +10,8 @@ #ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H #define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H -#include <string> - #include "llvm/ADT/STLExtras.h" +#include <string> namespace llvm { class StringRef; @@ -166,9 +165,7 @@ public: : CrashRecoveryContextCleanupBase< CrashRecoveryContextDeleteCleanup<T>, T>(context, resource) {} - virtual void recoverResources() { - delete this->resource; - } + void recoverResources() override { delete this->resource; } }; template <typename T> @@ -181,9 +178,7 @@ public: : CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T>(context, resource) {} - virtual void recoverResources() { - this->resource->Release(); - } + void recoverResources() override { this->resource->Release(); } }; template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> > diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index e8a19cd773b5..48235d4145bd 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -348,6 +348,17 @@ public: bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const { return offset + length >= offset && isValidOffset(offset + length - 1); } + + /// Test the availability of enough bytes of data for a pointer from + /// \a offset. The size of a pointer is \a getAddressSize(). + /// + /// @return + /// \b true if \a offset is a valid offset and there are enough + /// bytes for a pointer available at that offset, \b false + /// otherwise. + bool isValidOffsetForAddress(uint32_t offset) const { + return isValidOffsetForDataOfSize(offset, AddressSize); + } }; } // namespace llvm diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index 1f0c8eba5e11..c90bf51afaee 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -101,6 +101,13 @@ typedef signed int ssize_t; #define PRIu64 "I64u" #define PRIx64 "I64x" #define PRIX64 "I64X" + +#define PRId32 "d" +#define PRIi32 "i" +#define PRIo32 "o" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" #endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ @@ -116,12 +123,6 @@ typedef signed int ssize_t; # define UINT64_MAX 0xffffffffffffffffULL #endif -#if __GNUC__ > 3 -#define END_WITH_NULL __attribute__((sentinel)) -#else -#define END_WITH_NULL -#endif - #ifndef HUGE_VALF #define HUGE_VALF (float)HUGE_VAL #endif diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index 09cfcdf3b56b..b8b2ba56ff30 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -116,12 +116,6 @@ typedef signed int ssize_t; # define UINT64_MAX 0xffffffffffffffffULL #endif -#if __GNUC__ > 3 -#define END_WITH_NULL __attribute__((sentinel)) -#else -#define END_WITH_NULL -#endif - #ifndef HUGE_VALF #define HUGE_VALF (float)HUGE_VAL #endif diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index cd9f75600cbc..47b00b1f09d8 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -7,9 +7,13 @@ // //===----------------------------------------------------------------------===// // -// This file contains constants used for implementing Dwarf debug support. For -// Details on the Dwarf 3 specfication see DWARF Debugging Information Format -// V.3 reference manual http://dwarf.freestandards.org , +// \file +// \brief This file contains constants used for implementing Dwarf +// debug support. +// +// For details on the Dwarf specfication see the latest DWARF Debugging +// Information Format standard document on http://www.dwarfstd.org. This +// file often includes support for non-released standard features. // //===----------------------------------------------------------------------===// @@ -21,22 +25,6 @@ namespace llvm { -//===----------------------------------------------------------------------===// -// Debug info constants. - -enum : uint32_t { - LLVMDebugVersion = (12 << 16), // Current version of debug information. - LLVMDebugVersion11 = (11 << 16), // Constant for version 11. - LLVMDebugVersion10 = (10 << 16), // Constant for version 10. - LLVMDebugVersion9 = (9 << 16), // Constant for version 9. - LLVMDebugVersion8 = (8 << 16), // Constant for version 8. - LLVMDebugVersion7 = (7 << 16), // Constant for version 7. - LLVMDebugVersion6 = (6 << 16), // Constant for version 6. - LLVMDebugVersion5 = (5 << 16), // Constant for version 5. - LLVMDebugVersion4 = (4 << 16), // Constant for version 4. - LLVMDebugVersionMask = 0xffff0000 // Mask for version number. -}; - namespace dwarf { //===----------------------------------------------------------------------===// @@ -53,6 +41,7 @@ enum LLVMConstants : uint32_t { DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. DW_TAG_arg_variable = 0x101, // Tag for argument variables. + DW_TAG_expression = 0x102, // Tag for complex address expressions. DW_TAG_user_base = 0x1000, // Recommended base for user tags. @@ -779,100 +768,24 @@ enum LocationListEntry : unsigned char { DW_LLE_offset_pair_entry }; +/// Contstants for the DW_APPLE_PROPERTY_attributes attribute. +/// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind. enum ApplePropertyAttributes { // Apple Objective-C Property Attributes DW_APPLE_PROPERTY_readonly = 0x01, - DW_APPLE_PROPERTY_readwrite = 0x02, + DW_APPLE_PROPERTY_getter = 0x02, DW_APPLE_PROPERTY_assign = 0x04, - DW_APPLE_PROPERTY_retain = 0x08, - DW_APPLE_PROPERTY_copy = 0x10, - DW_APPLE_PROPERTY_nonatomic = 0x20 + DW_APPLE_PROPERTY_readwrite = 0x08, + DW_APPLE_PROPERTY_retain = 0x10, + DW_APPLE_PROPERTY_copy = 0x20, + DW_APPLE_PROPERTY_nonatomic = 0x40, + DW_APPLE_PROPERTY_setter = 0x80, + DW_APPLE_PROPERTY_atomic = 0x100, + DW_APPLE_PROPERTY_weak = 0x200, + DW_APPLE_PROPERTY_strong = 0x400, + DW_APPLE_PROPERTY_unsafe_unretained = 0x800 }; -/// TagString - Return the string for the specified tag. -/// -const char *TagString(unsigned Tag); - -/// ChildrenString - Return the string for the specified children flag. -/// -const char *ChildrenString(unsigned Children); - -/// AttributeString - Return the string for the specified attribute. -/// -const char *AttributeString(unsigned Attribute); - -/// FormEncodingString - Return the string for the specified form encoding. -/// -const char *FormEncodingString(unsigned Encoding); - -/// OperationEncodingString - Return the string for the specified operation -/// encoding. -const char *OperationEncodingString(unsigned Encoding); - -/// AttributeEncodingString - Return the string for the specified attribute -/// encoding. -const char *AttributeEncodingString(unsigned Encoding); - -/// DecimalSignString - Return the string for the specified decimal sign -/// attribute. -const char *DecimalSignString(unsigned Sign); - -/// EndianityString - Return the string for the specified endianity. -/// -const char *EndianityString(unsigned Endian); - -/// AccessibilityString - Return the string for the specified accessibility. -/// -const char *AccessibilityString(unsigned Access); - -/// VisibilityString - Return the string for the specified visibility. -/// -const char *VisibilityString(unsigned Visibility); - -/// VirtualityString - Return the string for the specified virtuality. -/// -const char *VirtualityString(unsigned Virtuality); - -/// LanguageString - Return the string for the specified language. -/// -const char *LanguageString(unsigned Language); - -/// CaseString - Return the string for the specified identifier case. -/// -const char *CaseString(unsigned Case); - -/// ConventionString - Return the string for the specified calling convention. -/// -const char *ConventionString(unsigned Convention); - -/// InlineCodeString - Return the string for the specified inline code. -/// -const char *InlineCodeString(unsigned Code); - -/// ArrayOrderString - Return the string for the specified array order. -/// -const char *ArrayOrderString(unsigned Order); - -/// DiscriminantString - Return the string for the specified discriminant -/// descriptor. -const char *DiscriminantString(unsigned Discriminant); - -/// LNStandardString - Return the string for the specified line number standard. -/// -const char *LNStandardString(unsigned Standard); - -/// LNExtendedString - Return the string for the specified line number extended -/// opcode encodings. -const char *LNExtendedString(unsigned Encoding); - -/// MacinfoString - Return the string for the specified macinfo type encodings. -/// -const char *MacinfoString(unsigned Encoding); - -/// CallFrameString - Return the string for the specified call frame instruction -/// encodings. -const char *CallFrameString(unsigned Encoding); - // Constants for the DWARF5 Accelerator Table Proposal enum AcceleratorTable { // Data layout descriptors. @@ -895,9 +808,6 @@ enum AcceleratorTable { DW_hash_function_djb = 0u }; -/// AtomTypeString - Return the string for the specified Atom type. -const char *AtomTypeString(unsigned Atom); - // Constants for the GNU pubnames/pubtypes extensions supporting gdb index. enum GDBIndexEntryKind { GIEK_NONE, @@ -910,15 +820,51 @@ enum GDBIndexEntryKind { GIEK_UNUSED7 }; -const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); - enum GDBIndexEntryLinkage { GIEL_EXTERNAL, GIEL_STATIC }; +/// \defgroup DwarfConstantsDumping Dwarf constants dumping functions +/// +/// All these functions map their argument's value back to the +/// corresponding enumerator name or return nullptr if the value isn't +/// known. +/// +/// @{ +const char *TagString(unsigned Tag); +const char *ChildrenString(unsigned Children); +const char *AttributeString(unsigned Attribute); +const char *FormEncodingString(unsigned Encoding); +const char *OperationEncodingString(unsigned Encoding); +const char *AttributeEncodingString(unsigned Encoding); +const char *DecimalSignString(unsigned Sign); +const char *EndianityString(unsigned Endian); +const char *AccessibilityString(unsigned Access); +const char *VisibilityString(unsigned Visibility); +const char *VirtualityString(unsigned Virtuality); +const char *LanguageString(unsigned Language); +const char *CaseString(unsigned Case); +const char *ConventionString(unsigned Convention); +const char *InlineCodeString(unsigned Code); +const char *ArrayOrderString(unsigned Order); +const char *DiscriminantString(unsigned Discriminant); +const char *LNStandardString(unsigned Standard); +const char *LNExtendedString(unsigned Encoding); +const char *MacinfoString(unsigned Encoding); +const char *CallFrameString(unsigned Encoding); +const char *ApplePropertyString(unsigned); +const char *AtomTypeString(unsigned Atom); +const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); +/// @} +/// \brief Returns the symbolic string representing Val when used as a value +/// for attribute Attr. +const char *AttributeValueString(uint16_t Attr, unsigned Val); + +/// \brief Decsribes an entry of the various gnu_pub* debug sections. +/// /// The gnu_pub* kind looks like: /// /// 0-3 reserved @@ -950,6 +896,7 @@ private: }; }; + } // End of namespace dwarf } // End of namespace llvm diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index de47be62a795..a7d22212dbdb 100644 --- a/include/llvm/Support/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_DYNAMICLIBRARY_H -#define LLVM_SYSTEM_DYNAMICLIBRARY_H +#ifndef LLVM_SUPPORT_DYNAMICLIBRARY_H +#define LLVM_SUPPORT_DYNAMICLIBRARY_H #include <string> @@ -43,10 +43,11 @@ namespace sys { // Opaque data used to interface with OS-specific dynamic library handling. void *Data; - explicit DynamicLibrary(void *data = &Invalid) : Data(data) {} public: + explicit DynamicLibrary(void *data = &Invalid) : Data(data) {} + /// Returns true if the object refers to a valid library. - bool isValid() { return Data != &Invalid; } + bool isValid() const { return Data != &Invalid; } /// Searches through the library for the symbol \p symbolName. If it is /// found, the address of that symbol is returned. If not, NULL is returned. @@ -101,4 +102,4 @@ namespace sys { } // End sys namespace } // End llvm namespace -#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#endif diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 42abe8906ea3..3d49205fa168 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -350,150 +350,21 @@ enum { ELFOSABI_STANDALONE = 255 // Standalone (embedded) application }; +#define ELF_RELOC(name, value) name = value, + // X86_64 relocations. enum { - R_X86_64_NONE = 0, - R_X86_64_64 = 1, - R_X86_64_PC32 = 2, - R_X86_64_GOT32 = 3, - R_X86_64_PLT32 = 4, - R_X86_64_COPY = 5, - R_X86_64_GLOB_DAT = 6, - R_X86_64_JUMP_SLOT = 7, - R_X86_64_RELATIVE = 8, - R_X86_64_GOTPCREL = 9, - R_X86_64_32 = 10, - R_X86_64_32S = 11, - R_X86_64_16 = 12, - R_X86_64_PC16 = 13, - R_X86_64_8 = 14, - R_X86_64_PC8 = 15, - R_X86_64_DTPMOD64 = 16, - R_X86_64_DTPOFF64 = 17, - R_X86_64_TPOFF64 = 18, - R_X86_64_TLSGD = 19, - R_X86_64_TLSLD = 20, - R_X86_64_DTPOFF32 = 21, - R_X86_64_GOTTPOFF = 22, - R_X86_64_TPOFF32 = 23, - R_X86_64_PC64 = 24, - R_X86_64_GOTOFF64 = 25, - R_X86_64_GOTPC32 = 26, - R_X86_64_GOT64 = 27, - R_X86_64_GOTPCREL64 = 28, - R_X86_64_GOTPC64 = 29, - R_X86_64_GOTPLT64 = 30, - R_X86_64_PLTOFF64 = 31, - R_X86_64_SIZE32 = 32, - R_X86_64_SIZE64 = 33, - R_X86_64_GOTPC32_TLSDESC = 34, - R_X86_64_TLSDESC_CALL = 35, - R_X86_64_TLSDESC = 36, - R_X86_64_IRELATIVE = 37 +#include "ELFRelocs/x86_64.def" }; // i386 relocations. -// TODO: this is just a subset enum { - R_386_NONE = 0, - R_386_32 = 1, - R_386_PC32 = 2, - R_386_GOT32 = 3, - R_386_PLT32 = 4, - R_386_COPY = 5, - R_386_GLOB_DAT = 6, - R_386_JUMP_SLOT = 7, - R_386_RELATIVE = 8, - R_386_GOTOFF = 9, - R_386_GOTPC = 10, - R_386_32PLT = 11, - R_386_TLS_TPOFF = 14, - R_386_TLS_IE = 15, - R_386_TLS_GOTIE = 16, - R_386_TLS_LE = 17, - R_386_TLS_GD = 18, - R_386_TLS_LDM = 19, - R_386_16 = 20, - R_386_PC16 = 21, - R_386_8 = 22, - R_386_PC8 = 23, - R_386_TLS_GD_32 = 24, - R_386_TLS_GD_PUSH = 25, - R_386_TLS_GD_CALL = 26, - R_386_TLS_GD_POP = 27, - R_386_TLS_LDM_32 = 28, - R_386_TLS_LDM_PUSH = 29, - R_386_TLS_LDM_CALL = 30, - R_386_TLS_LDM_POP = 31, - R_386_TLS_LDO_32 = 32, - R_386_TLS_IE_32 = 33, - R_386_TLS_LE_32 = 34, - R_386_TLS_DTPMOD32 = 35, - R_386_TLS_DTPOFF32 = 36, - R_386_TLS_TPOFF32 = 37, - R_386_TLS_GOTDESC = 39, - R_386_TLS_DESC_CALL = 40, - R_386_TLS_DESC = 41, - R_386_IRELATIVE = 42, - R_386_NUM = 43 +#include "ELFRelocs/i386.def" }; // ELF Relocation types for PPC32 enum { - R_PPC_NONE = 0, /* No relocation. */ - R_PPC_ADDR32 = 1, - R_PPC_ADDR24 = 2, - R_PPC_ADDR16 = 3, - R_PPC_ADDR16_LO = 4, - R_PPC_ADDR16_HI = 5, - R_PPC_ADDR16_HA = 6, - R_PPC_ADDR14 = 7, - R_PPC_ADDR14_BRTAKEN = 8, - R_PPC_ADDR14_BRNTAKEN = 9, - R_PPC_REL24 = 10, - R_PPC_REL14 = 11, - R_PPC_REL14_BRTAKEN = 12, - R_PPC_REL14_BRNTAKEN = 13, - R_PPC_GOT16 = 14, - R_PPC_GOT16_LO = 15, - R_PPC_GOT16_HI = 16, - R_PPC_GOT16_HA = 17, - R_PPC_PLTREL24 = 18, - R_PPC_REL32 = 26, - R_PPC_TLS = 67, - R_PPC_DTPMOD32 = 68, - R_PPC_TPREL16 = 69, - R_PPC_TPREL16_LO = 70, - R_PPC_TPREL16_HI = 71, - R_PPC_TPREL16_HA = 72, - R_PPC_TPREL32 = 73, - R_PPC_DTPREL16 = 74, - R_PPC_DTPREL16_LO = 75, - R_PPC_DTPREL16_HI = 76, - R_PPC_DTPREL16_HA = 77, - R_PPC_DTPREL32 = 78, - R_PPC_GOT_TLSGD16 = 79, - R_PPC_GOT_TLSGD16_LO = 80, - R_PPC_GOT_TLSGD16_HI = 81, - R_PPC_GOT_TLSGD16_HA = 82, - R_PPC_GOT_TLSLD16 = 83, - R_PPC_GOT_TLSLD16_LO = 84, - R_PPC_GOT_TLSLD16_HI = 85, - R_PPC_GOT_TLSLD16_HA = 86, - R_PPC_GOT_TPREL16 = 87, - R_PPC_GOT_TPREL16_LO = 88, - R_PPC_GOT_TPREL16_HI = 89, - R_PPC_GOT_TPREL16_HA = 90, - R_PPC_GOT_DTPREL16 = 91, - R_PPC_GOT_DTPREL16_LO = 92, - R_PPC_GOT_DTPREL16_HI = 93, - R_PPC_GOT_DTPREL16_HA = 94, - R_PPC_TLSGD = 95, - R_PPC_TLSLD = 96, - R_PPC_REL16 = 249, - R_PPC_REL16_LO = 250, - R_PPC_REL16_HI = 251, - R_PPC_REL16_HA = 252 +#include "ELFRelocs/PowerPC.def" }; // Specific e_flags for PPC64 @@ -529,178 +400,12 @@ encodePPC64LocalEntryOffset(int64_t Offset) { // ELF Relocation types for PPC64 enum { - R_PPC64_NONE = 0, - R_PPC64_ADDR32 = 1, - R_PPC64_ADDR24 = 2, - R_PPC64_ADDR16 = 3, - R_PPC64_ADDR16_LO = 4, - R_PPC64_ADDR16_HI = 5, - R_PPC64_ADDR16_HA = 6, - R_PPC64_ADDR14 = 7, - R_PPC64_ADDR14_BRTAKEN = 8, - R_PPC64_ADDR14_BRNTAKEN = 9, - R_PPC64_REL24 = 10, - R_PPC64_REL14 = 11, - R_PPC64_REL14_BRTAKEN = 12, - R_PPC64_REL14_BRNTAKEN = 13, - R_PPC64_GOT16 = 14, - R_PPC64_GOT16_LO = 15, - R_PPC64_GOT16_HI = 16, - R_PPC64_GOT16_HA = 17, - R_PPC64_REL32 = 26, - R_PPC64_ADDR64 = 38, - R_PPC64_ADDR16_HIGHER = 39, - R_PPC64_ADDR16_HIGHERA = 40, - R_PPC64_ADDR16_HIGHEST = 41, - R_PPC64_ADDR16_HIGHESTA = 42, - R_PPC64_REL64 = 44, - R_PPC64_TOC16 = 47, - R_PPC64_TOC16_LO = 48, - R_PPC64_TOC16_HI = 49, - R_PPC64_TOC16_HA = 50, - R_PPC64_TOC = 51, - R_PPC64_ADDR16_DS = 56, - R_PPC64_ADDR16_LO_DS = 57, - R_PPC64_GOT16_DS = 58, - R_PPC64_GOT16_LO_DS = 59, - R_PPC64_TOC16_DS = 63, - R_PPC64_TOC16_LO_DS = 64, - R_PPC64_TLS = 67, - R_PPC64_DTPMOD64 = 68, - R_PPC64_TPREL16 = 69, - R_PPC64_TPREL16_LO = 70, - R_PPC64_TPREL16_HI = 71, - R_PPC64_TPREL16_HA = 72, - R_PPC64_TPREL64 = 73, - R_PPC64_DTPREL16 = 74, - R_PPC64_DTPREL16_LO = 75, - R_PPC64_DTPREL16_HI = 76, - R_PPC64_DTPREL16_HA = 77, - R_PPC64_DTPREL64 = 78, - R_PPC64_GOT_TLSGD16 = 79, - R_PPC64_GOT_TLSGD16_LO = 80, - R_PPC64_GOT_TLSGD16_HI = 81, - R_PPC64_GOT_TLSGD16_HA = 82, - R_PPC64_GOT_TLSLD16 = 83, - R_PPC64_GOT_TLSLD16_LO = 84, - R_PPC64_GOT_TLSLD16_HI = 85, - R_PPC64_GOT_TLSLD16_HA = 86, - R_PPC64_GOT_TPREL16_DS = 87, - R_PPC64_GOT_TPREL16_LO_DS = 88, - R_PPC64_GOT_TPREL16_HI = 89, - R_PPC64_GOT_TPREL16_HA = 90, - R_PPC64_GOT_DTPREL16_DS = 91, - R_PPC64_GOT_DTPREL16_LO_DS = 92, - R_PPC64_GOT_DTPREL16_HI = 93, - R_PPC64_GOT_DTPREL16_HA = 94, - R_PPC64_TPREL16_DS = 95, - R_PPC64_TPREL16_LO_DS = 96, - R_PPC64_TPREL16_HIGHER = 97, - R_PPC64_TPREL16_HIGHERA = 98, - R_PPC64_TPREL16_HIGHEST = 99, - R_PPC64_TPREL16_HIGHESTA = 100, - R_PPC64_DTPREL16_DS = 101, - R_PPC64_DTPREL16_LO_DS = 102, - R_PPC64_DTPREL16_HIGHER = 103, - R_PPC64_DTPREL16_HIGHERA = 104, - R_PPC64_DTPREL16_HIGHEST = 105, - R_PPC64_DTPREL16_HIGHESTA = 106, - R_PPC64_TLSGD = 107, - R_PPC64_TLSLD = 108, - R_PPC64_REL16 = 249, - R_PPC64_REL16_LO = 250, - R_PPC64_REL16_HI = 251, - R_PPC64_REL16_HA = 252 +#include "ELFRelocs/PowerPC64.def" }; // ELF Relocation types for AArch64 - enum { - R_AARCH64_NONE = 0x100, - - R_AARCH64_ABS64 = 0x101, - R_AARCH64_ABS32 = 0x102, - R_AARCH64_ABS16 = 0x103, - R_AARCH64_PREL64 = 0x104, - R_AARCH64_PREL32 = 0x105, - R_AARCH64_PREL16 = 0x106, - - R_AARCH64_MOVW_UABS_G0 = 0x107, - R_AARCH64_MOVW_UABS_G0_NC = 0x108, - R_AARCH64_MOVW_UABS_G1 = 0x109, - R_AARCH64_MOVW_UABS_G1_NC = 0x10a, - R_AARCH64_MOVW_UABS_G2 = 0x10b, - R_AARCH64_MOVW_UABS_G2_NC = 0x10c, - R_AARCH64_MOVW_UABS_G3 = 0x10d, - R_AARCH64_MOVW_SABS_G0 = 0x10e, - R_AARCH64_MOVW_SABS_G1 = 0x10f, - R_AARCH64_MOVW_SABS_G2 = 0x110, - - R_AARCH64_LD_PREL_LO19 = 0x111, - R_AARCH64_ADR_PREL_LO21 = 0x112, - R_AARCH64_ADR_PREL_PG_HI21 = 0x113, - R_AARCH64_ADD_ABS_LO12_NC = 0x115, - R_AARCH64_LDST8_ABS_LO12_NC = 0x116, - - R_AARCH64_TSTBR14 = 0x117, - R_AARCH64_CONDBR19 = 0x118, - R_AARCH64_JUMP26 = 0x11a, - R_AARCH64_CALL26 = 0x11b, - - R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, - R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, - R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, - - R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, - - R_AARCH64_ADR_GOT_PAGE = 0x137, - R_AARCH64_LD64_GOT_LO12_NC = 0x138, - - R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, - R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, - R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, - R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, - R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, - R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, - R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, - R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, - R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, - R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, - R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, - R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, - R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, - R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, - R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, - R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, - - R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, - R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, - R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, - R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, - R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, - - R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, - R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, - R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, - R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, - R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, - R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, - R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, - R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, - R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, - R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, - R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, - R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, - R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, - R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, - R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, - R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, - - R_AARCH64_TLSDESC_ADR_PAGE = 0x232, - R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233, - R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234, - - R_AARCH64_TLSDESC_CALL = 0x239 +#include "ELFRelocs/AArch64.def" }; // ARM Specific e_flags @@ -717,140 +422,8 @@ enum : unsigned { }; // ELF Relocation types for ARM -// Meets 2.08 ABI Specs. - enum { - R_ARM_NONE = 0x00, - R_ARM_PC24 = 0x01, - R_ARM_ABS32 = 0x02, - R_ARM_REL32 = 0x03, - R_ARM_LDR_PC_G0 = 0x04, - R_ARM_ABS16 = 0x05, - R_ARM_ABS12 = 0x06, - R_ARM_THM_ABS5 = 0x07, - R_ARM_ABS8 = 0x08, - R_ARM_SBREL32 = 0x09, - R_ARM_THM_CALL = 0x0a, - R_ARM_THM_PC8 = 0x0b, - R_ARM_BREL_ADJ = 0x0c, - R_ARM_TLS_DESC = 0x0d, - R_ARM_THM_SWI8 = 0x0e, - R_ARM_XPC25 = 0x0f, - R_ARM_THM_XPC22 = 0x10, - R_ARM_TLS_DTPMOD32 = 0x11, - R_ARM_TLS_DTPOFF32 = 0x12, - R_ARM_TLS_TPOFF32 = 0x13, - R_ARM_COPY = 0x14, - R_ARM_GLOB_DAT = 0x15, - R_ARM_JUMP_SLOT = 0x16, - R_ARM_RELATIVE = 0x17, - R_ARM_GOTOFF32 = 0x18, - R_ARM_BASE_PREL = 0x19, - R_ARM_GOT_BREL = 0x1a, - R_ARM_PLT32 = 0x1b, - R_ARM_CALL = 0x1c, - R_ARM_JUMP24 = 0x1d, - R_ARM_THM_JUMP24 = 0x1e, - R_ARM_BASE_ABS = 0x1f, - R_ARM_ALU_PCREL_7_0 = 0x20, - R_ARM_ALU_PCREL_15_8 = 0x21, - R_ARM_ALU_PCREL_23_15 = 0x22, - R_ARM_LDR_SBREL_11_0_NC = 0x23, - R_ARM_ALU_SBREL_19_12_NC = 0x24, - R_ARM_ALU_SBREL_27_20_CK = 0x25, - R_ARM_TARGET1 = 0x26, - R_ARM_SBREL31 = 0x27, - R_ARM_V4BX = 0x28, - R_ARM_TARGET2 = 0x29, - R_ARM_PREL31 = 0x2a, - R_ARM_MOVW_ABS_NC = 0x2b, - R_ARM_MOVT_ABS = 0x2c, - R_ARM_MOVW_PREL_NC = 0x2d, - R_ARM_MOVT_PREL = 0x2e, - R_ARM_THM_MOVW_ABS_NC = 0x2f, - R_ARM_THM_MOVT_ABS = 0x30, - R_ARM_THM_MOVW_PREL_NC = 0x31, - R_ARM_THM_MOVT_PREL = 0x32, - R_ARM_THM_JUMP19 = 0x33, - R_ARM_THM_JUMP6 = 0x34, - R_ARM_THM_ALU_PREL_11_0 = 0x35, - R_ARM_THM_PC12 = 0x36, - R_ARM_ABS32_NOI = 0x37, - R_ARM_REL32_NOI = 0x38, - R_ARM_ALU_PC_G0_NC = 0x39, - R_ARM_ALU_PC_G0 = 0x3a, - R_ARM_ALU_PC_G1_NC = 0x3b, - R_ARM_ALU_PC_G1 = 0x3c, - R_ARM_ALU_PC_G2 = 0x3d, - R_ARM_LDR_PC_G1 = 0x3e, - R_ARM_LDR_PC_G2 = 0x3f, - R_ARM_LDRS_PC_G0 = 0x40, - R_ARM_LDRS_PC_G1 = 0x41, - R_ARM_LDRS_PC_G2 = 0x42, - R_ARM_LDC_PC_G0 = 0x43, - R_ARM_LDC_PC_G1 = 0x44, - R_ARM_LDC_PC_G2 = 0x45, - R_ARM_ALU_SB_G0_NC = 0x46, - R_ARM_ALU_SB_G0 = 0x47, - R_ARM_ALU_SB_G1_NC = 0x48, - R_ARM_ALU_SB_G1 = 0x49, - R_ARM_ALU_SB_G2 = 0x4a, - R_ARM_LDR_SB_G0 = 0x4b, - R_ARM_LDR_SB_G1 = 0x4c, - R_ARM_LDR_SB_G2 = 0x4d, - R_ARM_LDRS_SB_G0 = 0x4e, - R_ARM_LDRS_SB_G1 = 0x4f, - R_ARM_LDRS_SB_G2 = 0x50, - R_ARM_LDC_SB_G0 = 0x51, - R_ARM_LDC_SB_G1 = 0x52, - R_ARM_LDC_SB_G2 = 0x53, - R_ARM_MOVW_BREL_NC = 0x54, - R_ARM_MOVT_BREL = 0x55, - R_ARM_MOVW_BREL = 0x56, - R_ARM_THM_MOVW_BREL_NC = 0x57, - R_ARM_THM_MOVT_BREL = 0x58, - R_ARM_THM_MOVW_BREL = 0x59, - R_ARM_TLS_GOTDESC = 0x5a, - R_ARM_TLS_CALL = 0x5b, - R_ARM_TLS_DESCSEQ = 0x5c, - R_ARM_THM_TLS_CALL = 0x5d, - R_ARM_PLT32_ABS = 0x5e, - R_ARM_GOT_ABS = 0x5f, - R_ARM_GOT_PREL = 0x60, - R_ARM_GOT_BREL12 = 0x61, - R_ARM_GOTOFF12 = 0x62, - R_ARM_GOTRELAX = 0x63, - R_ARM_GNU_VTENTRY = 0x64, - R_ARM_GNU_VTINHERIT = 0x65, - R_ARM_THM_JUMP11 = 0x66, - R_ARM_THM_JUMP8 = 0x67, - R_ARM_TLS_GD32 = 0x68, - R_ARM_TLS_LDM32 = 0x69, - R_ARM_TLS_LDO32 = 0x6a, - R_ARM_TLS_IE32 = 0x6b, - R_ARM_TLS_LE32 = 0x6c, - R_ARM_TLS_LDO12 = 0x6d, - R_ARM_TLS_LE12 = 0x6e, - R_ARM_TLS_IE12GP = 0x6f, - R_ARM_PRIVATE_0 = 0x70, - R_ARM_PRIVATE_1 = 0x71, - R_ARM_PRIVATE_2 = 0x72, - R_ARM_PRIVATE_3 = 0x73, - R_ARM_PRIVATE_4 = 0x74, - R_ARM_PRIVATE_5 = 0x75, - R_ARM_PRIVATE_6 = 0x76, - R_ARM_PRIVATE_7 = 0x77, - R_ARM_PRIVATE_8 = 0x78, - R_ARM_PRIVATE_9 = 0x79, - R_ARM_PRIVATE_10 = 0x7a, - R_ARM_PRIVATE_11 = 0x7b, - R_ARM_PRIVATE_12 = 0x7c, - R_ARM_PRIVATE_13 = 0x7d, - R_ARM_PRIVATE_14 = 0x7e, - R_ARM_PRIVATE_15 = 0x7f, - R_ARM_ME_TOO = 0x80, - R_ARM_THM_TLS_DESCSEQ16 = 0x81, - R_ARM_THM_TLS_DESCSEQ32 = 0x82 +#include "ELFRelocs/ARM.def" }; // Mips Specific e_flags @@ -861,7 +434,13 @@ enum : unsigned { EF_MIPS_ABI2 = 0x00000020, EF_MIPS_32BITMODE = 0x00000100, EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding + + // ABI flags EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. + EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. + EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. + EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. //ARCH_ASE EF_MIPS_MICROMIPS = 0x02000000, // microMIPS @@ -884,85 +463,7 @@ enum : unsigned { // ELF Relocation types for Mips enum { - R_MIPS_NONE = 0, - R_MIPS_16 = 1, - R_MIPS_32 = 2, - R_MIPS_REL32 = 3, - R_MIPS_26 = 4, - R_MIPS_HI16 = 5, - R_MIPS_LO16 = 6, - R_MIPS_GPREL16 = 7, - R_MIPS_LITERAL = 8, - R_MIPS_GOT16 = 9, - R_MIPS_PC16 = 10, - R_MIPS_CALL16 = 11, - R_MIPS_GPREL32 = 12, - R_MIPS_UNUSED1 = 13, - R_MIPS_UNUSED2 = 14, - R_MIPS_SHIFT5 = 16, - R_MIPS_SHIFT6 = 17, - R_MIPS_64 = 18, - R_MIPS_GOT_DISP = 19, - R_MIPS_GOT_PAGE = 20, - R_MIPS_GOT_OFST = 21, - R_MIPS_GOT_HI16 = 22, - R_MIPS_GOT_LO16 = 23, - R_MIPS_SUB = 24, - R_MIPS_INSERT_A = 25, - R_MIPS_INSERT_B = 26, - R_MIPS_DELETE = 27, - R_MIPS_HIGHER = 28, - R_MIPS_HIGHEST = 29, - R_MIPS_CALL_HI16 = 30, - R_MIPS_CALL_LO16 = 31, - R_MIPS_SCN_DISP = 32, - R_MIPS_REL16 = 33, - R_MIPS_ADD_IMMEDIATE = 34, - R_MIPS_PJUMP = 35, - R_MIPS_RELGOT = 36, - R_MIPS_JALR = 37, - R_MIPS_TLS_DTPMOD32 = 38, - R_MIPS_TLS_DTPREL32 = 39, - R_MIPS_TLS_DTPMOD64 = 40, - R_MIPS_TLS_DTPREL64 = 41, - R_MIPS_TLS_GD = 42, - R_MIPS_TLS_LDM = 43, - R_MIPS_TLS_DTPREL_HI16 = 44, - R_MIPS_TLS_DTPREL_LO16 = 45, - R_MIPS_TLS_GOTTPREL = 46, - R_MIPS_TLS_TPREL32 = 47, - R_MIPS_TLS_TPREL64 = 48, - R_MIPS_TLS_TPREL_HI16 = 49, - R_MIPS_TLS_TPREL_LO16 = 50, - R_MIPS_GLOB_DAT = 51, - R_MIPS_PC21_S2 = 60, - R_MIPS_PC26_S2 = 61, - R_MIPS_PC18_S3 = 62, - R_MIPS_PC19_S2 = 63, - R_MIPS_PCHI16 = 64, - R_MIPS_PCLO16 = 65, - R_MIPS16_GOT16 = 102, - R_MIPS16_HI16 = 104, - R_MIPS16_LO16 = 105, - R_MIPS_COPY = 126, - R_MIPS_JUMP_SLOT = 127, - R_MICROMIPS_26_S1 = 133, - R_MICROMIPS_HI16 = 134, - R_MICROMIPS_LO16 = 135, - R_MICROMIPS_GOT16 = 138, - R_MICROMIPS_PC16_S1 = 141, - R_MICROMIPS_CALL16 = 142, - R_MICROMIPS_GOT_DISP = 145, - R_MICROMIPS_GOT_PAGE = 146, - R_MICROMIPS_GOT_OFST = 147, - R_MICROMIPS_TLS_GD = 162, - R_MICROMIPS_TLS_LDM = 163, - R_MICROMIPS_TLS_DTPREL_HI16 = 164, - R_MICROMIPS_TLS_DTPREL_LO16 = 165, - R_MICROMIPS_TLS_TPREL_HI16 = 169, - R_MICROMIPS_TLS_TPREL_LO16 = 170, - R_MIPS_NUM = 218, - R_MIPS_PC32 = 248 +#include "ELFRelocs/Mips.def" }; // Special values for the st_other field in the symbol table entry for MIPS. @@ -1003,250 +504,22 @@ enum { }; // ELF Relocation types for Hexagon -// Release 5 ABI enum { - R_HEX_NONE = 0, - R_HEX_B22_PCREL = 1, - R_HEX_B15_PCREL = 2, - R_HEX_B7_PCREL = 3, - R_HEX_LO16 = 4, - R_HEX_HI16 = 5, - R_HEX_32 = 6, - R_HEX_16 = 7, - R_HEX_8 = 8, - R_HEX_GPREL16_0 = 9, - R_HEX_GPREL16_1 = 10, - R_HEX_GPREL16_2 = 11, - R_HEX_GPREL16_3 = 12, - R_HEX_HL16 = 13, - R_HEX_B13_PCREL = 14, - R_HEX_B9_PCREL = 15, - R_HEX_B32_PCREL_X = 16, - R_HEX_32_6_X = 17, - R_HEX_B22_PCREL_X = 18, - R_HEX_B15_PCREL_X = 19, - R_HEX_B13_PCREL_X = 20, - R_HEX_B9_PCREL_X = 21, - R_HEX_B7_PCREL_X = 22, - R_HEX_16_X = 23, - R_HEX_12_X = 24, - R_HEX_11_X = 25, - R_HEX_10_X = 26, - R_HEX_9_X = 27, - R_HEX_8_X = 28, - R_HEX_7_X = 29, - R_HEX_6_X = 30, - R_HEX_32_PCREL = 31, - R_HEX_COPY = 32, - R_HEX_GLOB_DAT = 33, - R_HEX_JMP_SLOT = 34, - R_HEX_RELATIVE = 35, - R_HEX_PLT_B22_PCREL = 36, - R_HEX_GOTREL_LO16 = 37, - R_HEX_GOTREL_HI16 = 38, - R_HEX_GOTREL_32 = 39, - R_HEX_GOT_LO16 = 40, - R_HEX_GOT_HI16 = 41, - R_HEX_GOT_32 = 42, - R_HEX_GOT_16 = 43, - R_HEX_DTPMOD_32 = 44, - R_HEX_DTPREL_LO16 = 45, - R_HEX_DTPREL_HI16 = 46, - R_HEX_DTPREL_32 = 47, - R_HEX_DTPREL_16 = 48, - R_HEX_GD_PLT_B22_PCREL = 49, - R_HEX_GD_GOT_LO16 = 50, - R_HEX_GD_GOT_HI16 = 51, - R_HEX_GD_GOT_32 = 52, - R_HEX_GD_GOT_16 = 53, - R_HEX_IE_LO16 = 54, - R_HEX_IE_HI16 = 55, - R_HEX_IE_32 = 56, - R_HEX_IE_GOT_LO16 = 57, - R_HEX_IE_GOT_HI16 = 58, - R_HEX_IE_GOT_32 = 59, - R_HEX_IE_GOT_16 = 60, - R_HEX_TPREL_LO16 = 61, - R_HEX_TPREL_HI16 = 62, - R_HEX_TPREL_32 = 63, - R_HEX_TPREL_16 = 64, - R_HEX_6_PCREL_X = 65, - R_HEX_GOTREL_32_6_X = 66, - R_HEX_GOTREL_16_X = 67, - R_HEX_GOTREL_11_X = 68, - R_HEX_GOT_32_6_X = 69, - R_HEX_GOT_16_X = 70, - R_HEX_GOT_11_X = 71, - R_HEX_DTPREL_32_6_X = 72, - R_HEX_DTPREL_16_X = 73, - R_HEX_DTPREL_11_X = 74, - R_HEX_GD_GOT_32_6_X = 75, - R_HEX_GD_GOT_16_X = 76, - R_HEX_GD_GOT_11_X = 77, - R_HEX_IE_32_6_X = 78, - R_HEX_IE_16_X = 79, - R_HEX_IE_GOT_32_6_X = 80, - R_HEX_IE_GOT_16_X = 81, - R_HEX_IE_GOT_11_X = 82, - R_HEX_TPREL_32_6_X = 83, - R_HEX_TPREL_16_X = 84, - R_HEX_TPREL_11_X = 85 +#include "ELFRelocs/Hexagon.def" }; // ELF Relocation types for S390/zSeries enum { - R_390_NONE = 0, - R_390_8 = 1, - R_390_12 = 2, - R_390_16 = 3, - R_390_32 = 4, - R_390_PC32 = 5, - R_390_GOT12 = 6, - R_390_GOT32 = 7, - R_390_PLT32 = 8, - R_390_COPY = 9, - R_390_GLOB_DAT = 10, - R_390_JMP_SLOT = 11, - R_390_RELATIVE = 12, - R_390_GOTOFF = 13, - R_390_GOTPC = 14, - R_390_GOT16 = 15, - R_390_PC16 = 16, - R_390_PC16DBL = 17, - R_390_PLT16DBL = 18, - R_390_PC32DBL = 19, - R_390_PLT32DBL = 20, - R_390_GOTPCDBL = 21, - R_390_64 = 22, - R_390_PC64 = 23, - R_390_GOT64 = 24, - R_390_PLT64 = 25, - R_390_GOTENT = 26, - R_390_GOTOFF16 = 27, - R_390_GOTOFF64 = 28, - R_390_GOTPLT12 = 29, - R_390_GOTPLT16 = 30, - R_390_GOTPLT32 = 31, - R_390_GOTPLT64 = 32, - R_390_GOTPLTENT = 33, - R_390_PLTOFF16 = 34, - R_390_PLTOFF32 = 35, - R_390_PLTOFF64 = 36, - R_390_TLS_LOAD = 37, - R_390_TLS_GDCALL = 38, - R_390_TLS_LDCALL = 39, - R_390_TLS_GD32 = 40, - R_390_TLS_GD64 = 41, - R_390_TLS_GOTIE12 = 42, - R_390_TLS_GOTIE32 = 43, - R_390_TLS_GOTIE64 = 44, - R_390_TLS_LDM32 = 45, - R_390_TLS_LDM64 = 46, - R_390_TLS_IE32 = 47, - R_390_TLS_IE64 = 48, - R_390_TLS_IEENT = 49, - R_390_TLS_LE32 = 50, - R_390_TLS_LE64 = 51, - R_390_TLS_LDO32 = 52, - R_390_TLS_LDO64 = 53, - R_390_TLS_DTPMOD = 54, - R_390_TLS_DTPOFF = 55, - R_390_TLS_TPOFF = 56, - R_390_20 = 57, - R_390_GOT20 = 58, - R_390_GOTPLT20 = 59, - R_390_TLS_GOTIE20 = 60, - R_390_IRELATIVE = 61 +#include "ELFRelocs/SystemZ.def" }; // ELF Relocation type for Sparc. enum { - R_SPARC_NONE = 0, - R_SPARC_8 = 1, - R_SPARC_16 = 2, - R_SPARC_32 = 3, - R_SPARC_DISP8 = 4, - R_SPARC_DISP16 = 5, - R_SPARC_DISP32 = 6, - R_SPARC_WDISP30 = 7, - R_SPARC_WDISP22 = 8, - R_SPARC_HI22 = 9, - R_SPARC_22 = 10, - R_SPARC_13 = 11, - R_SPARC_LO10 = 12, - R_SPARC_GOT10 = 13, - R_SPARC_GOT13 = 14, - R_SPARC_GOT22 = 15, - R_SPARC_PC10 = 16, - R_SPARC_PC22 = 17, - R_SPARC_WPLT30 = 18, - R_SPARC_COPY = 19, - R_SPARC_GLOB_DAT = 20, - R_SPARC_JMP_SLOT = 21, - R_SPARC_RELATIVE = 22, - R_SPARC_UA32 = 23, - R_SPARC_PLT32 = 24, - R_SPARC_HIPLT22 = 25, - R_SPARC_LOPLT10 = 26, - R_SPARC_PCPLT32 = 27, - R_SPARC_PCPLT22 = 28, - R_SPARC_PCPLT10 = 29, - R_SPARC_10 = 30, - R_SPARC_11 = 31, - R_SPARC_64 = 32, - R_SPARC_OLO10 = 33, - R_SPARC_HH22 = 34, - R_SPARC_HM10 = 35, - R_SPARC_LM22 = 36, - R_SPARC_PC_HH22 = 37, - R_SPARC_PC_HM10 = 38, - R_SPARC_PC_LM22 = 39, - R_SPARC_WDISP16 = 40, - R_SPARC_WDISP19 = 41, - R_SPARC_7 = 43, - R_SPARC_5 = 44, - R_SPARC_6 = 45, - R_SPARC_DISP64 = 46, - R_SPARC_PLT64 = 47, - R_SPARC_HIX22 = 48, - R_SPARC_LOX10 = 49, - R_SPARC_H44 = 50, - R_SPARC_M44 = 51, - R_SPARC_L44 = 52, - R_SPARC_REGISTER = 53, - R_SPARC_UA64 = 54, - R_SPARC_UA16 = 55, - R_SPARC_TLS_GD_HI22 = 56, - R_SPARC_TLS_GD_LO10 = 57, - R_SPARC_TLS_GD_ADD = 58, - R_SPARC_TLS_GD_CALL = 59, - R_SPARC_TLS_LDM_HI22 = 60, - R_SPARC_TLS_LDM_LO10 = 61, - R_SPARC_TLS_LDM_ADD = 62, - R_SPARC_TLS_LDM_CALL = 63, - R_SPARC_TLS_LDO_HIX22 = 64, - R_SPARC_TLS_LDO_LOX10 = 65, - R_SPARC_TLS_LDO_ADD = 66, - R_SPARC_TLS_IE_HI22 = 67, - R_SPARC_TLS_IE_LO10 = 68, - R_SPARC_TLS_IE_LD = 69, - R_SPARC_TLS_IE_LDX = 70, - R_SPARC_TLS_IE_ADD = 71, - R_SPARC_TLS_LE_HIX22 = 72, - R_SPARC_TLS_LE_LOX10 = 73, - R_SPARC_TLS_DTPMOD32 = 74, - R_SPARC_TLS_DTPMOD64 = 75, - R_SPARC_TLS_DTPOFF32 = 76, - R_SPARC_TLS_DTPOFF64 = 77, - R_SPARC_TLS_TPOFF32 = 78, - R_SPARC_TLS_TPOFF64 = 79, - R_SPARC_GOTDATA_HIX22 = 80, - R_SPARC_GOTDATA_LOX22 = 81, - R_SPARC_GOTDATA_OP_HIX22 = 82, - R_SPARC_GOTDATA_OP_LOX22 = 83, - R_SPARC_GOTDATA_OP = 84 +#include "ELFRelocs/Sparc.def" }; +#undef ELF_RELOC + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) diff --git a/include/llvm/Support/ELFRelocs/AArch64.def b/include/llvm/Support/ELFRelocs/AArch64.def new file mode 100644 index 000000000000..aa0c560f3e50 --- /dev/null +++ b/include/llvm/Support/ELFRelocs/AArch64.def @@ -0,0 +1,147 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// ABI release 1.0 +ELF_RELOC(R_AARCH64_NONE, 0) + +ELF_RELOC(R_AARCH64_ABS64, 0x101) +ELF_RELOC(R_AARCH64_ABS32, 0x102) +ELF_RELOC(R_AARCH64_ABS16, 0x103) +ELF_RELOC(R_AARCH64_PREL64, 0x104) +ELF_RELOC(R_AARCH64_PREL32, 0x105) +ELF_RELOC(R_AARCH64_PREL16, 0x106) + +ELF_RELOC(R_AARCH64_MOVW_UABS_G0, 0x107) +ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 0x108) +ELF_RELOC(R_AARCH64_MOVW_UABS_G1, 0x109) +ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 0x10a) +ELF_RELOC(R_AARCH64_MOVW_UABS_G2, 0x10b) +ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 0x10c) +ELF_RELOC(R_AARCH64_MOVW_UABS_G3, 0x10d) +ELF_RELOC(R_AARCH64_MOVW_SABS_G0, 0x10e) +ELF_RELOC(R_AARCH64_MOVW_SABS_G1, 0x10f) +ELF_RELOC(R_AARCH64_MOVW_SABS_G2, 0x110) + +ELF_RELOC(R_AARCH64_LD_PREL_LO19, 0x111) +ELF_RELOC(R_AARCH64_ADR_PREL_LO21, 0x112) +ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 0x113) +ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 0x114) +ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 0x115) +ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 0x116) + +ELF_RELOC(R_AARCH64_TSTBR14, 0x117) +ELF_RELOC(R_AARCH64_CONDBR19, 0x118) +ELF_RELOC(R_AARCH64_JUMP26, 0x11a) +ELF_RELOC(R_AARCH64_CALL26, 0x11b) + +ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 0x11c) +ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 0x11d) +ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 0x11e) + +ELF_RELOC(R_AARCH64_MOVW_PREL_G0, 0x11f) +ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 0x120) +ELF_RELOC(R_AARCH64_MOVW_PREL_G1, 0x121) +ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 0x122) +ELF_RELOC(R_AARCH64_MOVW_PREL_G2, 0x123) +ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 0x124) +ELF_RELOC(R_AARCH64_MOVW_PREL_G3, 0x125) + +ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 0x12b) + +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 0x12c) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 0x12d) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 0x12e) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 0x12f) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 0x130) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 0x131) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 0x132) + +ELF_RELOC(R_AARCH64_GOTREL64, 0x133) +ELF_RELOC(R_AARCH64_GOTREL32, 0x134) + +ELF_RELOC(R_AARCH64_GOT_LD_PREL19, 0x135) +ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 0x136) +ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137) +ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138) +ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139) + +ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200) +ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201) +ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202) +ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1, 0x203) +ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 0x204) + +ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 0x205) +ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 0x206) +ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 0x207) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1, 0x208) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 0x209) +ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19, 0x20a) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 0x20b) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 0x20c) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 0x20d) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 0x20e) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 0x20f) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 0x210) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12, 0x211) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 0x212) +ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 0x213) +ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 0x214) +ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 0x215) +ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 0x216) +ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 0x217) +ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 0x218) +ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 0x219) +ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 0x21a) + +ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 0x21b) +ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 0x21c) +ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x21d) +ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0x21e) +ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 0x21f) + +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 0x220) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 0x221) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 0x222) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 0x223) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 0x224) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x225) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 0x226) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x227) +ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 0x228) +ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 0x229) +ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 0x22a) +ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 0x22b) +ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 0x22c) +ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 0x22d) +ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 0x22e) +ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 0x22f) + +ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 0x230) +ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 0x231) +ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 0x232) +ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC, 0x233) +ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC, 0x234) +ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1, 0x235) +ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 0x236) +ELF_RELOC(R_AARCH64_TLSDESC_LDR, 0x237) +ELF_RELOC(R_AARCH64_TLSDESC_ADD, 0x238) +ELF_RELOC(R_AARCH64_TLSDESC_CALL, 0x239) + +ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a) +ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b) + +ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c) +ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d) + +ELF_RELOC(R_AARCH64_COPY, 0x400) +ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401) +ELF_RELOC(R_AARCH64_JUMP_SLOT, 0x402) +ELF_RELOC(R_AARCH64_RELATIVE, 0x403) +ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x404) +ELF_RELOC(R_AARCH64_TLS_DTPMOD64, 0x405) +ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406) +ELF_RELOC(R_AARCH64_TLSDESC, 0x407) +ELF_RELOC(R_AARCH64_IRELATIVE, 0x408) diff --git a/include/llvm/Support/ELFRelocs/ARM.def b/include/llvm/Support/ELFRelocs/ARM.def new file mode 100644 index 000000000000..730fc5b8836c --- /dev/null +++ b/include/llvm/Support/ELFRelocs/ARM.def @@ -0,0 +1,138 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// Meets 2.09 ABI Specs. +ELF_RELOC(R_ARM_NONE, 0x00) +ELF_RELOC(R_ARM_PC24, 0x01) +ELF_RELOC(R_ARM_ABS32, 0x02) +ELF_RELOC(R_ARM_REL32, 0x03) +ELF_RELOC(R_ARM_LDR_PC_G0, 0x04) +ELF_RELOC(R_ARM_ABS16, 0x05) +ELF_RELOC(R_ARM_ABS12, 0x06) +ELF_RELOC(R_ARM_THM_ABS5, 0x07) +ELF_RELOC(R_ARM_ABS8, 0x08) +ELF_RELOC(R_ARM_SBREL32, 0x09) +ELF_RELOC(R_ARM_THM_CALL, 0x0a) +ELF_RELOC(R_ARM_THM_PC8, 0x0b) +ELF_RELOC(R_ARM_BREL_ADJ, 0x0c) +ELF_RELOC(R_ARM_TLS_DESC, 0x0d) +ELF_RELOC(R_ARM_THM_SWI8, 0x0e) +ELF_RELOC(R_ARM_XPC25, 0x0f) +ELF_RELOC(R_ARM_THM_XPC22, 0x10) +ELF_RELOC(R_ARM_TLS_DTPMOD32, 0x11) +ELF_RELOC(R_ARM_TLS_DTPOFF32, 0x12) +ELF_RELOC(R_ARM_TLS_TPOFF32, 0x13) +ELF_RELOC(R_ARM_COPY, 0x14) +ELF_RELOC(R_ARM_GLOB_DAT, 0x15) +ELF_RELOC(R_ARM_JUMP_SLOT, 0x16) +ELF_RELOC(R_ARM_RELATIVE, 0x17) +ELF_RELOC(R_ARM_GOTOFF32, 0x18) +ELF_RELOC(R_ARM_BASE_PREL, 0x19) +ELF_RELOC(R_ARM_GOT_BREL, 0x1a) +ELF_RELOC(R_ARM_PLT32, 0x1b) +ELF_RELOC(R_ARM_CALL, 0x1c) +ELF_RELOC(R_ARM_JUMP24, 0x1d) +ELF_RELOC(R_ARM_THM_JUMP24, 0x1e) +ELF_RELOC(R_ARM_BASE_ABS, 0x1f) +ELF_RELOC(R_ARM_ALU_PCREL_7_0, 0x20) +ELF_RELOC(R_ARM_ALU_PCREL_15_8, 0x21) +ELF_RELOC(R_ARM_ALU_PCREL_23_15, 0x22) +ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC, 0x23) +ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC, 0x24) +ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK, 0x25) +ELF_RELOC(R_ARM_TARGET1, 0x26) +ELF_RELOC(R_ARM_SBREL31, 0x27) +ELF_RELOC(R_ARM_V4BX, 0x28) +ELF_RELOC(R_ARM_TARGET2, 0x29) +ELF_RELOC(R_ARM_PREL31, 0x2a) +ELF_RELOC(R_ARM_MOVW_ABS_NC, 0x2b) +ELF_RELOC(R_ARM_MOVT_ABS, 0x2c) +ELF_RELOC(R_ARM_MOVW_PREL_NC, 0x2d) +ELF_RELOC(R_ARM_MOVT_PREL, 0x2e) +ELF_RELOC(R_ARM_THM_MOVW_ABS_NC, 0x2f) +ELF_RELOC(R_ARM_THM_MOVT_ABS, 0x30) +ELF_RELOC(R_ARM_THM_MOVW_PREL_NC, 0x31) +ELF_RELOC(R_ARM_THM_MOVT_PREL, 0x32) +ELF_RELOC(R_ARM_THM_JUMP19, 0x33) +ELF_RELOC(R_ARM_THM_JUMP6, 0x34) +ELF_RELOC(R_ARM_THM_ALU_PREL_11_0, 0x35) +ELF_RELOC(R_ARM_THM_PC12, 0x36) +ELF_RELOC(R_ARM_ABS32_NOI, 0x37) +ELF_RELOC(R_ARM_REL32_NOI, 0x38) +ELF_RELOC(R_ARM_ALU_PC_G0_NC, 0x39) +ELF_RELOC(R_ARM_ALU_PC_G0, 0x3a) +ELF_RELOC(R_ARM_ALU_PC_G1_NC, 0x3b) +ELF_RELOC(R_ARM_ALU_PC_G1, 0x3c) +ELF_RELOC(R_ARM_ALU_PC_G2, 0x3d) +ELF_RELOC(R_ARM_LDR_PC_G1, 0x3e) +ELF_RELOC(R_ARM_LDR_PC_G2, 0x3f) +ELF_RELOC(R_ARM_LDRS_PC_G0, 0x40) +ELF_RELOC(R_ARM_LDRS_PC_G1, 0x41) +ELF_RELOC(R_ARM_LDRS_PC_G2, 0x42) +ELF_RELOC(R_ARM_LDC_PC_G0, 0x43) +ELF_RELOC(R_ARM_LDC_PC_G1, 0x44) +ELF_RELOC(R_ARM_LDC_PC_G2, 0x45) +ELF_RELOC(R_ARM_ALU_SB_G0_NC, 0x46) +ELF_RELOC(R_ARM_ALU_SB_G0, 0x47) +ELF_RELOC(R_ARM_ALU_SB_G1_NC, 0x48) +ELF_RELOC(R_ARM_ALU_SB_G1, 0x49) +ELF_RELOC(R_ARM_ALU_SB_G2, 0x4a) +ELF_RELOC(R_ARM_LDR_SB_G0, 0x4b) +ELF_RELOC(R_ARM_LDR_SB_G1, 0x4c) +ELF_RELOC(R_ARM_LDR_SB_G2, 0x4d) +ELF_RELOC(R_ARM_LDRS_SB_G0, 0x4e) +ELF_RELOC(R_ARM_LDRS_SB_G1, 0x4f) +ELF_RELOC(R_ARM_LDRS_SB_G2, 0x50) +ELF_RELOC(R_ARM_LDC_SB_G0, 0x51) +ELF_RELOC(R_ARM_LDC_SB_G1, 0x52) +ELF_RELOC(R_ARM_LDC_SB_G2, 0x53) +ELF_RELOC(R_ARM_MOVW_BREL_NC, 0x54) +ELF_RELOC(R_ARM_MOVT_BREL, 0x55) +ELF_RELOC(R_ARM_MOVW_BREL, 0x56) +ELF_RELOC(R_ARM_THM_MOVW_BREL_NC, 0x57) +ELF_RELOC(R_ARM_THM_MOVT_BREL, 0x58) +ELF_RELOC(R_ARM_THM_MOVW_BREL, 0x59) +ELF_RELOC(R_ARM_TLS_GOTDESC, 0x5a) +ELF_RELOC(R_ARM_TLS_CALL, 0x5b) +ELF_RELOC(R_ARM_TLS_DESCSEQ, 0x5c) +ELF_RELOC(R_ARM_THM_TLS_CALL, 0x5d) +ELF_RELOC(R_ARM_PLT32_ABS, 0x5e) +ELF_RELOC(R_ARM_GOT_ABS, 0x5f) +ELF_RELOC(R_ARM_GOT_PREL, 0x60) +ELF_RELOC(R_ARM_GOT_BREL12, 0x61) +ELF_RELOC(R_ARM_GOTOFF12, 0x62) +ELF_RELOC(R_ARM_GOTRELAX, 0x63) +ELF_RELOC(R_ARM_GNU_VTENTRY, 0x64) +ELF_RELOC(R_ARM_GNU_VTINHERIT, 0x65) +ELF_RELOC(R_ARM_THM_JUMP11, 0x66) +ELF_RELOC(R_ARM_THM_JUMP8, 0x67) +ELF_RELOC(R_ARM_TLS_GD32, 0x68) +ELF_RELOC(R_ARM_TLS_LDM32, 0x69) +ELF_RELOC(R_ARM_TLS_LDO32, 0x6a) +ELF_RELOC(R_ARM_TLS_IE32, 0x6b) +ELF_RELOC(R_ARM_TLS_LE32, 0x6c) +ELF_RELOC(R_ARM_TLS_LDO12, 0x6d) +ELF_RELOC(R_ARM_TLS_LE12, 0x6e) +ELF_RELOC(R_ARM_TLS_IE12GP, 0x6f) +ELF_RELOC(R_ARM_PRIVATE_0, 0x70) +ELF_RELOC(R_ARM_PRIVATE_1, 0x71) +ELF_RELOC(R_ARM_PRIVATE_2, 0x72) +ELF_RELOC(R_ARM_PRIVATE_3, 0x73) +ELF_RELOC(R_ARM_PRIVATE_4, 0x74) +ELF_RELOC(R_ARM_PRIVATE_5, 0x75) +ELF_RELOC(R_ARM_PRIVATE_6, 0x76) +ELF_RELOC(R_ARM_PRIVATE_7, 0x77) +ELF_RELOC(R_ARM_PRIVATE_8, 0x78) +ELF_RELOC(R_ARM_PRIVATE_9, 0x79) +ELF_RELOC(R_ARM_PRIVATE_10, 0x7a) +ELF_RELOC(R_ARM_PRIVATE_11, 0x7b) +ELF_RELOC(R_ARM_PRIVATE_12, 0x7c) +ELF_RELOC(R_ARM_PRIVATE_13, 0x7d) +ELF_RELOC(R_ARM_PRIVATE_14, 0x7e) +ELF_RELOC(R_ARM_PRIVATE_15, 0x7f) +ELF_RELOC(R_ARM_ME_TOO, 0x80) +ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81) +ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82) +ELF_RELOC(R_ARM_IRELATIVE, 0xa0) diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def new file mode 100644 index 000000000000..c9d35b8bd75e --- /dev/null +++ b/include/llvm/Support/ELFRelocs/Hexagon.def @@ -0,0 +1,92 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// Release 5 ABI +ELF_RELOC(R_HEX_NONE, 0) +ELF_RELOC(R_HEX_B22_PCREL, 1) +ELF_RELOC(R_HEX_B15_PCREL, 2) +ELF_RELOC(R_HEX_B7_PCREL, 3) +ELF_RELOC(R_HEX_LO16, 4) +ELF_RELOC(R_HEX_HI16, 5) +ELF_RELOC(R_HEX_32, 6) +ELF_RELOC(R_HEX_16, 7) +ELF_RELOC(R_HEX_8, 8) +ELF_RELOC(R_HEX_GPREL16_0, 9) +ELF_RELOC(R_HEX_GPREL16_1, 10) +ELF_RELOC(R_HEX_GPREL16_2, 11) +ELF_RELOC(R_HEX_GPREL16_3, 12) +ELF_RELOC(R_HEX_HL16, 13) +ELF_RELOC(R_HEX_B13_PCREL, 14) +ELF_RELOC(R_HEX_B9_PCREL, 15) +ELF_RELOC(R_HEX_B32_PCREL_X, 16) +ELF_RELOC(R_HEX_32_6_X, 17) +ELF_RELOC(R_HEX_B22_PCREL_X, 18) +ELF_RELOC(R_HEX_B15_PCREL_X, 19) +ELF_RELOC(R_HEX_B13_PCREL_X, 20) +ELF_RELOC(R_HEX_B9_PCREL_X, 21) +ELF_RELOC(R_HEX_B7_PCREL_X, 22) +ELF_RELOC(R_HEX_16_X, 23) +ELF_RELOC(R_HEX_12_X, 24) +ELF_RELOC(R_HEX_11_X, 25) +ELF_RELOC(R_HEX_10_X, 26) +ELF_RELOC(R_HEX_9_X, 27) +ELF_RELOC(R_HEX_8_X, 28) +ELF_RELOC(R_HEX_7_X, 29) +ELF_RELOC(R_HEX_6_X, 30) +ELF_RELOC(R_HEX_32_PCREL, 31) +ELF_RELOC(R_HEX_COPY, 32) +ELF_RELOC(R_HEX_GLOB_DAT, 33) +ELF_RELOC(R_HEX_JMP_SLOT, 34) +ELF_RELOC(R_HEX_RELATIVE, 35) +ELF_RELOC(R_HEX_PLT_B22_PCREL, 36) +ELF_RELOC(R_HEX_GOTREL_LO16, 37) +ELF_RELOC(R_HEX_GOTREL_HI16, 38) +ELF_RELOC(R_HEX_GOTREL_32, 39) +ELF_RELOC(R_HEX_GOT_LO16, 40) +ELF_RELOC(R_HEX_GOT_HI16, 41) +ELF_RELOC(R_HEX_GOT_32, 42) +ELF_RELOC(R_HEX_GOT_16, 43) +ELF_RELOC(R_HEX_DTPMOD_32, 44) +ELF_RELOC(R_HEX_DTPREL_LO16, 45) +ELF_RELOC(R_HEX_DTPREL_HI16, 46) +ELF_RELOC(R_HEX_DTPREL_32, 47) +ELF_RELOC(R_HEX_DTPREL_16, 48) +ELF_RELOC(R_HEX_GD_PLT_B22_PCREL, 49) +ELF_RELOC(R_HEX_GD_GOT_LO16, 50) +ELF_RELOC(R_HEX_GD_GOT_HI16, 51) +ELF_RELOC(R_HEX_GD_GOT_32, 52) +ELF_RELOC(R_HEX_GD_GOT_16, 53) +ELF_RELOC(R_HEX_IE_LO16, 54) +ELF_RELOC(R_HEX_IE_HI16, 55) +ELF_RELOC(R_HEX_IE_32, 56) +ELF_RELOC(R_HEX_IE_GOT_LO16, 57) +ELF_RELOC(R_HEX_IE_GOT_HI16, 58) +ELF_RELOC(R_HEX_IE_GOT_32, 59) +ELF_RELOC(R_HEX_IE_GOT_16, 60) +ELF_RELOC(R_HEX_TPREL_LO16, 61) +ELF_RELOC(R_HEX_TPREL_HI16, 62) +ELF_RELOC(R_HEX_TPREL_32, 63) +ELF_RELOC(R_HEX_TPREL_16, 64) +ELF_RELOC(R_HEX_6_PCREL_X, 65) +ELF_RELOC(R_HEX_GOTREL_32_6_X, 66) +ELF_RELOC(R_HEX_GOTREL_16_X, 67) +ELF_RELOC(R_HEX_GOTREL_11_X, 68) +ELF_RELOC(R_HEX_GOT_32_6_X, 69) +ELF_RELOC(R_HEX_GOT_16_X, 70) +ELF_RELOC(R_HEX_GOT_11_X, 71) +ELF_RELOC(R_HEX_DTPREL_32_6_X, 72) +ELF_RELOC(R_HEX_DTPREL_16_X, 73) +ELF_RELOC(R_HEX_DTPREL_11_X, 74) +ELF_RELOC(R_HEX_GD_GOT_32_6_X, 75) +ELF_RELOC(R_HEX_GD_GOT_16_X, 76) +ELF_RELOC(R_HEX_GD_GOT_11_X, 77) +ELF_RELOC(R_HEX_IE_32_6_X, 78) +ELF_RELOC(R_HEX_IE_16_X, 79) +ELF_RELOC(R_HEX_IE_GOT_32_6_X, 80) +ELF_RELOC(R_HEX_IE_GOT_16_X, 81) +ELF_RELOC(R_HEX_IE_GOT_11_X, 82) +ELF_RELOC(R_HEX_TPREL_32_6_X, 83) +ELF_RELOC(R_HEX_TPREL_16_X, 84) +ELF_RELOC(R_HEX_TPREL_11_X, 85) diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def new file mode 100644 index 000000000000..dc573464dcf2 --- /dev/null +++ b/include/llvm/Support/ELFRelocs/Mips.def @@ -0,0 +1,112 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_MIPS_NONE, 0) +ELF_RELOC(R_MIPS_16, 1) +ELF_RELOC(R_MIPS_32, 2) +ELF_RELOC(R_MIPS_REL32, 3) +ELF_RELOC(R_MIPS_26, 4) +ELF_RELOC(R_MIPS_HI16, 5) +ELF_RELOC(R_MIPS_LO16, 6) +ELF_RELOC(R_MIPS_GPREL16, 7) +ELF_RELOC(R_MIPS_LITERAL, 8) +ELF_RELOC(R_MIPS_GOT16, 9) +ELF_RELOC(R_MIPS_PC16, 10) +ELF_RELOC(R_MIPS_CALL16, 11) +ELF_RELOC(R_MIPS_GPREL32, 12) +ELF_RELOC(R_MIPS_UNUSED1, 13) +ELF_RELOC(R_MIPS_UNUSED2, 14) +ELF_RELOC(R_MIPS_UNUSED3, 15) +ELF_RELOC(R_MIPS_SHIFT5, 16) +ELF_RELOC(R_MIPS_SHIFT6, 17) +ELF_RELOC(R_MIPS_64, 18) +ELF_RELOC(R_MIPS_GOT_DISP, 19) +ELF_RELOC(R_MIPS_GOT_PAGE, 20) +ELF_RELOC(R_MIPS_GOT_OFST, 21) +ELF_RELOC(R_MIPS_GOT_HI16, 22) +ELF_RELOC(R_MIPS_GOT_LO16, 23) +ELF_RELOC(R_MIPS_SUB, 24) +ELF_RELOC(R_MIPS_INSERT_A, 25) +ELF_RELOC(R_MIPS_INSERT_B, 26) +ELF_RELOC(R_MIPS_DELETE, 27) +ELF_RELOC(R_MIPS_HIGHER, 28) +ELF_RELOC(R_MIPS_HIGHEST, 29) +ELF_RELOC(R_MIPS_CALL_HI16, 30) +ELF_RELOC(R_MIPS_CALL_LO16, 31) +ELF_RELOC(R_MIPS_SCN_DISP, 32) +ELF_RELOC(R_MIPS_REL16, 33) +ELF_RELOC(R_MIPS_ADD_IMMEDIATE, 34) +ELF_RELOC(R_MIPS_PJUMP, 35) +ELF_RELOC(R_MIPS_RELGOT, 36) +ELF_RELOC(R_MIPS_JALR, 37) +ELF_RELOC(R_MIPS_TLS_DTPMOD32, 38) +ELF_RELOC(R_MIPS_TLS_DTPREL32, 39) +ELF_RELOC(R_MIPS_TLS_DTPMOD64, 40) +ELF_RELOC(R_MIPS_TLS_DTPREL64, 41) +ELF_RELOC(R_MIPS_TLS_GD, 42) +ELF_RELOC(R_MIPS_TLS_LDM, 43) +ELF_RELOC(R_MIPS_TLS_DTPREL_HI16, 44) +ELF_RELOC(R_MIPS_TLS_DTPREL_LO16, 45) +ELF_RELOC(R_MIPS_TLS_GOTTPREL, 46) +ELF_RELOC(R_MIPS_TLS_TPREL32, 47) +ELF_RELOC(R_MIPS_TLS_TPREL64, 48) +ELF_RELOC(R_MIPS_TLS_TPREL_HI16, 49) +ELF_RELOC(R_MIPS_TLS_TPREL_LO16, 50) +ELF_RELOC(R_MIPS_GLOB_DAT, 51) +ELF_RELOC(R_MIPS_PC21_S2, 60) +ELF_RELOC(R_MIPS_PC26_S2, 61) +ELF_RELOC(R_MIPS_PC18_S3, 62) +ELF_RELOC(R_MIPS_PC19_S2, 63) +ELF_RELOC(R_MIPS_PCHI16, 64) +ELF_RELOC(R_MIPS_PCLO16, 65) +ELF_RELOC(R_MIPS16_26, 100) +ELF_RELOC(R_MIPS16_GPREL, 101) +ELF_RELOC(R_MIPS16_GOT16, 102) +ELF_RELOC(R_MIPS16_CALL16, 103) +ELF_RELOC(R_MIPS16_HI16, 104) +ELF_RELOC(R_MIPS16_LO16, 105) +ELF_RELOC(R_MIPS16_TLS_GD, 106) +ELF_RELOC(R_MIPS16_TLS_LDM, 107) +ELF_RELOC(R_MIPS16_TLS_DTPREL_HI16, 108) +ELF_RELOC(R_MIPS16_TLS_DTPREL_LO16, 109) +ELF_RELOC(R_MIPS16_TLS_GOTTPREL, 110) +ELF_RELOC(R_MIPS16_TLS_TPREL_HI16, 111) +ELF_RELOC(R_MIPS16_TLS_TPREL_LO16, 112) +ELF_RELOC(R_MIPS_COPY, 126) +ELF_RELOC(R_MIPS_JUMP_SLOT, 127) +ELF_RELOC(R_MICROMIPS_26_S1, 133) +ELF_RELOC(R_MICROMIPS_HI16, 134) +ELF_RELOC(R_MICROMIPS_LO16, 135) +ELF_RELOC(R_MICROMIPS_GPREL16, 136) +ELF_RELOC(R_MICROMIPS_LITERAL, 137) +ELF_RELOC(R_MICROMIPS_GOT16, 138) +ELF_RELOC(R_MICROMIPS_PC7_S1, 139) +ELF_RELOC(R_MICROMIPS_PC10_S1, 140) +ELF_RELOC(R_MICROMIPS_PC16_S1, 141) +ELF_RELOC(R_MICROMIPS_CALL16, 142) +ELF_RELOC(R_MICROMIPS_GOT_DISP, 145) +ELF_RELOC(R_MICROMIPS_GOT_PAGE, 146) +ELF_RELOC(R_MICROMIPS_GOT_OFST, 147) +ELF_RELOC(R_MICROMIPS_GOT_HI16, 148) +ELF_RELOC(R_MICROMIPS_GOT_LO16, 149) +ELF_RELOC(R_MICROMIPS_SUB, 150) +ELF_RELOC(R_MICROMIPS_HIGHER, 151) +ELF_RELOC(R_MICROMIPS_HIGHEST, 152) +ELF_RELOC(R_MICROMIPS_CALL_HI16, 153) +ELF_RELOC(R_MICROMIPS_CALL_LO16, 154) +ELF_RELOC(R_MICROMIPS_SCN_DISP, 155) +ELF_RELOC(R_MICROMIPS_JALR, 156) +ELF_RELOC(R_MICROMIPS_HI0_LO16, 157) +ELF_RELOC(R_MICROMIPS_TLS_GD, 162) +ELF_RELOC(R_MICROMIPS_TLS_LDM, 163) +ELF_RELOC(R_MICROMIPS_TLS_DTPREL_HI16, 164) +ELF_RELOC(R_MICROMIPS_TLS_DTPREL_LO16, 165) +ELF_RELOC(R_MICROMIPS_TLS_GOTTPREL, 166) +ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169) +ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170) +ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) +ELF_RELOC(R_MICROMIPS_PC23_S2, 173) +ELF_RELOC(R_MIPS_NUM, 218) +ELF_RELOC(R_MIPS_PC32, 248) diff --git a/include/llvm/Support/ELFRelocs/PowerPC.def b/include/llvm/Support/ELFRelocs/PowerPC.def new file mode 100644 index 000000000000..b6c39419b0f7 --- /dev/null +++ b/include/llvm/Support/ELFRelocs/PowerPC.def @@ -0,0 +1,61 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_PPC_NONE, 0) /* No relocation. */ +ELF_RELOC(R_PPC_ADDR32, 1) +ELF_RELOC(R_PPC_ADDR24, 2) +ELF_RELOC(R_PPC_ADDR16, 3) +ELF_RELOC(R_PPC_ADDR16_LO, 4) +ELF_RELOC(R_PPC_ADDR16_HI, 5) +ELF_RELOC(R_PPC_ADDR16_HA, 6) +ELF_RELOC(R_PPC_ADDR14, 7) +ELF_RELOC(R_PPC_ADDR14_BRTAKEN, 8) +ELF_RELOC(R_PPC_ADDR14_BRNTAKEN, 9) +ELF_RELOC(R_PPC_REL24, 10) +ELF_RELOC(R_PPC_REL14, 11) +ELF_RELOC(R_PPC_REL14_BRTAKEN, 12) +ELF_RELOC(R_PPC_REL14_BRNTAKEN, 13) +ELF_RELOC(R_PPC_GOT16, 14) +ELF_RELOC(R_PPC_GOT16_LO, 15) +ELF_RELOC(R_PPC_GOT16_HI, 16) +ELF_RELOC(R_PPC_GOT16_HA, 17) +ELF_RELOC(R_PPC_PLTREL24, 18) +ELF_RELOC(R_PPC_JMP_SLOT, 21) +ELF_RELOC(R_PPC_LOCAL24PC, 23) +ELF_RELOC(R_PPC_REL32, 26) +ELF_RELOC(R_PPC_TLS, 67) +ELF_RELOC(R_PPC_DTPMOD32, 68) +ELF_RELOC(R_PPC_TPREL16, 69) +ELF_RELOC(R_PPC_TPREL16_LO, 70) +ELF_RELOC(R_PPC_TPREL16_HI, 71) +ELF_RELOC(R_PPC_TPREL16_HA, 72) +ELF_RELOC(R_PPC_TPREL32, 73) +ELF_RELOC(R_PPC_DTPREL16, 74) +ELF_RELOC(R_PPC_DTPREL16_LO, 75) +ELF_RELOC(R_PPC_DTPREL16_HI, 76) +ELF_RELOC(R_PPC_DTPREL16_HA, 77) +ELF_RELOC(R_PPC_DTPREL32, 78) +ELF_RELOC(R_PPC_GOT_TLSGD16, 79) +ELF_RELOC(R_PPC_GOT_TLSGD16_LO, 80) +ELF_RELOC(R_PPC_GOT_TLSGD16_HI, 81) +ELF_RELOC(R_PPC_GOT_TLSGD16_HA, 82) +ELF_RELOC(R_PPC_GOT_TLSLD16, 83) +ELF_RELOC(R_PPC_GOT_TLSLD16_LO, 84) +ELF_RELOC(R_PPC_GOT_TLSLD16_HI, 85) +ELF_RELOC(R_PPC_GOT_TLSLD16_HA, 86) +ELF_RELOC(R_PPC_GOT_TPREL16, 87) +ELF_RELOC(R_PPC_GOT_TPREL16_LO, 88) +ELF_RELOC(R_PPC_GOT_TPREL16_HI, 89) +ELF_RELOC(R_PPC_GOT_TPREL16_HA, 90) +ELF_RELOC(R_PPC_GOT_DTPREL16, 91) +ELF_RELOC(R_PPC_GOT_DTPREL16_LO, 92) +ELF_RELOC(R_PPC_GOT_DTPREL16_HI, 93) +ELF_RELOC(R_PPC_GOT_DTPREL16_HA, 94) +ELF_RELOC(R_PPC_TLSGD, 95) +ELF_RELOC(R_PPC_TLSLD, 96) +ELF_RELOC(R_PPC_REL16, 249) +ELF_RELOC(R_PPC_REL16_LO, 250) +ELF_RELOC(R_PPC_REL16_HI, 251) +ELF_RELOC(R_PPC_REL16_HA, 252) diff --git a/include/llvm/Support/ELFRelocs/PowerPC64.def b/include/llvm/Support/ELFRelocs/PowerPC64.def new file mode 100644 index 000000000000..7b2a3cb2235b --- /dev/null +++ b/include/llvm/Support/ELFRelocs/PowerPC64.def @@ -0,0 +1,88 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_PPC64_NONE, 0) +ELF_RELOC(R_PPC64_ADDR32, 1) +ELF_RELOC(R_PPC64_ADDR24, 2) +ELF_RELOC(R_PPC64_ADDR16, 3) +ELF_RELOC(R_PPC64_ADDR16_LO, 4) +ELF_RELOC(R_PPC64_ADDR16_HI, 5) +ELF_RELOC(R_PPC64_ADDR16_HA, 6) +ELF_RELOC(R_PPC64_ADDR14, 7) +ELF_RELOC(R_PPC64_ADDR14_BRTAKEN, 8) +ELF_RELOC(R_PPC64_ADDR14_BRNTAKEN, 9) +ELF_RELOC(R_PPC64_REL24, 10) +ELF_RELOC(R_PPC64_REL14, 11) +ELF_RELOC(R_PPC64_REL14_BRTAKEN, 12) +ELF_RELOC(R_PPC64_REL14_BRNTAKEN, 13) +ELF_RELOC(R_PPC64_GOT16, 14) +ELF_RELOC(R_PPC64_GOT16_LO, 15) +ELF_RELOC(R_PPC64_GOT16_HI, 16) +ELF_RELOC(R_PPC64_GOT16_HA, 17) +ELF_RELOC(R_PPC64_JMP_SLOT, 21) +ELF_RELOC(R_PPC64_REL32, 26) +ELF_RELOC(R_PPC64_ADDR64, 38) +ELF_RELOC(R_PPC64_ADDR16_HIGHER, 39) +ELF_RELOC(R_PPC64_ADDR16_HIGHERA, 40) +ELF_RELOC(R_PPC64_ADDR16_HIGHEST, 41) +ELF_RELOC(R_PPC64_ADDR16_HIGHESTA, 42) +ELF_RELOC(R_PPC64_REL64, 44) +ELF_RELOC(R_PPC64_TOC16, 47) +ELF_RELOC(R_PPC64_TOC16_LO, 48) +ELF_RELOC(R_PPC64_TOC16_HI, 49) +ELF_RELOC(R_PPC64_TOC16_HA, 50) +ELF_RELOC(R_PPC64_TOC, 51) +ELF_RELOC(R_PPC64_ADDR16_DS, 56) +ELF_RELOC(R_PPC64_ADDR16_LO_DS, 57) +ELF_RELOC(R_PPC64_GOT16_DS, 58) +ELF_RELOC(R_PPC64_GOT16_LO_DS, 59) +ELF_RELOC(R_PPC64_TOC16_DS, 63) +ELF_RELOC(R_PPC64_TOC16_LO_DS, 64) +ELF_RELOC(R_PPC64_TLS, 67) +ELF_RELOC(R_PPC64_DTPMOD64, 68) +ELF_RELOC(R_PPC64_TPREL16, 69) +ELF_RELOC(R_PPC64_TPREL16_LO, 70) +ELF_RELOC(R_PPC64_TPREL16_HI, 71) +ELF_RELOC(R_PPC64_TPREL16_HA, 72) +ELF_RELOC(R_PPC64_TPREL64, 73) +ELF_RELOC(R_PPC64_DTPREL16, 74) +ELF_RELOC(R_PPC64_DTPREL16_LO, 75) +ELF_RELOC(R_PPC64_DTPREL16_HI, 76) +ELF_RELOC(R_PPC64_DTPREL16_HA, 77) +ELF_RELOC(R_PPC64_DTPREL64, 78) +ELF_RELOC(R_PPC64_GOT_TLSGD16, 79) +ELF_RELOC(R_PPC64_GOT_TLSGD16_LO, 80) +ELF_RELOC(R_PPC64_GOT_TLSGD16_HI, 81) +ELF_RELOC(R_PPC64_GOT_TLSGD16_HA, 82) +ELF_RELOC(R_PPC64_GOT_TLSLD16, 83) +ELF_RELOC(R_PPC64_GOT_TLSLD16_LO, 84) +ELF_RELOC(R_PPC64_GOT_TLSLD16_HI, 85) +ELF_RELOC(R_PPC64_GOT_TLSLD16_HA, 86) +ELF_RELOC(R_PPC64_GOT_TPREL16_DS, 87) +ELF_RELOC(R_PPC64_GOT_TPREL16_LO_DS, 88) +ELF_RELOC(R_PPC64_GOT_TPREL16_HI, 89) +ELF_RELOC(R_PPC64_GOT_TPREL16_HA, 90) +ELF_RELOC(R_PPC64_GOT_DTPREL16_DS, 91) +ELF_RELOC(R_PPC64_GOT_DTPREL16_LO_DS, 92) +ELF_RELOC(R_PPC64_GOT_DTPREL16_HI, 93) +ELF_RELOC(R_PPC64_GOT_DTPREL16_HA, 94) +ELF_RELOC(R_PPC64_TPREL16_DS, 95) +ELF_RELOC(R_PPC64_TPREL16_LO_DS, 96) +ELF_RELOC(R_PPC64_TPREL16_HIGHER, 97) +ELF_RELOC(R_PPC64_TPREL16_HIGHERA, 98) +ELF_RELOC(R_PPC64_TPREL16_HIGHEST, 99) +ELF_RELOC(R_PPC64_TPREL16_HIGHESTA, 100) +ELF_RELOC(R_PPC64_DTPREL16_DS, 101) +ELF_RELOC(R_PPC64_DTPREL16_LO_DS, 102) +ELF_RELOC(R_PPC64_DTPREL16_HIGHER, 103) +ELF_RELOC(R_PPC64_DTPREL16_HIGHERA, 104) +ELF_RELOC(R_PPC64_DTPREL16_HIGHEST, 105) +ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106) +ELF_RELOC(R_PPC64_TLSGD, 107) +ELF_RELOC(R_PPC64_TLSLD, 108) +ELF_RELOC(R_PPC64_REL16, 249) +ELF_RELOC(R_PPC64_REL16_LO, 250) +ELF_RELOC(R_PPC64_REL16_HI, 251) +ELF_RELOC(R_PPC64_REL16_HA, 252) diff --git a/include/llvm/Support/ELFRelocs/Sparc.def b/include/llvm/Support/ELFRelocs/Sparc.def new file mode 100644 index 000000000000..d6772ea675d6 --- /dev/null +++ b/include/llvm/Support/ELFRelocs/Sparc.def @@ -0,0 +1,89 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_SPARC_NONE, 0) +ELF_RELOC(R_SPARC_8, 1) +ELF_RELOC(R_SPARC_16, 2) +ELF_RELOC(R_SPARC_32, 3) +ELF_RELOC(R_SPARC_DISP8, 4) +ELF_RELOC(R_SPARC_DISP16, 5) +ELF_RELOC(R_SPARC_DISP32, 6) +ELF_RELOC(R_SPARC_WDISP30, 7) +ELF_RELOC(R_SPARC_WDISP22, 8) +ELF_RELOC(R_SPARC_HI22, 9) +ELF_RELOC(R_SPARC_22, 10) +ELF_RELOC(R_SPARC_13, 11) +ELF_RELOC(R_SPARC_LO10, 12) +ELF_RELOC(R_SPARC_GOT10, 13) +ELF_RELOC(R_SPARC_GOT13, 14) +ELF_RELOC(R_SPARC_GOT22, 15) +ELF_RELOC(R_SPARC_PC10, 16) +ELF_RELOC(R_SPARC_PC22, 17) +ELF_RELOC(R_SPARC_WPLT30, 18) +ELF_RELOC(R_SPARC_COPY, 19) +ELF_RELOC(R_SPARC_GLOB_DAT, 20) +ELF_RELOC(R_SPARC_JMP_SLOT, 21) +ELF_RELOC(R_SPARC_RELATIVE, 22) +ELF_RELOC(R_SPARC_UA32, 23) +ELF_RELOC(R_SPARC_PLT32, 24) +ELF_RELOC(R_SPARC_HIPLT22, 25) +ELF_RELOC(R_SPARC_LOPLT10, 26) +ELF_RELOC(R_SPARC_PCPLT32, 27) +ELF_RELOC(R_SPARC_PCPLT22, 28) +ELF_RELOC(R_SPARC_PCPLT10, 29) +ELF_RELOC(R_SPARC_10, 30) +ELF_RELOC(R_SPARC_11, 31) +ELF_RELOC(R_SPARC_64, 32) +ELF_RELOC(R_SPARC_OLO10, 33) +ELF_RELOC(R_SPARC_HH22, 34) +ELF_RELOC(R_SPARC_HM10, 35) +ELF_RELOC(R_SPARC_LM22, 36) +ELF_RELOC(R_SPARC_PC_HH22, 37) +ELF_RELOC(R_SPARC_PC_HM10, 38) +ELF_RELOC(R_SPARC_PC_LM22, 39) +ELF_RELOC(R_SPARC_WDISP16, 40) +ELF_RELOC(R_SPARC_WDISP19, 41) +ELF_RELOC(R_SPARC_7, 43) +ELF_RELOC(R_SPARC_5, 44) +ELF_RELOC(R_SPARC_6, 45) +ELF_RELOC(R_SPARC_DISP64, 46) +ELF_RELOC(R_SPARC_PLT64, 47) +ELF_RELOC(R_SPARC_HIX22, 48) +ELF_RELOC(R_SPARC_LOX10, 49) +ELF_RELOC(R_SPARC_H44, 50) +ELF_RELOC(R_SPARC_M44, 51) +ELF_RELOC(R_SPARC_L44, 52) +ELF_RELOC(R_SPARC_REGISTER, 53) +ELF_RELOC(R_SPARC_UA64, 54) +ELF_RELOC(R_SPARC_UA16, 55) +ELF_RELOC(R_SPARC_TLS_GD_HI22, 56) +ELF_RELOC(R_SPARC_TLS_GD_LO10, 57) +ELF_RELOC(R_SPARC_TLS_GD_ADD, 58) +ELF_RELOC(R_SPARC_TLS_GD_CALL, 59) +ELF_RELOC(R_SPARC_TLS_LDM_HI22, 60) +ELF_RELOC(R_SPARC_TLS_LDM_LO10, 61) +ELF_RELOC(R_SPARC_TLS_LDM_ADD, 62) +ELF_RELOC(R_SPARC_TLS_LDM_CALL, 63) +ELF_RELOC(R_SPARC_TLS_LDO_HIX22, 64) +ELF_RELOC(R_SPARC_TLS_LDO_LOX10, 65) +ELF_RELOC(R_SPARC_TLS_LDO_ADD, 66) +ELF_RELOC(R_SPARC_TLS_IE_HI22, 67) +ELF_RELOC(R_SPARC_TLS_IE_LO10, 68) +ELF_RELOC(R_SPARC_TLS_IE_LD, 69) +ELF_RELOC(R_SPARC_TLS_IE_LDX, 70) +ELF_RELOC(R_SPARC_TLS_IE_ADD, 71) +ELF_RELOC(R_SPARC_TLS_LE_HIX22, 72) +ELF_RELOC(R_SPARC_TLS_LE_LOX10, 73) +ELF_RELOC(R_SPARC_TLS_DTPMOD32, 74) +ELF_RELOC(R_SPARC_TLS_DTPMOD64, 75) +ELF_RELOC(R_SPARC_TLS_DTPOFF32, 76) +ELF_RELOC(R_SPARC_TLS_DTPOFF64, 77) +ELF_RELOC(R_SPARC_TLS_TPOFF32, 78) +ELF_RELOC(R_SPARC_TLS_TPOFF64, 79) +ELF_RELOC(R_SPARC_GOTDATA_HIX22, 80) +ELF_RELOC(R_SPARC_GOTDATA_LOX22, 81) +ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82) +ELF_RELOC(R_SPARC_GOTDATA_OP_LOX22, 83) +ELF_RELOC(R_SPARC_GOTDATA_OP, 84) diff --git a/include/llvm/Support/ELFRelocs/SystemZ.def b/include/llvm/Support/ELFRelocs/SystemZ.def new file mode 100644 index 000000000000..711f94011f2c --- /dev/null +++ b/include/llvm/Support/ELFRelocs/SystemZ.def @@ -0,0 +1,67 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_390_NONE, 0) +ELF_RELOC(R_390_8, 1) +ELF_RELOC(R_390_12, 2) +ELF_RELOC(R_390_16, 3) +ELF_RELOC(R_390_32, 4) +ELF_RELOC(R_390_PC32, 5) +ELF_RELOC(R_390_GOT12, 6) +ELF_RELOC(R_390_GOT32, 7) +ELF_RELOC(R_390_PLT32, 8) +ELF_RELOC(R_390_COPY, 9) +ELF_RELOC(R_390_GLOB_DAT, 10) +ELF_RELOC(R_390_JMP_SLOT, 11) +ELF_RELOC(R_390_RELATIVE, 12) +ELF_RELOC(R_390_GOTOFF, 13) +ELF_RELOC(R_390_GOTPC, 14) +ELF_RELOC(R_390_GOT16, 15) +ELF_RELOC(R_390_PC16, 16) +ELF_RELOC(R_390_PC16DBL, 17) +ELF_RELOC(R_390_PLT16DBL, 18) +ELF_RELOC(R_390_PC32DBL, 19) +ELF_RELOC(R_390_PLT32DBL, 20) +ELF_RELOC(R_390_GOTPCDBL, 21) +ELF_RELOC(R_390_64, 22) +ELF_RELOC(R_390_PC64, 23) +ELF_RELOC(R_390_GOT64, 24) +ELF_RELOC(R_390_PLT64, 25) +ELF_RELOC(R_390_GOTENT, 26) +ELF_RELOC(R_390_GOTOFF16, 27) +ELF_RELOC(R_390_GOTOFF64, 28) +ELF_RELOC(R_390_GOTPLT12, 29) +ELF_RELOC(R_390_GOTPLT16, 30) +ELF_RELOC(R_390_GOTPLT32, 31) +ELF_RELOC(R_390_GOTPLT64, 32) +ELF_RELOC(R_390_GOTPLTENT, 33) +ELF_RELOC(R_390_PLTOFF16, 34) +ELF_RELOC(R_390_PLTOFF32, 35) +ELF_RELOC(R_390_PLTOFF64, 36) +ELF_RELOC(R_390_TLS_LOAD, 37) +ELF_RELOC(R_390_TLS_GDCALL, 38) +ELF_RELOC(R_390_TLS_LDCALL, 39) +ELF_RELOC(R_390_TLS_GD32, 40) +ELF_RELOC(R_390_TLS_GD64, 41) +ELF_RELOC(R_390_TLS_GOTIE12, 42) +ELF_RELOC(R_390_TLS_GOTIE32, 43) +ELF_RELOC(R_390_TLS_GOTIE64, 44) +ELF_RELOC(R_390_TLS_LDM32, 45) +ELF_RELOC(R_390_TLS_LDM64, 46) +ELF_RELOC(R_390_TLS_IE32, 47) +ELF_RELOC(R_390_TLS_IE64, 48) +ELF_RELOC(R_390_TLS_IEENT, 49) +ELF_RELOC(R_390_TLS_LE32, 50) +ELF_RELOC(R_390_TLS_LE64, 51) +ELF_RELOC(R_390_TLS_LDO32, 52) +ELF_RELOC(R_390_TLS_LDO64, 53) +ELF_RELOC(R_390_TLS_DTPMOD, 54) +ELF_RELOC(R_390_TLS_DTPOFF, 55) +ELF_RELOC(R_390_TLS_TPOFF, 56) +ELF_RELOC(R_390_20, 57) +ELF_RELOC(R_390_GOT20, 58) +ELF_RELOC(R_390_GOTPLT20, 59) +ELF_RELOC(R_390_TLS_GOTIE20, 60) +ELF_RELOC(R_390_IRELATIVE, 61) diff --git a/include/llvm/Support/ELFRelocs/i386.def b/include/llvm/Support/ELFRelocs/i386.def new file mode 100644 index 000000000000..45eae7fe426b --- /dev/null +++ b/include/llvm/Support/ELFRelocs/i386.def @@ -0,0 +1,47 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// TODO: this is just a subset +ELF_RELOC(R_386_NONE, 0) +ELF_RELOC(R_386_32, 1) +ELF_RELOC(R_386_PC32, 2) +ELF_RELOC(R_386_GOT32, 3) +ELF_RELOC(R_386_PLT32, 4) +ELF_RELOC(R_386_COPY, 5) +ELF_RELOC(R_386_GLOB_DAT, 6) +ELF_RELOC(R_386_JUMP_SLOT, 7) +ELF_RELOC(R_386_RELATIVE, 8) +ELF_RELOC(R_386_GOTOFF, 9) +ELF_RELOC(R_386_GOTPC, 10) +ELF_RELOC(R_386_32PLT, 11) +ELF_RELOC(R_386_TLS_TPOFF, 14) +ELF_RELOC(R_386_TLS_IE, 15) +ELF_RELOC(R_386_TLS_GOTIE, 16) +ELF_RELOC(R_386_TLS_LE, 17) +ELF_RELOC(R_386_TLS_GD, 18) +ELF_RELOC(R_386_TLS_LDM, 19) +ELF_RELOC(R_386_16, 20) +ELF_RELOC(R_386_PC16, 21) +ELF_RELOC(R_386_8, 22) +ELF_RELOC(R_386_PC8, 23) +ELF_RELOC(R_386_TLS_GD_32, 24) +ELF_RELOC(R_386_TLS_GD_PUSH, 25) +ELF_RELOC(R_386_TLS_GD_CALL, 26) +ELF_RELOC(R_386_TLS_GD_POP, 27) +ELF_RELOC(R_386_TLS_LDM_32, 28) +ELF_RELOC(R_386_TLS_LDM_PUSH, 29) +ELF_RELOC(R_386_TLS_LDM_CALL, 30) +ELF_RELOC(R_386_TLS_LDM_POP, 31) +ELF_RELOC(R_386_TLS_LDO_32, 32) +ELF_RELOC(R_386_TLS_IE_32, 33) +ELF_RELOC(R_386_TLS_LE_32, 34) +ELF_RELOC(R_386_TLS_DTPMOD32, 35) +ELF_RELOC(R_386_TLS_DTPOFF32, 36) +ELF_RELOC(R_386_TLS_TPOFF32, 37) +ELF_RELOC(R_386_TLS_GOTDESC, 39) +ELF_RELOC(R_386_TLS_DESC_CALL, 40) +ELF_RELOC(R_386_TLS_DESC, 41) +ELF_RELOC(R_386_IRELATIVE, 42) +ELF_RELOC(R_386_NUM, 43) diff --git a/include/llvm/Support/ELFRelocs/x86_64.def b/include/llvm/Support/ELFRelocs/x86_64.def new file mode 100644 index 000000000000..36ad0618eb2d --- /dev/null +++ b/include/llvm/Support/ELFRelocs/x86_64.def @@ -0,0 +1,44 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_X86_64_NONE, 0) +ELF_RELOC(R_X86_64_64, 1) +ELF_RELOC(R_X86_64_PC32, 2) +ELF_RELOC(R_X86_64_GOT32, 3) +ELF_RELOC(R_X86_64_PLT32, 4) +ELF_RELOC(R_X86_64_COPY, 5) +ELF_RELOC(R_X86_64_GLOB_DAT, 6) +ELF_RELOC(R_X86_64_JUMP_SLOT, 7) +ELF_RELOC(R_X86_64_RELATIVE, 8) +ELF_RELOC(R_X86_64_GOTPCREL, 9) +ELF_RELOC(R_X86_64_32, 10) +ELF_RELOC(R_X86_64_32S, 11) +ELF_RELOC(R_X86_64_16, 12) +ELF_RELOC(R_X86_64_PC16, 13) +ELF_RELOC(R_X86_64_8, 14) +ELF_RELOC(R_X86_64_PC8, 15) +ELF_RELOC(R_X86_64_DTPMOD64, 16) +ELF_RELOC(R_X86_64_DTPOFF64, 17) +ELF_RELOC(R_X86_64_TPOFF64, 18) +ELF_RELOC(R_X86_64_TLSGD, 19) +ELF_RELOC(R_X86_64_TLSLD, 20) +ELF_RELOC(R_X86_64_DTPOFF32, 21) +ELF_RELOC(R_X86_64_GOTTPOFF, 22) +ELF_RELOC(R_X86_64_TPOFF32, 23) +ELF_RELOC(R_X86_64_PC64, 24) +ELF_RELOC(R_X86_64_GOTOFF64, 25) +ELF_RELOC(R_X86_64_GOTPC32, 26) +ELF_RELOC(R_X86_64_GOT64, 27) +ELF_RELOC(R_X86_64_GOTPCREL64, 28) +ELF_RELOC(R_X86_64_GOTPC64, 29) +ELF_RELOC(R_X86_64_GOTPLT64, 30) +ELF_RELOC(R_X86_64_PLTOFF64, 31) +ELF_RELOC(R_X86_64_SIZE32, 32) +ELF_RELOC(R_X86_64_SIZE64, 33) +ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34) +ELF_RELOC(R_X86_64_TLSDESC_CALL, 35) +ELF_RELOC(R_X86_64_TLSDESC, 36) +ELF_RELOC(R_X86_64_IRELATIVE, 37) + diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 455d0fc241f2..47b82fdc4975 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -93,15 +93,40 @@ struct packed_endian_specific_integral { (void*)Value.buffer, newValue); } + packed_endian_specific_integral &operator+=(value_type newValue) { + *this = *this + newValue; + return *this; + } + + packed_endian_specific_integral &operator-=(value_type newValue) { + *this = *this - newValue; + return *this; + } + private: AlignedCharArray<PickAlignment<value_type, alignment>::value, sizeof(value_type)> Value; + +public: + struct ref { + explicit ref(void *Ptr) : Ptr(Ptr) {} + + operator value_type() const { + return endian::read<value_type, endian, alignment>(Ptr); + } + + void operator=(value_type NewValue) { + endian::write<value_type, endian, alignment>(Ptr, NewValue); + } + + private: + void *Ptr; + }; }; + } // end namespace detail typedef detail::packed_endian_specific_integral - <uint8_t, little, unaligned> ulittle8_t; -typedef detail::packed_endian_specific_integral <uint16_t, little, unaligned> ulittle16_t; typedef detail::packed_endian_specific_integral <uint32_t, little, unaligned> ulittle32_t; @@ -109,8 +134,6 @@ typedef detail::packed_endian_specific_integral <uint64_t, little, unaligned> ulittle64_t; typedef detail::packed_endian_specific_integral - <int8_t, little, unaligned> little8_t; -typedef detail::packed_endian_specific_integral <int16_t, little, unaligned> little16_t; typedef detail::packed_endian_specific_integral <int32_t, little, unaligned> little32_t; @@ -118,8 +141,6 @@ typedef detail::packed_endian_specific_integral <int64_t, little, unaligned> little64_t; typedef detail::packed_endian_specific_integral - <uint8_t, little, aligned> aligned_ulittle8_t; -typedef detail::packed_endian_specific_integral <uint16_t, little, aligned> aligned_ulittle16_t; typedef detail::packed_endian_specific_integral <uint32_t, little, aligned> aligned_ulittle32_t; @@ -127,8 +148,6 @@ typedef detail::packed_endian_specific_integral <uint64_t, little, aligned> aligned_ulittle64_t; typedef detail::packed_endian_specific_integral - <int8_t, little, aligned> aligned_little8_t; -typedef detail::packed_endian_specific_integral <int16_t, little, aligned> aligned_little16_t; typedef detail::packed_endian_specific_integral <int32_t, little, aligned> aligned_little32_t; @@ -136,8 +155,6 @@ typedef detail::packed_endian_specific_integral <int64_t, little, aligned> aligned_little64_t; typedef detail::packed_endian_specific_integral - <uint8_t, big, unaligned> ubig8_t; -typedef detail::packed_endian_specific_integral <uint16_t, big, unaligned> ubig16_t; typedef detail::packed_endian_specific_integral <uint32_t, big, unaligned> ubig32_t; @@ -145,8 +162,6 @@ typedef detail::packed_endian_specific_integral <uint64_t, big, unaligned> ubig64_t; typedef detail::packed_endian_specific_integral - <int8_t, big, unaligned> big8_t; -typedef detail::packed_endian_specific_integral <int16_t, big, unaligned> big16_t; typedef detail::packed_endian_specific_integral <int32_t, big, unaligned> big32_t; @@ -154,8 +169,6 @@ typedef detail::packed_endian_specific_integral <int64_t, big, unaligned> big64_t; typedef detail::packed_endian_specific_integral - <uint8_t, big, aligned> aligned_ubig8_t; -typedef detail::packed_endian_specific_integral <uint16_t, big, aligned> aligned_ubig16_t; typedef detail::packed_endian_specific_integral <uint32_t, big, aligned> aligned_ubig32_t; @@ -163,8 +176,6 @@ typedef detail::packed_endian_specific_integral <uint64_t, big, aligned> aligned_ubig64_t; typedef detail::packed_endian_specific_integral - <int8_t, big, aligned> aligned_big8_t; -typedef detail::packed_endian_specific_integral <int16_t, big, aligned> aligned_big16_t; typedef detail::packed_endian_specific_integral <int32_t, big, aligned> aligned_big32_t; diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h index 89c66d3b8480..94f372f020b4 100644 --- a/include/llvm/Support/EndianStream.h +++ b/include/llvm/Support/EndianStream.h @@ -12,11 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef _LLVM_SUPPORT_ENDIAN_STREAM_H_ -#define _LLVM_SUPPORT_ENDIAN_STREAM_H_ +#ifndef LLVM_SUPPORT_ENDIANSTREAM_H +#define LLVM_SUPPORT_ENDIANSTREAM_H -#include <llvm/Support/Endian.h> -#include <llvm/Support/raw_ostream.h> +#include "llvm/Support/Endian.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { namespace support { @@ -36,4 +36,4 @@ template <endianness endian> struct Writer { } // end namespace support } // end namespace llvm -#endif // _LLVM_SUPPORT_ENDIAN_STREAM_H_ +#endif diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 0742a2d06f71..84763deea0f9 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ERROR_OR_H -#define LLVM_SUPPORT_ERROR_OR_H +#ifndef LLVM_SUPPORT_ERROROR_H +#define LLVM_SUPPORT_ERROROR_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" @@ -68,9 +68,9 @@ public: /// \endcode /// /// -/// An implicit conversion to bool provides a way to check if there was an -/// error. The unary * and -> operators provide pointer like access to the -/// value. Accessing the value when there is an error has undefined behavior. +/// Implicit conversion to bool returns true if there is a usable value. The +/// unary * and -> operators provide pointer like access to the value. Accessing +/// the value when there is an error has undefined behavior. /// /// When T is a reference type the behaivor is slightly different. The reference /// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and @@ -115,19 +115,19 @@ public: } template <class OtherT> - ErrorOr(const ErrorOr<OtherT> &Other) { + ErrorOr( + const ErrorOr<OtherT> &Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = + nullptr) { copyConstruct(Other); } - ErrorOr &operator =(const ErrorOr &Other) { - copyAssign(Other); - return *this; - } - template <class OtherT> - ErrorOr &operator =(const ErrorOr<OtherT> &Other) { - copyAssign(Other); - return *this; + explicit ErrorOr( + const ErrorOr<OtherT> &Other, + typename std::enable_if< + !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) { + copyConstruct(Other); } ErrorOr(ErrorOr &&Other) { @@ -135,17 +135,29 @@ public: } template <class OtherT> - ErrorOr(ErrorOr<OtherT> &&Other) { + ErrorOr( + ErrorOr<OtherT> &&Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = + nullptr) { moveConstruct(std::move(Other)); } - ErrorOr &operator =(ErrorOr &&Other) { - moveAssign(std::move(Other)); + // This might eventually need SFINAE but it's more complex than is_convertible + // & I'm too lazy to write it right now. + template <class OtherT> + explicit ErrorOr( + ErrorOr<OtherT> &&Other, + typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator=(const ErrorOr &Other) { + copyAssign(Other); return *this; } - template <class OtherT> - ErrorOr &operator =(ErrorOr<OtherT> &&Other) { + ErrorOr &operator=(ErrorOr &&Other) { moveAssign(std::move(Other)); return *this; } @@ -161,7 +173,7 @@ public: } reference get() { return *getStorage(); } - const_reference get() const { return const_cast<ErrorOr<T> >(this)->get(); } + const_reference get() const { return const_cast<ErrorOr<T> *>(this)->get(); } std::error_code getError() const { return HasError ? *getErrorStorage() : std::error_code(); diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 0a9a97995156..9f02a16e3d65 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -66,7 +66,7 @@ public: /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. - std::error_code commit(int64_t NewSmallerSize = -1); + std::error_code commit(); /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor @@ -77,7 +77,7 @@ private: FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; - FileOutputBuffer(llvm::sys::fs::mapped_file_region *R, + FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R, StringRef Path, StringRef TempPath); std::unique_ptr<llvm::sys::fs::mapped_file_region> Region; diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 556701c3ba34..b60c1b07043b 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -226,6 +226,7 @@ struct file_magic { unknown = 0, ///< Unrecognized file bitcode, ///< Bitcode file archive, ///< ar style archive file + elf, ///< ELF Unknown type elf_relocatable, ///< ELF Relocatable object file elf_executable, ///< ELF Executable image elf_shared_object, ///< ELF dynamically linked shared lib @@ -276,14 +277,6 @@ private: /// platform-specific error_code. std::error_code make_absolute(SmallVectorImpl<char> &path); -/// @brief Normalize path separators in \a Path -/// -/// If the path contains any '\' separators, they are transformed into '/'. -/// This is particularly useful when cross-compiling Windows on Linux, but is -/// safe to invoke on Windows, which accepts both characters as a path -/// separator. -std::error_code normalize_separators(SmallVectorImpl<char> &Path); - /// @brief Create all the non-existent directories in path. /// /// @param path Directories to create. @@ -343,11 +336,11 @@ std::error_code copy_file(const Twine &From, const Twine &To); /// @brief Resize path to size. File is resized as if by POSIX truncate(). /// -/// @param path Input path. -/// @param size Size to resize to. +/// @param FD Input file descriptor. +/// @param Size Size to resize to. /// @returns errc::success if \a path has been resized to \a size, otherwise a /// platform-specific error_code. -std::error_code resize_file(const Twine &path, uint64_t size); +std::error_code resize_file(int FD, uint64_t Size); /// @} /// @name Physical Observers @@ -360,33 +353,38 @@ std::error_code resize_file(const Twine &path, uint64_t size); /// not. bool exists(file_status status); -/// @brief Does file exist? +enum class AccessMode { Exist, Write, Execute }; + +/// @brief Can the file be accessed? /// -/// @param path Input path. -/// @param result Set to true if the file represented by status exists, false if -/// it does not. Undefined otherwise. -/// @returns errc::success if result has been successfully set, otherwise a +/// @param Path Input path. +/// @returns errc::success if the path can be accessed, otherwise a /// platform-specific error_code. -std::error_code exists(const Twine &path, bool &result); +std::error_code access(const Twine &Path, AccessMode Mode); -/// @brief Simpler version of exists for clients that don't need to -/// differentiate between an error and false. -inline bool exists(const Twine &path) { - bool result; - return !exists(path, result) && result; +/// @brief Does file exist? +/// +/// @param Path Input path. +/// @returns True if it exists, false otherwise. +inline bool exists(const Twine &Path) { + return !access(Path, AccessMode::Exist); } /// @brief Can we execute this file? /// /// @param Path Input path. /// @returns True if we can execute it, false otherwise. -bool can_execute(const Twine &Path); +inline bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute); +} /// @brief Can we write this file? /// /// @param Path Input path. /// @returns True if we can write to it, false otherwise. -bool can_write(const Twine &Path); +inline bool can_write(const Twine &Path) { + return !access(Path, AccessMode::Write); +} /// @brief Do file_status's represent the same thing? /// @@ -639,49 +637,20 @@ public: private: /// Platform-specific mapping state. - mapmode Mode; uint64_t Size; void *Mapping; -#ifdef LLVM_ON_WIN32 - int FileDescriptor; - void *FileHandle; - void *FileMappingHandle; -#endif - std::error_code init(int FD, bool CloseFD, uint64_t Offset); + std::error_code init(int FD, uint64_t Offset, mapmode Mode); public: - typedef char char_type; - - mapped_file_region(mapped_file_region&&); - mapped_file_region &operator =(mapped_file_region&&); - - /// Construct a mapped_file_region at \a path starting at \a offset of length - /// \a length and with access \a mode. - /// - /// \param path Path to the file to map. If it does not exist it will be - /// created. - /// \param mode How to map the memory. - /// \param length Number of bytes to map in starting at \a offset. If the file - /// is shorter than this, it will be extended. If \a length is - /// 0, the entire file will be mapped. - /// \param offset Byte offset from the beginning of the file where the map - /// should begin. Must be a multiple of - /// mapped_file_region::alignment(). - /// \param ec This is set to errc::success if the map was constructed - /// successfully. Otherwise it is set to a platform dependent error. - mapped_file_region(const Twine &path, mapmode mode, uint64_t length, - uint64_t offset, std::error_code &ec); - /// \param fd An open file descriptor to map. mapped_file_region takes /// ownership if closefd is true. It must have been opended in the correct /// mode. - mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length, - uint64_t offset, std::error_code &ec); + mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, + std::error_code &ec); ~mapped_file_region(); - mapmode flags() const; uint64_t size() const; char *data() const; diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index b713cc72e852..5d599e96ec3a 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -23,6 +23,8 @@ #ifndef LLVM_SUPPORT_FORMAT_H #define LLVM_SUPPORT_FORMAT_H +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <cstdio> #ifdef _MSC_VER @@ -41,6 +43,7 @@ namespace llvm { class format_object_base { protected: const char *Fmt; + ~format_object_base() {} // Disallow polymorphic deletion. virtual void home(); // Out of line virtual method. /// Call snprintf() for this object, on the given buffer and size. @@ -48,7 +51,6 @@ protected: public: format_object_base(const char *fmt) : Fmt(fmt) {} - virtual ~format_object_base() {} /// Format the object into the specified buffer. On success, this returns /// the length of the formatted string. If the buffer is too small, this @@ -79,7 +81,7 @@ public: /// returns whether or not it is big enough. template <typename T> -class format_object1 : public format_object_base { +class format_object1 final : public format_object_base { T Val; public: format_object1(const char *fmt, const T &val) @@ -92,7 +94,7 @@ public: }; template <typename T1, typename T2> -class format_object2 : public format_object_base { +class format_object2 final : public format_object_base { T1 Val1; T2 Val2; public: @@ -106,7 +108,7 @@ public: }; template <typename T1, typename T2, typename T3> -class format_object3 : public format_object_base { +class format_object3 final : public format_object_base { T1 Val1; T2 Val2; T3 Val3; @@ -121,7 +123,7 @@ public: }; template <typename T1, typename T2, typename T3, typename T4> -class format_object4 : public format_object_base { +class format_object4 final : public format_object_base { T1 Val1; T2 Val2; T3 Val3; @@ -138,7 +140,7 @@ public: }; template <typename T1, typename T2, typename T3, typename T4, typename T5> -class format_object5 : public format_object_base { +class format_object5 final : public format_object_base { T1 Val1; T2 Val2; T3 Val3; @@ -158,7 +160,7 @@ public: template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> -class format_object6 : public format_object_base { +class format_object6 final : public format_object_base { T1 Val1; T2 Val2; T3 Val3; @@ -225,6 +227,66 @@ format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, Val5, Val6); } +/// This is a helper class used for left_justify() and right_justify(). +class FormattedString { + StringRef Str; + unsigned Width; + bool RightJustify; + friend class raw_ostream; +public: + FormattedString(StringRef S, unsigned W, bool R) + : Str(S), Width(W), RightJustify(R) { } +}; + +/// left_justify - append spaces after string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is written with no padding. +inline FormattedString left_justify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, false); +} + +/// right_justify - add spaces before string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is written with no padding. +inline FormattedString right_justify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, true); +} + +/// This is a helper class used for format_hex() and format_decimal(). +class FormattedNumber { + uint64_t HexValue; + int64_t DecValue; + unsigned Width; + bool Hex; + bool Upper; + friend class raw_ostream; +public: + FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U) + : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { } +}; + +/// format_hex - Output \p N as a fixed width hexadecimal. If number will not +/// fit in width, full number is still printed. Examples: +/// OS << format_hex(255, 4) => 0xff +/// OS << format_hex(255, 4, true) => 0xFF +/// OS << format_hex(255, 6) => 0x00ff +/// OS << format_hex(255, 2) => 0xff +inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) { + assert(Width <= 18 && "hex width must be <= 18"); + return FormattedNumber(N, 0, Width, true, Upper); +} + +/// format_decimal - Output \p N as a right justified, fixed-width decimal. If +/// number will not fit in width, full number is still printed. Examples: +/// OS << format_decimal(0, 5) => " 0" +/// OS << format_decimal(255, 5) => " 255" +/// OS << format_decimal(-1, 3) => " -1" +/// OS << format_decimal(12345, 3) => "12345" +inline FormattedNumber format_decimal(int64_t N, unsigned Width) { + return FormattedNumber(0, N, Width, false, false); +} + + } // end namespace llvm #endif diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index 0cb6cfd62ccb..e378602c7bb3 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -100,7 +100,7 @@ public: /// cursor and return true otherwise return false. bool readFunctionTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || Tag[3] != '\1') { return false; @@ -113,7 +113,7 @@ public: /// cursor and return true otherwise return false. bool readBlockTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || Tag[3] != '\x01') { return false; @@ -126,7 +126,7 @@ public: /// cursor and return true otherwise return false. bool readEdgeTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || Tag[3] != '\x01') { return false; @@ -139,7 +139,7 @@ public: /// cursor and return true otherwise return false. bool readLineTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || Tag[3] != '\x01') { return false; @@ -152,7 +152,7 @@ public: /// cursor and return true otherwise return false. bool readArcTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || Tag[3] != '\1') { return false; diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index 876ab6ec71a5..fde56135a962 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -15,8 +15,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_H -#define LLVM_SUPPORT_GENERIC_DOM_TREE_H +#ifndef LLVM_SUPPORT_GENERICDOMTREE_H +#define LLVM_SUPPORT_GENERICDOMTREE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" @@ -29,76 +29,78 @@ namespace llvm { -//===----------------------------------------------------------------------===// -/// DominatorBase - Base class that other, more interesting dominator analyses +/// \brief Base class that other, more interesting dominator analyses /// inherit from. -/// -template <class NodeT> -class DominatorBase { +template <class NodeT> class DominatorBase { protected: - std::vector<NodeT*> Roots; - const bool IsPostDominators; - inline explicit DominatorBase(bool isPostDom) : - Roots(), IsPostDominators(isPostDom) {} -public: + std::vector<NodeT *> Roots; + bool IsPostDominators; + explicit DominatorBase(bool isPostDom) + : Roots(), IsPostDominators(isPostDom) {} + DominatorBase(DominatorBase &&Arg) + : Roots(std::move(Arg.Roots)), + IsPostDominators(std::move(Arg.IsPostDominators)) { + Arg.Roots.clear(); + } + DominatorBase &operator=(DominatorBase &&RHS) { + Roots = std::move(RHS.Roots); + IsPostDominators = std::move(RHS.IsPostDominators); + RHS.Roots.clear(); + return *this; + } +public: /// getRoots - Return the root blocks of the current CFG. This may include /// multiple blocks if we are computing post dominators. For forward /// dominators, this will always be a single block (the entry node). /// - inline const std::vector<NodeT*> &getRoots() const { return Roots; } + const std::vector<NodeT *> &getRoots() const { return Roots; } /// isPostDominator - Returns true if analysis based of postdoms /// bool isPostDominator() const { return IsPostDominators; } }; - -//===----------------------------------------------------------------------===// -// DomTreeNodeBase - Dominator Tree Node -template<class NodeT> class DominatorTreeBase; +template <class NodeT> class DominatorTreeBase; struct PostDominatorTree; -template <class NodeT> -class DomTreeNodeBase { +/// \brief Base class for the actual dominator tree node. +template <class NodeT> class DomTreeNodeBase { NodeT *TheBB; DomTreeNodeBase<NodeT> *IDom; std::vector<DomTreeNodeBase<NodeT> *> Children; mutable int DFSNumIn, DFSNumOut; - template<class N> friend class DominatorTreeBase; + template <class N> friend class DominatorTreeBase; friend struct PostDominatorTree; + public: typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator; typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator - const_iterator; + const_iterator; - iterator begin() { return Children.begin(); } - iterator end() { return Children.end(); } + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } const_iterator begin() const { return Children.begin(); } - const_iterator end() const { return Children.end(); } + const_iterator end() const { return Children.end(); } NodeT *getBlock() const { return TheBB; } DomTreeNodeBase<NodeT> *getIDom() const { return IDom; } - const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const { + const std::vector<DomTreeNodeBase<NodeT> *> &getChildren() const { return Children; } DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom) - : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { } + : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {} DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) { Children.push_back(C); return C; } - size_t getNumChildren() const { - return Children.size(); - } + size_t getNumChildren() const { return Children.size(); } - void clearAllChildren() { - Children.clear(); - } + void clearAllChildren() { Children.clear(); } bool compare(const DomTreeNodeBase<NodeT> *Other) const { if (getNumChildren() != Other->getNumChildren()) @@ -121,8 +123,8 @@ public: void setIDom(DomTreeNodeBase<NodeT> *NewIDom) { assert(IDom && "No immediate dominator?"); if (IDom != NewIDom) { - typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I = - std::find(IDom->Children.begin(), IDom->Children.end(), this); + typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), this); assert(I != IDom->Children.end() && "Not in immediate dominator children set!"); // I am no longer your child... @@ -138,18 +140,18 @@ public: /// not call them. unsigned getDFSNumIn() const { return DFSNumIn; } unsigned getDFSNumOut() const { return DFSNumOut; } + private: // Return true if this node is dominated by other. Use this only if DFS info // is valid. bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const { return this->DFSNumIn >= other->DFSNumIn && - this->DFSNumOut <= other->DFSNumOut; + this->DFSNumOut <= other->DFSNumOut; } }; -template<class NodeT> -inline raw_ostream &operator<<(raw_ostream &o, - const DomTreeNodeBase<NodeT> *Node) { +template <class NodeT> +raw_ostream &operator<<(raw_ostream &o, const DomTreeNodeBase<NodeT> *Node) { if (Node->getBlock()) Node->getBlock()->printAsOperand(o, false); else @@ -160,25 +162,29 @@ inline raw_ostream &operator<<(raw_ostream &o, return o << "\n"; } -template<class NodeT> -inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, - unsigned Lev) { - o.indent(2*Lev) << "[" << Lev << "] " << N; +template <class NodeT> +void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, + unsigned Lev) { + o.indent(2 * Lev) << "[" << Lev << "] " << N; for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(), - E = N->end(); I != E; ++I) - PrintDomTree<NodeT>(*I, o, Lev+1); + E = N->end(); + I != E; ++I) + PrintDomTree<NodeT>(*I, o, Lev + 1); } -//===----------------------------------------------------------------------===// -/// DominatorTree - Calculate the immediate dominator tree for a function. -/// +// The calculate routine is provided in a separate header but referenced here. +template <class FuncT, class N> +void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, + FuncT &F); -template<class FuncT, class N> -void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT, - FuncT& F); +/// \brief Core dominator tree base class. +/// +/// This class is a generic template over graph nodes. It is instantiated for +/// various graphs in the LLVM IR or in the code generator. +template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> { + DominatorTreeBase(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; + DominatorTreeBase &operator=(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; -template<class NodeT> -class DominatorTreeBase : public DominatorBase<NodeT> { bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A, const DomTreeNodeBase<NodeT> *B) const { assert(A != B); @@ -187,12 +193,24 @@ class DominatorTreeBase : public DominatorBase<NodeT> { const DomTreeNodeBase<NodeT> *IDom; while ((IDom = B->getIDom()) != nullptr && IDom != A && IDom != B) - B = IDom; // Walk up the tree + B = IDom; // Walk up the tree return IDom != nullptr; } + /// \brief Wipe this tree's state without releasing any resources. + /// + /// This is essentially a post-move helper only. It leaves the object in an + /// assignable and destroyable state, but otherwise invalid. + void wipe() { + DomTreeNodes.clear(); + IDoms.clear(); + Vertex.clear(); + Info.clear(); + RootNode = nullptr; + } + protected: - typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType; + typedef DenseMap<NodeT *, DomTreeNodeBase<NodeT> *> DomTreeNodeMapType; DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase<NodeT> *RootNode; @@ -208,17 +226,18 @@ protected: InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {} }; - DenseMap<NodeT*, NodeT*> IDoms; + DenseMap<NodeT *, NodeT *> IDoms; // Vertex - Map the DFS number to the NodeT* - std::vector<NodeT*> Vertex; + std::vector<NodeT *> Vertex; // Info - Collection of information used during the computation of idoms. - DenseMap<NodeT*, InfoRec> Info; + DenseMap<NodeT *, InfoRec> Info; void reset() { for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), - E = DomTreeNodes.end(); I != E; ++I) + E = DomTreeNodes.end(); + I != E; ++I) delete I->second; DomTreeNodes.clear(); IDoms.clear(); @@ -229,27 +248,29 @@ protected: // NewBB is split and now it has one successor. Update dominator tree to // reflect this change. - template<class N, class GraphT> - void Split(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* NewBB) { + template <class N, class GraphT> + void Split(DominatorTreeBase<typename GraphT::NodeType> &DT, + typename GraphT::NodeType *NewBB) { assert(std::distance(GraphT::child_begin(NewBB), GraphT::child_end(NewBB)) == 1 && "NewBB should have a single successor!"); - typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB); - - std::vector<typename GraphT::NodeType*> PredBlocks; - typedef GraphTraits<Inverse<N> > InvTraits; - for (typename InvTraits::ChildIteratorType PI = - InvTraits::child_begin(NewBB), - PE = InvTraits::child_end(NewBB); PI != PE; ++PI) + typename GraphT::NodeType *NewBBSucc = *GraphT::child_begin(NewBB); + + std::vector<typename GraphT::NodeType *> PredBlocks; + typedef GraphTraits<Inverse<N>> InvTraits; + for (typename InvTraits::ChildIteratorType + PI = InvTraits::child_begin(NewBB), + PE = InvTraits::child_end(NewBB); + PI != PE; ++PI) PredBlocks.push_back(*PI); assert(!PredBlocks.empty() && "No predblocks?"); bool NewBBDominatesNewBBSucc = true; - for (typename InvTraits::ChildIteratorType PI = - InvTraits::child_begin(NewBBSucc), - E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) { + for (typename InvTraits::ChildIteratorType + PI = InvTraits::child_begin(NewBBSucc), + E = InvTraits::child_end(NewBBSucc); + PI != E; ++PI) { typename InvTraits::NodeType *ND = *PI; if (ND != NewBB && !DT.dominates(NewBBSucc, ND) && DT.isReachableFromEntry(ND)) { @@ -292,8 +313,32 @@ protected: public: explicit DominatorTreeBase(bool isPostDom) - : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} - virtual ~DominatorTreeBase() { reset(); } + : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} + ~DominatorTreeBase() { reset(); } + + DominatorTreeBase(DominatorTreeBase &&Arg) + : DominatorBase<NodeT>( + std::move(static_cast<DominatorBase<NodeT> &>(Arg))), + DomTreeNodes(std::move(Arg.DomTreeNodes)), + RootNode(std::move(Arg.RootNode)), + DFSInfoValid(std::move(Arg.DFSInfoValid)), + SlowQueries(std::move(Arg.SlowQueries)), IDoms(std::move(Arg.IDoms)), + Vertex(std::move(Arg.Vertex)), Info(std::move(Arg.Info)) { + Arg.wipe(); + } + DominatorTreeBase &operator=(DominatorTreeBase &&RHS) { + DominatorBase<NodeT>::operator=( + std::move(static_cast<DominatorBase<NodeT> &>(RHS))); + DomTreeNodes = std::move(RHS.DomTreeNodes); + RootNode = std::move(RHS.RootNode); + DFSInfoValid = std::move(RHS.DFSInfoValid); + SlowQueries = std::move(RHS.SlowQueries); + IDoms = std::move(RHS.IDoms); + Vertex = std::move(RHS.Vertex); + Info = std::move(RHS.Info); + RHS.wipe(); + return *this; + } /// compare - Return false if the other dominator tree base matches this /// dominator tree base. Otherwise return true. @@ -304,15 +349,17 @@ public: return true; for (typename DomTreeNodeMapType::const_iterator - I = this->DomTreeNodes.begin(), - E = this->DomTreeNodes.end(); I != E; ++I) { + I = this->DomTreeNodes.begin(), + E = this->DomTreeNodes.end(); + I != E; ++I) { NodeT *BB = I->first; - typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB); + typename DomTreeNodeMapType::const_iterator OI = + OtherDomTreeNodes.find(BB); if (OI == OtherDomTreeNodes.end()) return true; - DomTreeNodeBase<NodeT>* MyNd = I->second; - DomTreeNodeBase<NodeT>* OtherNd = OI->second; + DomTreeNodeBase<NodeT> *MyNd = I->second; + DomTreeNodeBase<NodeT> *OtherNd = OI->second; if (MyNd->compare(OtherNd)) return true; @@ -321,18 +368,16 @@ public: return false; } - virtual void releaseMemory() { reset(); } + void releaseMemory() { reset(); } /// getNode - return the (Post)DominatorTree node for the specified basic /// block. This is the same as using operator[] on this class. /// - inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { + DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { return DomTreeNodes.lookup(BB); } - inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { - return getNode(BB); - } + DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); } /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, @@ -376,21 +421,19 @@ public: /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. - bool isReachableFromEntry(const NodeT* A) const { + bool isReachableFromEntry(const NodeT *A) const { assert(!this->isPostDominator() && "This is not implemented for post dominators"); return isReachableFromEntry(getNode(const_cast<NodeT *>(A))); } - inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { - return A; - } + bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { return A; } /// dominates - Returns true iff A dominates B. Note that this is not a /// constant time operation! /// - inline bool dominates(const DomTreeNodeBase<NodeT> *A, - const DomTreeNodeBase<NodeT> *B) const { + bool dominates(const DomTreeNodeBase<NodeT> *A, + const DomTreeNodeBase<NodeT> *B) const { // A node trivially dominates itself. if (B == A) return true; @@ -473,7 +516,7 @@ public: } // Collect NodeA dominators set. - SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms; + SmallPtrSet<DomTreeNodeBase<NodeT> *, 16> NodeADoms; NodeADoms.insert(NodeA); DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom(); while (IDomA) { @@ -513,7 +556,7 @@ public: assert(IDomNode && "Not immediate dominator specified for block!"); DFSInfoValid = false; return DomTreeNodes[BB] = - IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode)); + IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode)); } /// changeImmediateDominator - This method is used to update the dominator @@ -538,11 +581,11 @@ public: assert(Node && "Removing node that isn't in dominator tree."); assert(Node->getChildren().empty() && "Node is not a leaf node."); - // Remove node from immediate dominator's children list. + // Remove node from immediate dominator's children list. DomTreeNodeBase<NodeT> *IDom = Node->getIDom(); if (IDom) { - typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I = - std::find(IDom->Children.begin(), IDom->Children.end(), Node); + typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), Node); assert(I != IDom->Children.end() && "Not in immediate dominator children set!"); // I am no longer your child... @@ -563,11 +606,12 @@ public: /// splitBlock - BB is split and now it has one successor. Update dominator /// tree to reflect this change. - void splitBlock(NodeT* NewBB) { + void splitBlock(NodeT *NewBB) { if (this->IsPostDominators) - this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB); + this->Split<Inverse<NodeT *>, GraphTraits<Inverse<NodeT *>>>(*this, + NewBB); else - this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB); + this->Split<NodeT *, GraphTraits<NodeT *>>(*this, NewBB); } /// print - Convert to human readable form @@ -588,28 +632,27 @@ public: } protected: - template<class GraphT> - friend typename GraphT::NodeType* Eval( - DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* V, - unsigned LastLinked); + template <class GraphT> + friend typename GraphT::NodeType * + Eval(DominatorTreeBase<typename GraphT::NodeType> &DT, + typename GraphT::NodeType *V, unsigned LastLinked); - template<class GraphT> - friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* V, - unsigned N); + template <class GraphT> + friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType> &DT, + typename GraphT::NodeType *V, unsigned N); - template<class FuncT, class N> - friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT, - FuncT& F); + template <class FuncT, class N> + friend void + Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F); /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. void updateDFSNumbers() const { unsigned DFSNum = 0; - SmallVector<std::pair<const DomTreeNodeBase<NodeT>*, - typename DomTreeNodeBase<NodeT>::const_iterator>, 32> WorkStack; + SmallVector<std::pair<const DomTreeNodeBase<NodeT> *, + typename DomTreeNodeBase<NodeT>::const_iterator>, + 32> WorkStack; const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode(); @@ -626,7 +669,7 @@ protected: while (!WorkStack.empty()) { const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first; typename DomTreeNodeBase<NodeT>::const_iterator ChildIt = - WorkStack.back().second; + WorkStack.back().second; // If we visited all of the children of this node, "recurse" back up the // stack setting the DFOutNum. @@ -664,19 +707,14 @@ protected: return this->DomTreeNodes[BB] = IDomNode->addChild(C); } - inline NodeT *getIDom(NodeT *BB) const { - return IDoms.lookup(BB); - } + NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } - inline void addRoot(NodeT* BB) { - this->Roots.push_back(BB); - } + void addRoot(NodeT *BB) { this->Roots.push_back(BB); } public: /// recalculate - compute a dominator tree for the given function - template<class FT> - void recalculate(FT& F) { - typedef GraphTraits<FT*> TraitsTy; + template <class FT> void recalculate(FT &F) { + typedef GraphTraits<FT *> TraitsTy; reset(); this->Vertex.push_back(nullptr); @@ -687,27 +725,29 @@ public: this->IDoms[entry] = nullptr; this->DomTreeNodes[entry] = nullptr; - Calculate<FT, NodeT*>(*this, F); + Calculate<FT, NodeT *>(*this, F); } else { // Initialize the roots list for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F), - E = TraitsTy::nodes_end(&F); I != E; ++I) { + E = TraitsTy::nodes_end(&F); + I != E; ++I) { if (TraitsTy::child_begin(I) == TraitsTy::child_end(I)) addRoot(I); - // Prepopulate maps so that we don't get iterator invalidation issues later. + // Prepopulate maps so that we don't get iterator invalidation issues + // later. this->IDoms[I] = nullptr; this->DomTreeNodes[I] = nullptr; } - Calculate<FT, Inverse<NodeT*> >(*this, F); + Calculate<FT, Inverse<NodeT *>>(*this, F); } } }; // These two functions are declared out of line as a workaround for building // with old (< r147295) versions of clang because of pr11642. -template<class NodeT> +template <class NodeT> bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { if (A == B) return true; @@ -718,9 +758,9 @@ bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { return dominates(getNode(const_cast<NodeT *>(A)), getNode(const_cast<NodeT *>(B))); } -template<class NodeT> -bool -DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) const { +template <class NodeT> +bool DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, + const NodeT *B) const { if (A == B) return false; diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index bcba5e0aeb43..ad4f8a9f429a 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -22,8 +22,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H -#define LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H +#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H +#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/GenericDomTree.h" @@ -125,7 +125,7 @@ Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent]; // Process Ancestor first - if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) { + if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) { Work.push_back(VAncestor); continue; } diff --git a/include/llvm/Support/IncludeFile.h b/include/llvm/Support/IncludeFile.h deleted file mode 100644 index 2067e34f0d71..000000000000 --- a/include/llvm/Support/IncludeFile.h +++ /dev/null @@ -1,79 +0,0 @@ -//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR -// macros. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_INCLUDEFILE_H -#define LLVM_SUPPORT_INCLUDEFILE_H - -/// This macro is the public interface that IncludeFile.h exports. This gives -/// us the option to implement the "link the definition" capability in any -/// manner that we choose. All header files that depend on a specific .cpp -/// file being linked at run time should use this macro instead of the -/// IncludeFile class directly. -/// -/// For example, foo.h would use:<br/> -/// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/> -/// -/// And, foo.cp would use:<br/> -/// <tt>DEFINING_FILE_FOR(foo)</tt><br/> -#ifdef __GNUC__ -// If the `used' attribute is available, use it to create a variable -// with an initializer that will force the linking of the defining file. -#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ - namespace llvm { \ - extern const char name ## LinkVar; \ - __attribute__((used)) static const char *const name ## LinkObj = \ - &name ## LinkVar; \ - } -#else -// Otherwise use a constructor call. -#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ - namespace llvm { \ - extern const char name ## LinkVar; \ - static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ - } -#endif - -/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should -/// be used in a .cpp file to define the name referenced in a header file that -/// will cause linkage of the .cpp file. It should only be used at extern level. -#define DEFINING_FILE_FOR(name) \ - namespace llvm { const char name ## LinkVar = 0; } - -namespace llvm { - -/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED -/// macro to make sure that the implementation of a header file is included -/// into a tool that uses the header. This is solely -/// to overcome problems linking .a files and not getting the implementation -/// of compilation units we need. This is commonly an issue with the various -/// Passes but also occurs elsewhere in LLVM. We like to use .a files because -/// they link faster and provide the smallest executables. However, sometimes -/// those executables are too small, if the program doesn't reference something -/// that might be needed, especially by a loaded share object. This little class -/// helps to resolve that problem. The basic strategy is to use this class in -/// a header file and pass the address of a variable to the constructor. If the -/// variable is defined in the header file's corresponding .cpp file then all -/// tools/libraries that \#include the header file will require the .cpp as -/// well. -/// For example:<br/> -/// <tt>extern int LinkMyCodeStub;</tt><br/> -/// <tt>static IncludeFile LinkMyModule(&LinkMyCodeStub);</tt><br/> -/// @brief Class to ensure linking of corresponding object file. -struct IncludeFile { - explicit IncludeFile(const void *); -}; - -} - -#endif diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index ea76c9b58922..6a95432ca2d9 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -82,7 +82,7 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) { uint64_t Value = 0; unsigned Shift = 0; do { - Value += (*p & 0x7f) << Shift; + Value += uint64_t(*p & 0x7f) << Shift; Shift += 7; } while (*p++ >= 128); if (n) @@ -90,6 +90,26 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) { return Value; } +/// Utility function to decode a SLEB128 value. +inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) { + const uint8_t *orig_p = p; + int64_t Value = 0; + unsigned Shift = 0; + uint8_t Byte; + do { + Byte = *p++; + Value |= ((Byte & 0x7f) << Shift); + Shift += 7; + } while (Byte >= 128); + // Sign extend negative numbers. + if (Byte & 0x40) + Value |= (-1ULL) << Shift; + if (n) + *n = (unsigned)(p - orig_p); + return Value; +} + + /// Utility function to get the size of the ULEB128-encoded value. extern unsigned getULEB128Size(uint64_t Value); diff --git a/include/llvm/Support/LineIterator.h b/include/llvm/Support/LineIterator.h index 2a5826200143..9d4cd3bd4c6d 100644 --- a/include/llvm/Support/LineIterator.h +++ b/include/llvm/Support/LineIterator.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_LINEITERATOR_H__ -#define LLVM_SUPPORT_LINEITERATOR_H__ +#ifndef LLVM_SUPPORT_LINEITERATOR_H +#define LLVM_SUPPORT_LINEITERATOR_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" @@ -18,20 +18,22 @@ namespace llvm { class MemoryBuffer; -/// \brief A forward iterator which reads non-blank text lines from a buffer. +/// \brief A forward iterator which reads text lines from a buffer. /// /// This class provides a forward iterator interface for reading one line at /// a time from a buffer. When default constructed the iterator will be the /// "end" iterator. /// -/// The iterator also is aware of what line number it is currently processing -/// and can strip comment lines given the comment-starting character. +/// The iterator is aware of what line number it is currently processing. It +/// strips blank lines by default, and comment lines given a comment-starting +/// character. /// /// Note that this iterator requires the buffer to be nul terminated. class line_iterator : public std::iterator<std::forward_iterator_tag, StringRef> { const MemoryBuffer *Buffer; char CommentMarker; + bool SkipBlanks; unsigned LineNumber; StringRef CurrentLine; @@ -41,7 +43,8 @@ public: line_iterator() : Buffer(nullptr) {} /// \brief Construct a new iterator around some memory buffer. - explicit line_iterator(const MemoryBuffer &Buffer, char CommentMarker = '\0'); + explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true, + char CommentMarker = '\0'); /// \brief Return true if we've reached EOF or are an "end" iterator. bool is_at_eof() const { return !Buffer; } @@ -82,4 +85,4 @@ private: }; } -#endif // LLVM_SUPPORT_LINEITERATOR_H__ +#endif diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h index 4eb8507ea34f..f6e1e92c9fa8 100644 --- a/include/llvm/Support/MD5.h +++ b/include/llvm/Support/MD5.h @@ -25,8 +25,8 @@ * See md5.c for more information. */ -#ifndef LLVM_SYSTEM_MD5_H -#define LLVM_SYSTEM_MD5_H +#ifndef LLVM_SUPPORT_MD5_H +#define LLVM_SUPPORT_MD5_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" @@ -55,11 +55,11 @@ public: void update(StringRef Str); /// \brief Finishes off the hash and puts the result in result. - void final(MD5Result &result); + void final(MD5Result &Result); /// \brief Translates the bytes in \p Res to a hex string that is /// deposited into \p Str. The result will be of length 32. - static void stringifyResult(MD5Result &Res, SmallString<32> &Str); + static void stringifyResult(MD5Result &Result, SmallString<32> &Str); private: const uint8_t *body(ArrayRef<uint8_t> Data); diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 90df1f4f140f..775127505923 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -73,7 +73,10 @@ namespace llvm { MH_SETUID_SAFE = 0x00080000u, MH_NO_REEXPORTED_DYLIBS = 0x00100000u, MH_PIE = 0x00200000u, - MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u + MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u, + MH_HAS_TLV_DESCRIPTORS = 0x00800000u, + MH_NO_HEAP_EXECUTION = 0x01000000u, + MH_APP_EXTENSION_SAFE = 0x02000000u }; enum : uint32_t { @@ -127,8 +130,8 @@ namespace llvm { LC_DATA_IN_CODE = 0x00000029u, LC_SOURCE_VERSION = 0x0000002Au, LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu, - // 0x0000002Cu, - LC_LINKER_OPTIONS = 0x0000002Du, + LC_ENCRYPTION_INFO_64 = 0x0000002Cu, + LC_LINKER_OPTION = 0x0000002Du, LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu }; @@ -327,7 +330,8 @@ namespace llvm { enum ExportSymbolKind { EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u, - EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u + EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u, + EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02u }; @@ -838,12 +842,21 @@ namespace llvm { uint32_t cryptid; }; + struct encryption_info_command_64 { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; + uint32_t pad; + }; + struct version_min_command { uint32_t cmd; // LC_VERSION_MIN_MACOSX or // LC_VERSION_MIN_IPHONEOS uint32_t cmdsize; // sizeof(struct version_min_command) uint32_t version; // X.Y.Z is encoded in nibbles xxxx.yy.zz - uint32_t reserved; + uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz }; struct dyld_info_command { @@ -861,7 +874,7 @@ namespace llvm { uint32_t export_size; }; - struct linker_options_command { + struct linker_option_command { uint32_t cmd; uint32_t cmdsize; uint32_t count; @@ -1094,12 +1107,84 @@ namespace llvm { sys::swapByteOrder(d.dylib.compatibility_version); } + inline void swapStruct(sub_framework_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.umbrella); + } + + inline void swapStruct(sub_umbrella_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.sub_umbrella); + } + + inline void swapStruct(sub_library_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.sub_library); + } + + inline void swapStruct(sub_client_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.client); + } + + inline void swapStruct(routines_command &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.init_address); + sys::swapByteOrder(r.init_module); + sys::swapByteOrder(r.reserved1); + sys::swapByteOrder(r.reserved2); + sys::swapByteOrder(r.reserved3); + sys::swapByteOrder(r.reserved4); + sys::swapByteOrder(r.reserved5); + sys::swapByteOrder(r.reserved6); + } + + inline void swapStruct(routines_command_64 &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.init_address); + sys::swapByteOrder(r.init_module); + sys::swapByteOrder(r.reserved1); + sys::swapByteOrder(r.reserved2); + sys::swapByteOrder(r.reserved3); + sys::swapByteOrder(r.reserved4); + sys::swapByteOrder(r.reserved5); + sys::swapByteOrder(r.reserved6); + } + + inline void swapStruct(thread_command &t) { + sys::swapByteOrder(t.cmd); + sys::swapByteOrder(t.cmdsize); + } + inline void swapStruct(dylinker_command &d) { sys::swapByteOrder(d.cmd); sys::swapByteOrder(d.cmdsize); sys::swapByteOrder(d.name); } + inline void swapStruct(uuid_command &u) { + sys::swapByteOrder(u.cmd); + sys::swapByteOrder(u.cmdsize); + } + + inline void swapStruct(rpath_command &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.path); + } + + inline void swapStruct(source_version_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.version); + } + inline void swapStruct(entry_point_command &e) { sys::swapByteOrder(e.cmd); sys::swapByteOrder(e.cmdsize); @@ -1107,6 +1192,23 @@ namespace llvm { sys::swapByteOrder(e.stacksize); } + inline void swapStruct(encryption_info_command &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.cryptoff); + sys::swapByteOrder(e.cryptsize); + sys::swapByteOrder(e.cryptid); + } + + inline void swapStruct(encryption_info_command_64 &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.cryptoff); + sys::swapByteOrder(e.cryptsize); + sys::swapByteOrder(e.cryptid); + sys::swapByteOrder(e.pad); + } + inline void swapStruct(dysymtab_command &dst) { sys::swapByteOrder(dst.cmd); sys::swapByteOrder(dst.cmdsize); @@ -1159,7 +1261,7 @@ namespace llvm { sys::swapByteOrder(C.datasize); } - inline void swapStruct(linker_options_command &C) { + inline void swapStruct(linker_option_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); sys::swapByteOrder(C.count); @@ -1169,7 +1271,7 @@ namespace llvm { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); sys::swapByteOrder(C.version); - sys::swapByteOrder(C.reserved); + sys::swapByteOrder(C.sdk); } inline void swapStruct(data_in_code_entry &C) { @@ -1316,6 +1418,262 @@ namespace llvm { CPU_SUBTYPE_MC980000_ALL = CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601 }; + + struct x86_thread_state64_t { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint64_t cs; + uint64_t fs; + uint64_t gs; + }; + + enum x86_fp_control_precis { + x86_FP_PREC_24B = 0, + x86_FP_PREC_53B = 2, + x86_FP_PREC_64B = 3 + }; + + enum x86_fp_control_rc { + x86_FP_RND_NEAR = 0, + x86_FP_RND_DOWN = 1, + x86_FP_RND_UP = 2, + x86_FP_CHOP = 3 + }; + + struct fp_control_t { + unsigned short + invalid :1, + denorm :1, + zdiv :1, + ovrfl :1, + undfl :1, + precis :1, + :2, + pc :2, + rc :2, + :1, + :3; + }; + + struct fp_status_t { + unsigned short + invalid :1, + denorm :1, + zdiv :1, + ovrfl :1, + undfl :1, + precis :1, + stkflt :1, + errsumm :1, + c0 :1, + c1 :1, + c2 :1, + tos :3, + c3 :1, + busy :1; + }; + + struct mmst_reg_t { + char mmst_reg[10]; + char mmst_rsrv[6]; + }; + + struct xmm_reg_t { + char xmm_reg[16]; + }; + + struct x86_float_state64_t { + int32_t fpu_reserved[2]; + fp_control_t fpu_fcw; + fp_status_t fpu_fsw; + uint8_t fpu_ftw; + uint8_t fpu_rsrv1; + uint16_t fpu_fop; + uint32_t fpu_ip; + uint16_t fpu_cs; + uint16_t fpu_rsrv2; + uint32_t fpu_dp; + uint16_t fpu_ds; + uint16_t fpu_rsrv3; + uint32_t fpu_mxcsr; + uint32_t fpu_mxcsrmask; + mmst_reg_t fpu_stmm0; + mmst_reg_t fpu_stmm1; + mmst_reg_t fpu_stmm2; + mmst_reg_t fpu_stmm3; + mmst_reg_t fpu_stmm4; + mmst_reg_t fpu_stmm5; + mmst_reg_t fpu_stmm6; + mmst_reg_t fpu_stmm7; + xmm_reg_t fpu_xmm0; + xmm_reg_t fpu_xmm1; + xmm_reg_t fpu_xmm2; + xmm_reg_t fpu_xmm3; + xmm_reg_t fpu_xmm4; + xmm_reg_t fpu_xmm5; + xmm_reg_t fpu_xmm6; + xmm_reg_t fpu_xmm7; + xmm_reg_t fpu_xmm8; + xmm_reg_t fpu_xmm9; + xmm_reg_t fpu_xmm10; + xmm_reg_t fpu_xmm11; + xmm_reg_t fpu_xmm12; + xmm_reg_t fpu_xmm13; + xmm_reg_t fpu_xmm14; + xmm_reg_t fpu_xmm15; + char fpu_rsrv4[6*16]; + uint32_t fpu_reserved1; + }; + + struct x86_exception_state64_t { + uint16_t trapno; + uint16_t cpu; + uint32_t err; + uint64_t faultvaddr; + }; + + inline void swapStruct(x86_thread_state64_t &x) { + sys::swapByteOrder(x.rax); + sys::swapByteOrder(x.rbx); + sys::swapByteOrder(x.rcx); + sys::swapByteOrder(x.rdx); + sys::swapByteOrder(x.rdi); + sys::swapByteOrder(x.rsi); + sys::swapByteOrder(x.rbp); + sys::swapByteOrder(x.rsp); + sys::swapByteOrder(x.r8); + sys::swapByteOrder(x.r9); + sys::swapByteOrder(x.r10); + sys::swapByteOrder(x.r11); + sys::swapByteOrder(x.r12); + sys::swapByteOrder(x.r13); + sys::swapByteOrder(x.r14); + sys::swapByteOrder(x.r15); + sys::swapByteOrder(x.rip); + sys::swapByteOrder(x.rflags); + sys::swapByteOrder(x.cs); + sys::swapByteOrder(x.fs); + sys::swapByteOrder(x.gs); + } + + inline void swapStruct(x86_float_state64_t &x) { + sys::swapByteOrder(x.fpu_reserved[0]); + sys::swapByteOrder(x.fpu_reserved[1]); + // TODO swap: fp_control_t fpu_fcw; + // TODO swap: fp_status_t fpu_fsw; + sys::swapByteOrder(x.fpu_fop); + sys::swapByteOrder(x.fpu_ip); + sys::swapByteOrder(x.fpu_cs); + sys::swapByteOrder(x.fpu_rsrv2); + sys::swapByteOrder(x.fpu_dp); + sys::swapByteOrder(x.fpu_ds); + sys::swapByteOrder(x.fpu_rsrv3); + sys::swapByteOrder(x.fpu_mxcsr); + sys::swapByteOrder(x.fpu_mxcsrmask); + sys::swapByteOrder(x.fpu_reserved1); + } + + inline void swapStruct(x86_exception_state64_t &x) { + sys::swapByteOrder(x.trapno); + sys::swapByteOrder(x.cpu); + sys::swapByteOrder(x.err); + sys::swapByteOrder(x.faultvaddr); + } + + struct x86_state_hdr_t { + uint32_t flavor; + uint32_t count; + }; + + struct x86_thread_state_t { + x86_state_hdr_t tsh; + union { + x86_thread_state64_t ts64; + } uts; + }; + + struct x86_float_state_t { + x86_state_hdr_t fsh; + union { + x86_float_state64_t fs64; + } ufs; + }; + + struct x86_exception_state_t { + x86_state_hdr_t esh; + union { + x86_exception_state64_t es64; + } ues; + }; + + inline void swapStruct(x86_state_hdr_t &x) { + sys::swapByteOrder(x.flavor); + sys::swapByteOrder(x.count); + } + + enum X86ThreadFlavors { + x86_THREAD_STATE32 = 1, + x86_FLOAT_STATE32 = 2, + x86_EXCEPTION_STATE32 = 3, + x86_THREAD_STATE64 = 4, + x86_FLOAT_STATE64 = 5, + x86_EXCEPTION_STATE64 = 6, + x86_THREAD_STATE = 7, + x86_FLOAT_STATE = 8, + x86_EXCEPTION_STATE = 9, + x86_DEBUG_STATE32 = 10, + x86_DEBUG_STATE64 = 11, + x86_DEBUG_STATE = 12 + }; + + inline void swapStruct(x86_thread_state_t &x) { + swapStruct(x.tsh); + if (x.tsh.flavor == x86_THREAD_STATE64) + swapStruct(x.uts.ts64); + } + + inline void swapStruct(x86_float_state_t &x) { + swapStruct(x.fsh); + if (x.fsh.flavor == x86_FLOAT_STATE64) + swapStruct(x.ufs.fs64); + } + + inline void swapStruct(x86_exception_state_t &x) { + swapStruct(x.esh); + if (x.esh.flavor == x86_EXCEPTION_STATE64) + swapStruct(x.ues.es64); + } + + const uint32_t x86_THREAD_STATE64_COUNT = + sizeof(x86_thread_state64_t) / sizeof(uint32_t); + const uint32_t x86_FLOAT_STATE64_COUNT = + sizeof(x86_float_state64_t) / sizeof(uint32_t); + const uint32_t x86_EXCEPTION_STATE64_COUNT = + sizeof(x86_exception_state64_t) / sizeof(uint32_t); + + const uint32_t x86_THREAD_STATE_COUNT = + sizeof(x86_thread_state_t) / sizeof(uint32_t); + const uint32_t x86_FLOAT_STATE_COUNT = + sizeof(x86_float_state_t) / sizeof(uint32_t); + const uint32_t x86_EXCEPTION_STATE_COUNT = + sizeof(x86_exception_state_t) / sizeof(uint32_t); + } // end namespace MachO } // end namespace llvm diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index d8fbfeb8e20c..addd34e704bc 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_MANAGED_STATIC_H -#define LLVM_SUPPORT_MANAGED_STATIC_H +#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H +#define LLVM_SUPPORT_MANAGEDSTATIC_H #include "llvm/Support/Atomic.h" #include "llvm/Support/Threading.h" diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 0abba62a2c23..698363614ac5 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -22,7 +22,6 @@ #ifdef _MSC_VER #include <intrin.h> -#include <limits> #endif namespace llvm { @@ -73,7 +72,7 @@ countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { template <typename T> typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; +countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER template <> @@ -81,7 +80,7 @@ inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; -#if __has_builtin(__builtin_ctz) || __GNUC_PREREQ(4, 0) +#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_ctz(Val); #elif _MSC_VER unsigned long Index; @@ -96,7 +95,7 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; -#if __has_builtin(__builtin_ctzll) || __GNUC_PREREQ(4, 0) +#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_ctzll(Val); #elif _MSC_VER unsigned long Index; @@ -139,7 +138,7 @@ countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { template <typename T> typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; +countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER template <> @@ -147,7 +146,7 @@ inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; -#if __has_builtin(__builtin_clz) || __GNUC_PREREQ(4, 0) +#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_clz(Val); #elif _MSC_VER unsigned long Index; @@ -162,7 +161,7 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; -#if __has_builtin(__builtin_clzll) || __GNUC_PREREQ(4, 0) +#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_clzll(Val); #elif _MSC_VER unsigned long Index; @@ -194,7 +193,7 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { template <typename T> typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, T>::type -findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; +findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Get the index of the last set bit starting from the least /// significant bit. @@ -220,7 +219,7 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { template <typename T> typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, T>::type -findLastSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; +findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Macro compressed bit reversal table for 256 bits. /// @@ -550,16 +549,23 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) { return (A | B) & (1 + ~(A | B)); } -/// \brief Aligns \c Ptr to \c Alignment bytes, rounding up. +/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. /// /// Alignment should be a power of two. This method rounds up, so -/// AlignPtr(7, 4) == 8 and AlignPtr(8, 4) == 8. -inline char *alignPtr(char *Ptr, size_t Alignment) { +/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. +inline uintptr_t alignAddr(void *Addr, size_t Alignment) { assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && "Alignment is not a power of two!"); - return (char *)(((uintptr_t)Ptr + Alignment - 1) & - ~(uintptr_t)(Alignment - 1)); + assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); + + return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); +} + +/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment +/// bytes, rounding up. +inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { + return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; } /// NextPowerOf2 - Returns the next power of two (in 64-bits) @@ -589,9 +595,10 @@ inline uint64_t PowerOf2Floor(uint64_t A) { /// RoundUpToAlignment(5, 8) = 8 /// RoundUpToAlignment(17, 8) = 24 /// RoundUpToAlignment(~0LL, 8) = 0 +/// RoundUpToAlignment(321, 255) = 510 /// \endcode inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { - return ((Value + Align - 1) / Align) * Align; + return (Value + Align - 1) / Align * Align; } /// Returns the offset to the next integer (mod 2**64) that is greater than @@ -632,13 +639,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { return int64_t(X << (64 - B)) >> (64 - B); } -#if defined(_MSC_VER) - // Visual Studio defines the HUGE_VAL class of macros using purposeful - // constant arithmetic overflow, which it then warns on when encountered. - const float huge_valf = std::numeric_limits<float>::infinity(); -#else - const float huge_valf = HUGE_VALF; -#endif +extern const float huge_valf; } // End llvm namespace #endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 147be47e1c8f..e2f8d7e90fef 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -24,11 +24,13 @@ #include <system_error> namespace llvm { -/// MemoryBuffer - This interface provides simple read-only access to a block -/// of memory, and provides simple methods for reading files and standard input -/// into a memory buffer. In addition to basic access to the characters in the -/// file, this interface guarantees you can read one character past the end of -/// the file, and that this character will read as '\0'. +class MemoryBufferRef; + +/// This interface provides simple read-only access to a block of memory, and +/// provides simple methods for reading files and standard input into a memory +/// buffer. In addition to basic access to the characters in the file, this +/// interface guarantees you can read one character past the end of the file, +/// and that this character will read as '\0'. /// /// The '\0' guarantee is needed to support an optimization -- it's intended to /// be more efficient for clients which are reading all the data to stop @@ -55,8 +57,8 @@ public: return StringRef(BufferStart, getBufferSize()); } - /// getBufferIdentifier - Return an identifier for this buffer, typically the - /// filename it was read from. + /// Return an identifier for this buffer, typically the filename it was read + /// from. virtual const char *getBufferIdentifier() const { return "Unknown buffer"; } @@ -70,19 +72,15 @@ public: /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. static ErrorOr<std::unique_ptr<MemoryBuffer>> - getFile(Twine Filename, int64_t FileSize = -1, + getFile(const Twine &Filename, int64_t FileSize = -1, bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// Given an already-open file descriptor, map some slice of it into a /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. /// Since this is in the middle of a file, the buffer is not null terminated. - /// - /// \param IsVolatileSize Set to true to indicate that the file size may be - /// changing, e.g. when libclang tries to parse while the user is - /// editing/updating the file. static ErrorOr<std::unique_ptr<MemoryBuffer>> - getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, - int64_t Offset, bool IsVolatileSize = false); + getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, + int64_t Offset); /// Given an already-open file descriptor, read the file and return a /// MemoryBuffer. @@ -91,33 +89,34 @@ public: /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. static ErrorOr<std::unique_ptr<MemoryBuffer>> - getOpenFile(int FD, const char *Filename, uint64_t FileSize, + getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator = true, bool IsVolatileSize = false); - /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note - /// that InputData must be null terminated if RequiresNullTerminator is true. - static MemoryBuffer *getMemBuffer(StringRef InputData, - StringRef BufferName = "", - bool RequiresNullTerminator = true); - - /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, - /// copying the contents and taking ownership of it. InputData does not - /// have to be null terminated. - static MemoryBuffer *getMemBufferCopy(StringRef InputData, - StringRef BufferName = ""); - - /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that - /// is completely initialized to zeros. Note that the caller should - /// initialize the memory allocated by this method. The memory is owned by - /// the MemoryBuffer object. - static MemoryBuffer *getNewMemBuffer(size_t Size, StringRef BufferName = ""); - - /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size - /// that is not initialized. Note that the caller should initialize the - /// memory allocated by this method. The memory is owned by the MemoryBuffer - /// object. - static MemoryBuffer *getNewUninitMemBuffer(size_t Size, - StringRef BufferName = ""); + /// Open the specified memory range as a MemoryBuffer. Note that InputData + /// must be null terminated if RequiresNullTerminator is true. + static std::unique_ptr<MemoryBuffer> + getMemBuffer(StringRef InputData, StringRef BufferName = "", + bool RequiresNullTerminator = true); + + static std::unique_ptr<MemoryBuffer> + getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); + + /// Open the specified memory range as a MemoryBuffer, copying the contents + /// and taking ownership of it. InputData does not have to be null terminated. + static std::unique_ptr<MemoryBuffer> + getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); + + /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note + /// that the caller need not initialize the memory allocated by this method. + /// The memory is owned by the MemoryBuffer object. + static std::unique_ptr<MemoryBuffer> + getNewMemBuffer(size_t Size, StringRef BufferName = ""); + + /// Allocate a new MemoryBuffer of the specified size that is not initialized. + /// Note that the caller should initialize the memory allocated by this + /// method. The memory is owned by the MemoryBuffer object. + static std::unique_ptr<MemoryBuffer> + getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); /// Read all of stdin into a file buffer, and return it. static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); @@ -125,7 +124,11 @@ public: /// Open the specified file as a MemoryBuffer, or open stdin if the Filename /// is "-". static ErrorOr<std::unique_ptr<MemoryBuffer>> - getFileOrSTDIN(StringRef Filename, int64_t FileSize = -1); + getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1); + + /// Map a subrange of the the specified file as a MemoryBuffer. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); //===--------------------------------------------------------------------===// // Provided for performance analysis. @@ -139,7 +142,27 @@ public: /// Return information on the memory mechanism used to support the /// MemoryBuffer. - virtual BufferKind getBufferKind() const = 0; + virtual BufferKind getBufferKind() const = 0; + + MemoryBufferRef getMemBufferRef() const; +}; + +class MemoryBufferRef { + StringRef Buffer; + StringRef Identifier; + +public: + MemoryBufferRef() {} + MemoryBufferRef(StringRef Buffer, StringRef Identifier) + : Buffer(Buffer), Identifier(Identifier) {} + + StringRef getBuffer() const { return Buffer; } + + StringRef getBufferIdentifier() const { return Identifier; } + + const char *getBufferStart() const { return Buffer.begin(); } + const char *getBufferEnd() const { return Buffer.end(); } + size_t getBufferSize() const { return Buffer.size(); } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h index 17aa9d2f675a..e0c8749da346 100644 --- a/include/llvm/Support/MemoryObject.h +++ b/include/llvm/Support/MemoryObject.h @@ -14,49 +14,53 @@ namespace llvm { -/// MemoryObject - Abstract base class for contiguous addressable memory. -/// Necessary for cases in which the memory is in another process, in a -/// file, or on a remote machine. -/// All size and offset parameters are uint64_ts, to allow 32-bit processes -/// access to 64-bit address spaces. +/// Interface to data which might be streamed. Streamability has 2 important +/// implications/restrictions. First, the data might not yet exist in memory +/// when the request is made. This just means that readByte/readBytes might have +/// to block or do some work to get it. More significantly, the exact size of +/// the object might not be known until it has all been fetched. This means that +/// to return the right result, getExtent must also wait for all the data to +/// arrive; therefore it should not be called on objects which are actually +/// streamed (this would defeat the purpose of streaming). Instead, +/// isValidAddress can be used to test addresses without knowing the exact size +/// of the stream. Finally, getPointer can be used instead of readBytes to avoid +/// extra copying. class MemoryObject { public: - /// Destructor - Override as necessary. virtual ~MemoryObject(); - /// getBase - Returns the lowest valid address in the region. - /// - /// @result - The lowest valid address. - virtual uint64_t getBase() const = 0; - - /// getExtent - Returns the size of the region in bytes. (The region is - /// contiguous, so the highest valid address of the region - /// is getBase() + getExtent() - 1). + /// Returns the size of the region in bytes. (The region is contiguous, so + /// the highest valid address of the region is getExtent() - 1). /// /// @result - The size of the region. virtual uint64_t getExtent() const = 0; - /// readByte - Tries to read a single byte from the region. - /// - /// @param address - The address of the byte, in the same space as getBase(). - /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. - /// @result - 0 if successful; -1 if not. Failure may be due to a - /// bounds violation or an implementation-specific error. - virtual int readByte(uint64_t address, uint8_t *ptr) const = 0; - - /// readBytes - Tries to read a contiguous range of bytes from the - /// region, up to the end of the region. - /// You should override this function if there is a quicker - /// way than going back and forth with individual bytes. + /// Tries to read a contiguous range of bytes from the region, up to the end + /// of the region. /// - /// @param address - The address of the first byte, in the same space as - /// getBase(). - /// @param size - The number of bytes to copy. - /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL + /// @param Buf - A pointer to a buffer to be filled in. Must be non-NULL /// and large enough to hold size bytes. - /// @result - 0 if successful; -1 if not. Failure may be due to a - /// bounds violation or an implementation-specific error. - virtual int readBytes(uint64_t address, uint64_t size, uint8_t *buf) const; + /// @param Size - The number of bytes to copy. + /// @param Address - The address of the first byte, in the same space as + /// getBase(). + /// @result - The number of bytes read. + virtual uint64_t readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const = 0; + + /// Ensures that the requested data is in memory, and returns a pointer to it. + /// More efficient than using readBytes if the data is already in memory. May + /// block until (address - base + size) bytes have been read + /// @param address - address of the byte, in the same space as getBase() + /// @param size - amount of data that must be available on return + /// @result - valid pointer to the requested data + virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0; + + /// Returns true if the address is within the object (i.e. between base and + /// base + extent - 1 inclusive). May block until (address - base) bytes have + /// been read + /// @param address - address of the byte, in the same space as getBase() + /// @result - true if the address may be read with readByte() + virtual bool isValidAddress(uint64_t address) const = 0; }; } diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 496a4381f3fc..97dd50115322 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -86,16 +86,17 @@ namespace llvm /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> - class SmartMutex : public MutexImpl { + class SmartMutex { + MutexImpl impl; unsigned acquired; bool recursive; public: explicit SmartMutex(bool rec = true) : - MutexImpl(rec), acquired(0), recursive(rec) { } + impl(rec), acquired(0), recursive(rec) { } - bool acquire() { + bool lock() { if (!mt_only || llvm_is_multithreaded()) { - return MutexImpl::acquire(); + return impl.acquire(); } else { // Single-threaded debugging code. This would be racy in // multithreaded mode, but provides not sanity checks in single @@ -106,9 +107,9 @@ namespace llvm } } - bool release() { + bool unlock() { if (!mt_only || llvm_is_multithreaded()) { - return MutexImpl::release(); + return impl.release(); } else { // Single-threaded debugging code. This would be racy in // multithreaded mode, but provides not sanity checks in single @@ -120,9 +121,9 @@ namespace llvm } } - bool tryacquire() { + bool try_lock() { if (!mt_only || llvm_is_multithreaded()) - return MutexImpl::tryacquire(); + return impl.tryacquire(); else return true; } @@ -140,11 +141,11 @@ namespace llvm public: SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { - mtx.acquire(); + mtx.lock(); } ~SmartScopedLock() { - mtx.release(); + mtx.unlock(); } }; diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index 6bb162277e2b..b9f941dab323 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -29,8 +29,8 @@ namespace llvm { MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION; void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION; public: - MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } - ~MutexGuard() { M.release(); } + MutexGuard(sys::Mutex &m) : M(m) { M.lock(); } + ~MutexGuard() { M.unlock(); } /// holds - Returns true if this locker instance holds the specified lock. /// This is mostly used in assertions to validate that the correct mutex /// is held. diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index f6d43a440788..52f133ccff68 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -11,11 +11,11 @@ /// \brief Defines facilities for reading and writing on-disk hash tables. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ON_DISK_HASH_TABLE_H -#define LLVM_SUPPORT_ON_DISK_HASH_TABLE_H +#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H +#define LLVM_SUPPORT_ONDISKHASHTABLE_H -#include "llvm/Support/Allocator.h" #include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/Host.h" @@ -568,4 +568,4 @@ public: } // end namespace llvm -#endif // LLVM_SUPPORT_ON_DISK_HASH_TABLE_H +#endif diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h new file mode 100644 index 000000000000..4fd1bff358fd --- /dev/null +++ b/include/llvm/Support/Options.h @@ -0,0 +1,120 @@ +//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares helper objects for defining debug options that can be +/// configured via the command line. The new API currently builds on the cl::opt +/// API, but does not require the use of static globals. +/// +/// With this API options are registered during initialization. For passes, this +/// happens during pass initialization. Passes with options will call a static +/// registerOptions method during initialization that registers options with the +/// OptionRegistry. An example implementation of registerOptions is: +/// +/// static void registerOptions() { +/// OptionRegistry::registerOption<bool, Scalarizer, +/// &Scalarizer::ScalarizeLoadStore>( +/// "scalarize-load-store", +/// "Allow the scalarizer pass to scalarize loads and store", false); +/// } +/// +/// When reading data for options the interface is via the LLVMContext. Option +/// data for passes should be read from the context during doInitialization. An +/// example of reading the above option would be: +/// +/// ScalarizeLoadStore = +/// M.getContext().getOption<bool, +/// Scalarizer, +/// &Scalarizer::ScalarizeLoadStore>(); +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OPTIONS_H +#define LLVM_SUPPORT_OPTIONS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +namespace detail { + +// Options are keyed of the unique address of a static character synthesized +// based on template arguments. +template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey { +public: + static char ID; +}; + +template <typename ValT, typename Base, ValT(Base::*Mem)> +char OptionKey<ValT, Base, Mem>::ID = 0; + +} // namespace detail + +/// \brief Singleton class used to register debug options. +/// +/// The OptionRegistry is responsible for managing lifetimes of the options and +/// provides interfaces for option registration and reading values from options. +/// This object is a singleton, only one instance should ever exist so that all +/// options are registered in teh same place. +class OptionRegistry { +private: + DenseMap<void *, cl::Option *> Options; + + /// \brief Adds a cl::Option to the registry. + /// + /// \param Key unique key for option + /// \param O option to map to \p Key + /// + /// Allocated cl::Options are owened by the OptionRegistry and are deallocated + /// on destruction or removal + void addOption(void *Key, cl::Option *O); + +public: + ~OptionRegistry(); + OptionRegistry() {} + + /// \brief Returns a reference to the singleton instance. + static OptionRegistry &instance(); + + /// \brief Registers an option with the OptionRegistry singleton. + /// + /// \tparam ValT type of the option's data + /// \tparam Base class used to key the option + /// \tparam Mem member of \p Base used for keying the option + /// + /// Options are keyed off the template parameters to generate unique static + /// characters. The template parameters are (1) the type of the data the + /// option stores (\p ValT), the class that will read the option (\p Base), + /// and the memeber that the class will store the data into (\p Mem). + template <typename ValT, typename Base, ValT(Base::*Mem)> + static void registerOption(const char *ArgStr, const char *Desc, + const ValT &InitValue) { + cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc), + cl::Hidden, cl::init(InitValue)); + instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option); + } + + /// \brief Returns the value of the option. + /// + /// \tparam ValT type of the option's data + /// \tparam Base class used to key the option + /// \tparam Mem member of \p Base used for keying the option + /// + /// Reads option values based on the key generated by the template parameters. + /// Keying for get() is the same as keying for registerOption. + template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const { + auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID); + assert(It != Options.end() && "Option not in OptionRegistry"); + return *(cl::opt<ValT> *)It->second; + } +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index cf821f0ef4a4..8fae853e2cf4 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -30,13 +30,13 @@ namespace path { /// @brief Path iterator. /// -/// This is a bidirectional iterator that iterates over the individual -/// components in \a path. The forward traversal order is as follows: +/// This is an input iterator that iterates over the individual components in +/// \a path. The traversal order is as follows: /// * The root-name element, if present. /// * The root-directory element, if present. /// * Each successive filename element, if present. /// * Dot, if one or more trailing non-root slash characters are present. -/// The backwards traversal order is the reverse of forward traversal. +/// Traversing backwards is possible with \a reverse_iterator /// /// Iteration examples. Each component is separated by ',': /// @code @@ -47,7 +47,8 @@ namespace path { /// ../ => ..,. /// C:\foo\bar => C:,/,foo,bar /// @endcode -class const_iterator { +class const_iterator + : public std::iterator<std::input_iterator_tag, const StringRef> { StringRef Path; ///< The entire path. StringRef Component; ///< The current component. Not necessarily in Path. size_t Position; ///< The iterators current position within Path. @@ -57,26 +58,39 @@ class const_iterator { friend const_iterator end(StringRef path); public: - typedef const StringRef value_type; - typedef ptrdiff_t difference_type; - typedef value_type &reference; - typedef value_type *pointer; - typedef std::bidirectional_iterator_tag iterator_category; - reference operator*() const { return Component; } pointer operator->() const { return &Component; } const_iterator &operator++(); // preincrement const_iterator &operator++(int); // postincrement - const_iterator &operator--(); // predecrement - const_iterator &operator--(int); // postdecrement bool operator==(const const_iterator &RHS) const; - bool operator!=(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); } /// @brief Difference in bytes between this and RHS. ptrdiff_t operator-(const const_iterator &RHS) const; }; -typedef std::reverse_iterator<const_iterator> reverse_iterator; +/// @brief Reverse path iterator. +/// +/// This is an input iterator that iterates over the individual components in +/// \a path in reverse order. The traversal order is exactly reversed from that +/// of \a const_iterator +class reverse_iterator + : public std::iterator<std::input_iterator_tag, const StringRef> { + StringRef Path; ///< The entire path. + StringRef Component; ///< The current component. Not necessarily in Path. + size_t Position; ///< The iterators current position within Path. + + friend reverse_iterator rbegin(StringRef path); + friend reverse_iterator rend(StringRef path); + +public: + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + reverse_iterator &operator++(); // preincrement + reverse_iterator &operator++(int); // postincrement + bool operator==(const reverse_iterator &RHS) const; + bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } +}; /// @brief Get begin iterator over \a path. /// @param path Input path. @@ -91,16 +105,12 @@ const_iterator end(StringRef path); /// @brief Get reverse begin iterator over \a path. /// @param path Input path. /// @returns Iterator initialized with the first reverse component of \a path. -inline reverse_iterator rbegin(StringRef path) { - return reverse_iterator(end(path)); -} +reverse_iterator rbegin(StringRef path); /// @brief Get reverse end iterator over \a path. /// @param path Input path. /// @returns Iterator initialized to the reverse end of \a path. -inline reverse_iterator rend(StringRef path) { - return reverse_iterator(begin(path)); -} +reverse_iterator rend(StringRef path); /// @} /// @name Lexical Modifiers @@ -194,7 +204,7 @@ void native(SmallVectorImpl<char> &path); /// /// @param path Input path. /// @result The root name of \a path if it has one, otherwise "". -const StringRef root_name(StringRef path); +StringRef root_name(StringRef path); /// @brief Get root directory. /// @@ -207,7 +217,7 @@ const StringRef root_name(StringRef path); /// @param path Input path. /// @result The root directory of \a path if it has one, otherwise /// "". -const StringRef root_directory(StringRef path); +StringRef root_directory(StringRef path); /// @brief Get root path. /// @@ -215,7 +225,7 @@ const StringRef root_directory(StringRef path); /// /// @param path Input path. /// @result The root path of \a path if it has one, otherwise "". -const StringRef root_path(StringRef path); +StringRef root_path(StringRef path); /// @brief Get relative path. /// @@ -227,7 +237,7 @@ const StringRef root_path(StringRef path); /// /// @param path Input path. /// @result The path starting after root_path if one exists, otherwise "". -const StringRef relative_path(StringRef path); +StringRef relative_path(StringRef path); /// @brief Get parent path. /// @@ -239,7 +249,7 @@ const StringRef relative_path(StringRef path); /// /// @param path Input path. /// @result The parent path of \a path if one exists, otherwise "". -const StringRef parent_path(StringRef path); +StringRef parent_path(StringRef path); /// @brief Get filename. /// @@ -253,7 +263,7 @@ const StringRef parent_path(StringRef path); /// @param path Input path. /// @result The filename part of \a path. This is defined as the last component /// of \a path. -const StringRef filename(StringRef path); +StringRef filename(StringRef path); /// @brief Get stem. /// @@ -271,7 +281,7 @@ const StringRef filename(StringRef path); /// /// @param path Input path. /// @result The stem of \a path. -const StringRef stem(StringRef path); +StringRef stem(StringRef path); /// @brief Get extension. /// @@ -287,7 +297,7 @@ const StringRef stem(StringRef path); /// /// @param path Input path. /// @result The extension of \a path. -const StringRef extension(StringRef path); +StringRef extension(StringRef path); /// @brief Check whether the given char is a path separator on the host OS. /// @@ -298,7 +308,7 @@ bool is_separator(char value); /// @brief Return the preferred separator for this platform. /// /// @result StringRef of the preferred separator, null-terminated. -const StringRef get_separator(); +StringRef get_separator(); /// @brief Get the typical temporary directory for the system, e.g., /// "/var/tmp" or "C:/TEMP" diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 30973de3aac4..cfdd06c62f33 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -38,111 +38,13 @@ class StringRef; namespace sys { -class self_process; - -/// \brief Generic base class which exposes information about an operating -/// system process. -/// -/// This base class is the core interface behind any OS process. It exposes -/// methods to query for generic information about a particular process. -/// -/// Subclasses implement this interface based on the mechanisms available, and -/// can optionally expose more interfaces unique to certain process kinds. -class process { -protected: - /// \brief Only specific subclasses of process objects can be destroyed. - virtual ~process(); - -public: - /// \brief Operating system specific type to identify a process. - /// - /// Note that the windows one is defined to 'unsigned long' as this is the - /// documented type for DWORD on windows, and we don't want to pull in the - /// Windows headers here. -#if defined(LLVM_ON_UNIX) - typedef pid_t id_type; -#elif defined(LLVM_ON_WIN32) - typedef unsigned long id_type; // Must match the type of DWORD. -#else -#error Unsupported operating system. -#endif - - /// \brief Get the operating system specific identifier for this process. - virtual id_type get_id() = 0; - - /// \brief Get the user time consumed by this process. - /// - /// Note that this is often an approximation and may be zero on platforms - /// where we don't have good support for the functionality. - virtual TimeValue get_user_time() const = 0; - - /// \brief Get the system time consumed by this process. - /// - /// Note that this is often an approximation and may be zero on platforms - /// where we don't have good support for the functionality. - virtual TimeValue get_system_time() const = 0; - - /// \brief Get the wall time consumed by this process. - /// - /// Note that this is often an approximation and may be zero on platforms - /// where we don't have good support for the functionality. - virtual TimeValue get_wall_time() const = 0; - - /// \name Static factory routines for processes. - /// @{ - - /// \brief Get the process object for the current process. - static self_process *get_self(); - - /// @} - -}; - -/// \brief The specific class representing the current process. -/// -/// The current process can both specialize the implementation of the routines -/// and can expose certain information not available for other OS processes. -class self_process : public process { - friend class process; - - /// \brief Private destructor, as users shouldn't create objects of this - /// type. - virtual ~self_process(); - -public: - id_type get_id() override; - TimeValue get_user_time() const override; - TimeValue get_system_time() const override; - TimeValue get_wall_time() const override; - - /// \name Process configuration (sysconf on POSIX) - /// @{ - - /// \brief Get the virtual memory page size. - /// - /// Query the operating system for this process's page size. - size_t page_size() const { return PageSize; }; - - /// @} - -private: - /// \name Cached process state. - /// @{ - - /// \brief Cached page size, this cannot vary during the life of the process. - size_t PageSize; - - /// @} - - /// \brief Constructor, used by \c process::get_self() only. - self_process(); -}; - /// \brief A collection of legacy interfaces for querying information about the /// current executing process. class Process { public: + static unsigned getPageSize(); + /// \brief Return process memory usage. /// This static function will return the total amount of memory allocated /// by the process. This only counts the memory allocated via the malloc, @@ -186,6 +88,21 @@ public: ArrayRef<const char *> ArgsFromMain, SpecificBumpPtrAllocator<char> &ArgAllocator); + // This functions ensures that the standard file descriptors (input, output, + // and error) are properly mapped to a file descriptor before we use any of + // them. This should only be called by standalone programs, library + // components should not call this. + static std::error_code FixupStandardFileDescriptors(); + + // This function safely closes a file descriptor. It is not safe to retry + // close(2) when it returns with errno equivalent to EINTR; this is because + // *nixen cannot agree if the file descriptor is, in fact, closed when this + // occurs. + // + // N.B. Some operating systems, due to thread cancellation, cannot properly + // guarantee that it will or will not be closed one way or the other! + static std::error_code SafelyCloseFileDescriptor(int FD); + /// This function determines if the standard input is connected directly /// to a user's input (keyboard probably), rather than coming from a file /// or pipe. diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 51279a9b864a..40dc60fa30d6 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -15,6 +15,7 @@ #define LLVM_SUPPORT_PROGRAM_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/Path.h" #include <system_error> @@ -51,17 +52,22 @@ struct ProcessInfo { ProcessInfo(); }; - /// This function attempts to locate a program in the operating - /// system's file system using some pre-determined set of locations to search - /// (e.g. the PATH on Unix). Paths with slashes are returned unmodified. + /// \brief Find the first executable file \p Name in \p Paths. /// - /// It does not perform hashing as a shell would but instead stats each PATH + /// This does not perform hashing as a shell would but instead stats each PATH /// entry individually so should generally be avoided. Core LLVM library /// functions and options should instead require fully specified paths. /// - /// @returns A string containing the path of the program or an empty string if - /// the program could not be found. - std::string FindProgramByName(const std::string& name); + /// \param Name name of the executable to find. If it contains any system + /// slashes, it will be returned as is. + /// \param Paths optional list of paths to search for \p Name. If empty it + /// will use the system PATH environment instead. + /// + /// \returns The fully qualified path to the first \p Name in \p Paths if it + /// exists. \p Name if \p Name has slashes in it. Otherwise an error. + ErrorOr<std::string> + findProgramByName(StringRef Name, + ArrayRef<StringRef> Paths = ArrayRef<StringRef>()); // These functions change the specified standard stream (stdin or stdout) to // binary mode. They return errc::success if the specified stream @@ -82,7 +88,7 @@ struct ProcessInfo { /// -2 indicates a crash during execution or timeout int ExecuteAndWait( StringRef Program, ///< Path of the program to be executed. It is - /// presumed this is the result of the FindProgramByName method. + /// presumed this is the result of the findProgramByName method. const char **args, ///< A vector of strings that are passed to the ///< program. The first element should be the name of the program. ///< The list *must* be terminated by a null char* entry. @@ -126,6 +132,40 @@ struct ProcessInfo { /// argument length limits. bool argumentsFitWithinSystemLimits(ArrayRef<const char*> Args); + /// File encoding options when writing contents that a non-UTF8 tool will + /// read (on Windows systems). For UNIX, we always use UTF-8. + enum WindowsEncodingMethod { + /// UTF-8 is the LLVM native encoding, being the same as "do not perform + /// encoding conversion". + WEM_UTF8, + WEM_CurrentCodePage, + WEM_UTF16 + }; + + /// Saves the UTF8-encoded \p contents string into the file \p FileName + /// using a specific encoding. + /// + /// This write file function adds the possibility to choose which encoding + /// to use when writing a text file. On Windows, this is important when + /// writing files with internationalization support with an encoding that is + /// different from the one used in LLVM (UTF-8). We use this when writing + /// response files, since GCC tools on MinGW only understand legacy code + /// pages, and VisualStudio tools only understand UTF-16. + /// For UNIX, using different encodings is silently ignored, since all tools + /// work well with UTF-8. + /// This function assumes that you only use UTF-8 *text* data and will convert + /// it to your desired encoding before writing to the file. + /// + /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in + /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is + /// our best shot to make gcc/ld understand international characters. This + /// should be changed as soon as binutils fix this to support UTF16 on mingw. + /// + /// \returns non-zero error_code if failed + std::error_code + writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding = WEM_UTF8); + /// This function waits for the process specified by \p PI to finish. /// \returns A \see ProcessInfo struct with Pid set to: /// \li The process id of the child process if the child process has changed diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h index 935b3075df58..b80b8557576b 100644 --- a/include/llvm/Support/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_RWMUTEX_H -#define LLVM_SYSTEM_RWMUTEX_H +#ifndef LLVM_SUPPORT_RWMUTEX_H +#define LLVM_SUPPORT_RWMUTEX_H #include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" @@ -85,14 +85,15 @@ namespace llvm /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> - class SmartRWMutex : public RWMutexImpl { + class SmartRWMutex { + RWMutexImpl impl; unsigned readers, writers; public: - explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } + explicit SmartRWMutex() : impl(), readers(0), writers(0) { } - bool reader_acquire() { + bool lock_shared() { if (!mt_only || llvm_is_multithreaded()) - return RWMutexImpl::reader_acquire(); + return impl.reader_acquire(); // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. @@ -100,9 +101,9 @@ namespace llvm return true; } - bool reader_release() { + bool unlock_shared() { if (!mt_only || llvm_is_multithreaded()) - return RWMutexImpl::reader_release(); + return impl.reader_release(); // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. @@ -111,9 +112,9 @@ namespace llvm return true; } - bool writer_acquire() { + bool lock() { if (!mt_only || llvm_is_multithreaded()) - return RWMutexImpl::writer_acquire(); + return impl.writer_acquire(); // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. @@ -122,9 +123,9 @@ namespace llvm return true; } - bool writer_release() { + bool unlock() { if (!mt_only || llvm_is_multithreaded()) - return RWMutexImpl::writer_release(); + return impl.writer_release(); // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. @@ -145,11 +146,11 @@ namespace llvm SmartRWMutex<mt_only>& mutex; explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { - mutex.reader_acquire(); + mutex.lock_shared(); } ~SmartScopedReader() { - mutex.reader_release(); + mutex.unlock_shared(); } }; typedef SmartScopedReader<false> ScopedReader; @@ -160,11 +161,11 @@ namespace llvm SmartRWMutex<mt_only>& mutex; explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { - mutex.writer_acquire(); + mutex.lock(); } ~SmartScopedWriter() { - mutex.writer_release(); + mutex.unlock(); } }; typedef SmartScopedWriter<false> ScopedWriter; diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h index cadc713659d2..7ada34f075e4 100644 --- a/include/llvm/Support/RandomNumberGenerator.h +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This file defines an abstraction for random number generation (RNG). -// Note that the current implementation is not cryptographically secure -// as it uses the C++11 <random> facilities. +// This file defines an abstraction for deterministic random number +// generation (RNG). Note that the current implementation is not +// cryptographically secure as it uses the C++11 <random> facilities. // //===----------------------------------------------------------------------===// @@ -24,26 +24,27 @@ namespace llvm { /// A random number generator. -/// Instances of this class should not be shared across threads. +/// +/// Instances of this class should not be shared across threads. The +/// seed should be set by passing the -rng-seed=<uint64> option. Use +/// Module::createRNG to create a new RNG instance for use with that +/// module. class RandomNumberGenerator { public: - /// Seeds and salts the underlying RNG engine. The salt of type StringRef - /// is passed into the constructor. The seed can be set on the command - /// line via -rng-seed=<uint64>. - /// The reason for the salt is to ensure different random streams even if - /// the same seed is used for multiple invocations of the compiler. - /// A good salt value should add additional entropy and be constant across - /// different machines (i.e., no paths) to allow for reproducible builds. - /// An instance of this class can be retrieved from the current Module. - /// \see Module::getRNG - RandomNumberGenerator(StringRef Salt); - /// Returns a random number in the range [0, Max). - uint64_t next(uint64_t Max); + uint_fast64_t operator()(); private: + /// Seeds and salts the underlying RNG engine. + /// + /// This constructor should not be used directly. Instead use + /// Module::createRNG to create a new RNG salted with the Module ID. + RandomNumberGenerator(StringRef Salt); + // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine + // This RNG is deterministically portable across C++11 + // implementations. std::mt19937_64 Generator; // Noncopyable. @@ -51,6 +52,8 @@ private: LLVM_DELETED_FUNCTION; RandomNumberGenerator & operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; + + friend class Module; }; } diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index b0c2e899855d..e21269b2f1d5 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -16,7 +16,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" - #include <memory> namespace llvm { diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index 2bd7e741dd28..a1c4c80c356f 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -23,7 +23,6 @@ #define LLVM_SUPPORT_SCALEDNUMBER_H #include "llvm/Support/MathExtras.h" - #include <algorithm> #include <cstdint> #include <limits> diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 4717553bd0de..f9e114b67cb4 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -19,11 +19,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" #include <string> namespace llvm { - class MemoryBuffer; class SourceMgr; class SMDiagnostic; class SMFixIt; @@ -47,10 +47,15 @@ public: private: struct SrcBuffer { /// The memory buffer for the file. - MemoryBuffer *Buffer; + std::unique_ptr<MemoryBuffer> Buffer; /// This is the location of the parent include, or null if at the top level. SMLoc IncludeLoc; + + SrcBuffer() {} + + SrcBuffer(SrcBuffer &&O) + : Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {} }; /// This is all of the buffers that we are reading from. @@ -96,7 +101,7 @@ public: const MemoryBuffer *getMemoryBuffer(unsigned i) const { assert(isValidBufferID(i)); - return Buffers[i - 1].Buffer; + return Buffers[i - 1].Buffer.get(); } unsigned getNumBuffers() const { @@ -115,11 +120,12 @@ public: /// Add a new source buffer to this source manager. This takes ownership of /// the memory buffer. - unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F, + SMLoc IncludeLoc) { SrcBuffer NB; - NB.Buffer = F; + NB.Buffer = std::move(F); NB.IncludeLoc = IncludeLoc; - Buffers.push_back(NB); + Buffers.push_back(std::move(NB)); return Buffers.size(); } diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h index 098b9c7a17b7..313212e59dd2 100644 --- a/include/llvm/Support/SpecialCaseList.h +++ b/include/llvm/Support/SpecialCaseList.h @@ -56,17 +56,19 @@ class Regex; class StringRef; class SpecialCaseList { - public: +public: /// Parses the special case list from a file. If Path is empty, returns /// an empty special case list. On failure, returns 0 and writes an error /// message to string. - static SpecialCaseList *create(const StringRef Path, std::string &Error); + static std::unique_ptr<SpecialCaseList> create(StringRef Path, + std::string &Error); /// Parses the special case list from a memory buffer. On failure, returns /// 0 and writes an error message to string. - static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); + static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB, + std::string &Error); /// Parses the special case list from a file. On failure, reports a fatal /// error. - static SpecialCaseList *createOrDie(const StringRef Path); + static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path); ~SpecialCaseList(); @@ -75,10 +77,10 @@ class SpecialCaseList { /// @Section:<E>=@Category /// \endcode /// and @Query satisfies a wildcard expression <E>. - bool inSection(const StringRef Section, const StringRef Query, - const StringRef Category = StringRef()) const; + bool inSection(StringRef Section, StringRef Query, + StringRef Category = StringRef()) const; - private: +private: SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h deleted file mode 100644 index 6e71ad47c8dd..000000000000 --- a/include/llvm/Support/StreamableMemoryObject.h +++ /dev/null @@ -1,178 +0,0 @@ -//===- StreamableMemoryObject.h - Streamable data interface -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H -#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H - -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataStream.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryObject.h" -#include <cassert> -#include <memory> -#include <vector> - -namespace llvm { - -/// StreamableMemoryObject - Interface to data which might be streamed. -/// Streamability has 2 important implications/restrictions. First, the data -/// might not yet exist in memory when the request is made. This just means -/// that readByte/readBytes might have to block or do some work to get it. -/// More significantly, the exact size of the object might not be known until -/// it has all been fetched. This means that to return the right result, -/// getExtent must also wait for all the data to arrive; therefore it should -/// not be called on objects which are actually streamed (this would defeat -/// the purpose of streaming). Instead, isValidAddress and isObjectEnd can be -/// used to test addresses without knowing the exact size of the stream. -/// Finally, getPointer can be used instead of readBytes to avoid extra copying. -class StreamableMemoryObject : public MemoryObject { - public: - /// Destructor - Override as necessary. - virtual ~StreamableMemoryObject(); - - /// getBase - Returns the lowest valid address in the region. - /// - /// @result - The lowest valid address. - uint64_t getBase() const override = 0; - - /// getExtent - Returns the size of the region in bytes. (The region is - /// contiguous, so the highest valid address of the region - /// is getBase() + getExtent() - 1). - /// May block until all bytes in the stream have been read - /// - /// @result - The size of the region. - uint64_t getExtent() const override = 0; - - /// readByte - Tries to read a single byte from the region. - /// May block until (address - base) bytes have been read - /// @param address - The address of the byte, in the same space as getBase(). - /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. - /// @result - 0 if successful; -1 if not. Failure may be due to a - /// bounds violation or an implementation-specific error. - int readByte(uint64_t address, uint8_t *ptr) const override = 0; - - /// readBytes - Tries to read a contiguous range of bytes from the - /// region, up to the end of the region. - /// May block until (address - base + size) bytes have - /// been read. Additionally, StreamableMemoryObjects will - /// not do partial reads - if size bytes cannot be read, - /// readBytes will fail. - /// - /// @param address - The address of the first byte, in the same space as - /// getBase(). - /// @param size - The number of bytes to copy. - /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL - /// and large enough to hold size bytes. - /// @result - 0 if successful; -1 if not. Failure may be due to a - /// bounds violation or an implementation-specific error. - int readBytes(uint64_t address, uint64_t size, - uint8_t *buf) const override = 0; - - /// getPointer - Ensures that the requested data is in memory, and returns - /// A pointer to it. More efficient than using readBytes if the - /// data is already in memory. - /// May block until (address - base + size) bytes have been read - /// @param address - address of the byte, in the same space as getBase() - /// @param size - amount of data that must be available on return - /// @result - valid pointer to the requested data - virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0; - - /// isValidAddress - Returns true if the address is within the object - /// (i.e. between base and base + extent - 1 inclusive) - /// May block until (address - base) bytes have been read - /// @param address - address of the byte, in the same space as getBase() - /// @result - true if the address may be read with readByte() - virtual bool isValidAddress(uint64_t address) const = 0; - - /// isObjectEnd - Returns true if the address is one past the end of the - /// object (i.e. if it is equal to base + extent) - /// May block until (address - base) bytes have been read - /// @param address - address of the byte, in the same space as getBase() - /// @result - true if the address is equal to base + extent - virtual bool isObjectEnd(uint64_t address) const = 0; -}; - -/// StreamingMemoryObject - interface to data which is actually streamed from -/// a DataStreamer. In addition to inherited members, it has the -/// dropLeadingBytes and setKnownObjectSize methods which are not applicable -/// to non-streamed objects. -class StreamingMemoryObject : public StreamableMemoryObject { -public: - StreamingMemoryObject(DataStreamer *streamer); - uint64_t getBase() const override { return 0; } - uint64_t getExtent() const override; - int readByte(uint64_t address, uint8_t *ptr) const override; - int readBytes(uint64_t address, uint64_t size, - uint8_t *buf) const override; - const uint8_t *getPointer(uint64_t address, uint64_t size) const override { - // This could be fixed by ensuring the bytes are fetched and making a copy, - // requiring that the bitcode size be known, or otherwise ensuring that - // the memory doesn't go away/get reallocated, but it's - // not currently necessary. Users that need the pointer don't stream. - llvm_unreachable("getPointer in streaming memory objects not allowed"); - return nullptr; - } - bool isValidAddress(uint64_t address) const override; - bool isObjectEnd(uint64_t address) const override; - - /// Drop s bytes from the front of the stream, pushing the positions of the - /// remaining bytes down by s. This is used to skip past the bitcode header, - /// since we don't know a priori if it's present, and we can't put bytes - /// back into the stream once we've read them. - bool dropLeadingBytes(size_t s); - - /// If the data object size is known in advance, many of the operations can - /// be made more efficient, so this method should be called before reading - /// starts (although it can be called anytime). - void setKnownObjectSize(size_t size); - -private: - const static uint32_t kChunkSize = 4096 * 4; - mutable std::vector<unsigned char> Bytes; - std::unique_ptr<DataStreamer> Streamer; - mutable size_t BytesRead; // Bytes read from stream - size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) - mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached - mutable bool EOFReached; - - // Fetch enough bytes such that Pos can be read or EOF is reached - // (i.e. BytesRead > Pos). Return true if Pos can be read. - // Unlike most of the functions in BitcodeReader, returns true on success. - // Most of the requests will be small, but we fetch at kChunkSize bytes - // at a time to avoid making too many potentially expensive GetBytes calls - bool fetchToPos(size_t Pos) const { - if (EOFReached) return Pos < ObjectSize; - while (Pos >= BytesRead) { - Bytes.resize(BytesRead + BytesSkipped + kChunkSize); - size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], - kChunkSize); - BytesRead += bytes; - if (bytes < kChunkSize) { - assert((!ObjectSize || BytesRead >= Pos) && - "Unexpected short read fetching bitcode"); - if (BytesRead <= Pos) { // reached EOF/ran out of bytes - ObjectSize = BytesRead; - EOFReached = true; - return false; - } - } - } - return true; - } - - StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; - void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; -}; - -StreamableMemoryObject *getNonStreamedMemoryObject( - const unsigned char *Start, const unsigned char *End); - -} -#endif // STREAMABLEMEMORYOBJECT_H_ diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h new file mode 100644 index 000000000000..66ed521a411c --- /dev/null +++ b/include/llvm/Support/StreamingMemoryObject.h @@ -0,0 +1,92 @@ +//===- StreamingMemoryObject.h - Streamable data interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H +#define LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryObject.h" +#include <cassert> +#include <memory> +#include <vector> + +namespace llvm { + +/// Interface to data which is actually streamed from a DataStreamer. In +/// addition to inherited members, it has the dropLeadingBytes and +/// setKnownObjectSize methods which are not applicable to non-streamed objects. +class StreamingMemoryObject : public MemoryObject { +public: + StreamingMemoryObject(DataStreamer *streamer); + uint64_t getExtent() const override; + uint64_t readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const override; + const uint8_t *getPointer(uint64_t address, uint64_t size) const override { + // This could be fixed by ensuring the bytes are fetched and making a copy, + // requiring that the bitcode size be known, or otherwise ensuring that + // the memory doesn't go away/get reallocated, but it's + // not currently necessary. Users that need the pointer don't stream. + llvm_unreachable("getPointer in streaming memory objects not allowed"); + return nullptr; + } + bool isValidAddress(uint64_t address) const override; + + /// Drop s bytes from the front of the stream, pushing the positions of the + /// remaining bytes down by s. This is used to skip past the bitcode header, + /// since we don't know a priori if it's present, and we can't put bytes + /// back into the stream once we've read them. + bool dropLeadingBytes(size_t s); + + /// If the data object size is known in advance, many of the operations can + /// be made more efficient, so this method should be called before reading + /// starts (although it can be called anytime). + void setKnownObjectSize(size_t size); + +private: + const static uint32_t kChunkSize = 4096 * 4; + mutable std::vector<unsigned char> Bytes; + std::unique_ptr<DataStreamer> Streamer; + mutable size_t BytesRead; // Bytes read from stream + size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) + mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached + mutable bool EOFReached; + + // Fetch enough bytes such that Pos can be read or EOF is reached + // (i.e. BytesRead > Pos). Return true if Pos can be read. + // Unlike most of the functions in BitcodeReader, returns true on success. + // Most of the requests will be small, but we fetch at kChunkSize bytes + // at a time to avoid making too many potentially expensive GetBytes calls + bool fetchToPos(size_t Pos) const { + if (EOFReached) + return Pos < ObjectSize; + while (Pos >= BytesRead) { + Bytes.resize(BytesRead + BytesSkipped + kChunkSize); + size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], + kChunkSize); + BytesRead += bytes; + if (bytes != kChunkSize) { // reached EOF/ran out of bytes + ObjectSize = BytesRead; + EOFReached = true; + break; + } + } + return Pos < BytesRead; + } + + StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; + void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; +}; + +MemoryObject *getNonStreamedMemoryObject( + const unsigned char *Start, const unsigned char *End); + +} +#endif // STREAMINGMEMORYOBJECT_H_ diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index 3e0465340c3b..b51974c946e0 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -29,8 +29,8 @@ #ifndef LLVM_SUPPORT_STRINGPOOL_H #define LLVM_SUPPORT_STRINGPOOL_H -#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/Compiler.h" #include <cassert> #include <new> diff --git a/include/llvm/Support/StringRefMemoryObject.h b/include/llvm/Support/StringRefMemoryObject.h deleted file mode 100644 index 8a349eab84c8..000000000000 --- a/include/llvm/Support/StringRefMemoryObject.h +++ /dev/null @@ -1,41 +0,0 @@ -//===- llvm/Support/StringRefMemoryObject.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the StringRefMemObject class, a simple -// wrapper around StringRef implementing the MemoryObject interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_STRINGREFMEMORYOBJECT_H -#define LLVM_SUPPORT_STRINGREFMEMORYOBJECT_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/MemoryObject.h" - -namespace llvm { - -/// StringRefMemoryObject - Simple StringRef-backed MemoryObject -class StringRefMemoryObject : public MemoryObject { - StringRef Bytes; - uint64_t Base; -public: - StringRefMemoryObject(StringRef Bytes, uint64_t Base = 0) - : Bytes(Bytes), Base(Base) {} - - uint64_t getBase() const override { return Base; } - uint64_t getExtent() const override { return Bytes.size(); } - - int readByte(uint64_t Addr, uint8_t *Byte) const override; - int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const override; -}; - -} - -#endif diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 340954f4c893..9c5a3c59122e 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_SWAPBYTEORDER_H #define LLVM_SUPPORT_SWAPBYTEORDER_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cstddef> #include <limits> @@ -39,8 +40,7 @@ inline uint16_t SwapByteOrder_16(uint16_t value) { /// SwapByteOrder_32 - This function returns a byte-swapped representation of /// the 32-bit argument. inline uint32_t SwapByteOrder_32(uint32_t value) { -#if defined(__llvm__) || \ -(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) +#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) return __builtin_bswap32(value); #elif defined(_MSC_VER) && !defined(_DEBUG) return _byteswap_ulong(value); @@ -56,8 +56,7 @@ inline uint32_t SwapByteOrder_32(uint32_t value) { /// SwapByteOrder_64 - This function returns a byte-swapped representation of /// the 64-bit argument. inline uint64_t SwapByteOrder_64(uint64_t value) { -#if defined(__llvm__) || \ -(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) +#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) return __builtin_bswap64(value); #elif defined(_MSC_VER) && !defined(_DEBUG) return _byteswap_uint64(value); diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 5d5b86a6a2ae..8ac4b904bb88 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -123,15 +123,10 @@ namespace llvm { const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); - typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T, - StringRef TT, - MCContext &Ctx, - MCAsmBackend &TAB, - raw_ostream &_OS, - MCCodeEmitter *_Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll, - bool NoExecStack); + typedef MCStreamer *(*MCObjectStreamerCtorTy)( + const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &_OS, MCCodeEmitter *_Emitter, const MCSubtargetInfo &STI, + bool RelaxAll); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, @@ -423,18 +418,15 @@ namespace llvm { /// \param _OS The stream object. /// \param _Emitter The target independent assembler object.Takes ownership. /// \param RelaxAll Relax all fixups? - /// \param NoExecStack Mark file as not needing a executable stack. MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, - MCAsmBackend &TAB, - raw_ostream &_OS, + MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, const MCSubtargetInfo &STI, - bool RelaxAll, - bool NoExecStack) const { + bool RelaxAll) const { if (!MCObjectStreamerCtorFn) return nullptr; return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, - RelaxAll, NoExecStack); + RelaxAll); } /// createAsmStreamer - Create a target specific MCStreamer. diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 7518626901e0..427a67e2a96d 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -36,7 +36,7 @@ namespace llvm { ThreadLocalImpl(); virtual ~ThreadLocalImpl(); void setInstance(const void* d); - const void* getInstance(); + void *getInstance(); void removeInstance(); }; diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index 7e8758407c7c..3cca1d6a9913 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -21,7 +21,8 @@ namespace llvm { bool llvm_is_multithreaded(); /// llvm_execute_on_thread - Execute the given \p UserFn on a separate - /// thread, passing it the provided \p UserData. + /// thread, passing it the provided \p UserData and waits for thread + /// completion. /// /// This function does not guarantee that the code will actually be executed /// on a separate thread or honoring the requested stack size, but tries to do diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index ee0e2866d59e..6bca58b6bc20 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -38,28 +38,38 @@ namespace sys { /// value permissible by the class. MinTime is some point /// in the distant past, about 300 billion years BCE. /// @brief The smallest possible time value. - static const TimeValue MinTime; + static TimeValue MinTime() { + return TimeValue ( INT64_MIN,0 ); + } /// A constant TimeValue representing the largest time /// value permissible by the class. MaxTime is some point /// in the distant future, about 300 billion years AD. /// @brief The largest possible time value. - static const TimeValue MaxTime; + static TimeValue MaxTime() { + return TimeValue ( INT64_MAX,0 ); + } /// A constant TimeValue representing the base time, /// or zero time of 00:00:00 (midnight) January 1st, 2000. /// @brief 00:00:00 Jan 1, 2000 UTC. - static const TimeValue ZeroTime; + static TimeValue ZeroTime() { + return TimeValue ( 0,0 ); + } /// A constant TimeValue for the Posix base time which is /// 00:00:00 (midnight) January 1st, 1970. /// @brief 00:00:00 Jan 1, 1970 UTC. - static const TimeValue PosixZeroTime; + static TimeValue PosixZeroTime() { + return TimeValue ( PosixZeroTimeSeconds,0 ); + } /// A constant TimeValue for the Win32 base time which is /// 00:00:00 (midnight) January 1st, 1601. /// @brief 00:00:00 Jan 1, 1601 UTC. - static const TimeValue Win32ZeroTime; + static TimeValue Win32ZeroTime() { + return TimeValue ( Win32ZeroTimeSeconds,0 ); + } /// @} /// @name Types diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index 88f8ccc292d3..d98e7bbd51d4 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -29,13 +29,13 @@ class tool_output_file { /// destructed after the raw_fd_ostream is destructed. It installs /// cleanups in its constructor and uninstalls them in its destructor. class CleanupInstaller { - /// Filename - The name of the file. + /// The name of the file. std::string Filename; public: - /// Keep - The flag which indicates whether we should not delete the file. + /// The flag which indicates whether we should not delete the file. bool Keep; - explicit CleanupInstaller(const char *filename); + explicit CleanupInstaller(StringRef ilename); ~CleanupInstaller(); } Installer; @@ -44,12 +44,12 @@ class tool_output_file { raw_fd_ostream OS; public: - /// tool_output_file - This constructor's arguments are passed to - /// to raw_fd_ostream's constructor. - tool_output_file(const char *filename, std::string &ErrorInfo, + /// This constructor's arguments are passed to to raw_fd_ostream's + /// constructor. + tool_output_file(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); - tool_output_file(const char *Filename, int FD); + tool_output_file(StringRef Filename, int FD); /// os - Return the contained raw_fd_ostream. raw_fd_ostream &os() { return OS; } diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h new file mode 100644 index 000000000000..5a4c273e83e2 --- /dev/null +++ b/include/llvm/Support/UniqueLock.h @@ -0,0 +1,67 @@ +//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H +#define LLVM_SUPPORT_UNIQUE_LOCK_H + +#include "llvm/Support/Mutex.h" + +namespace llvm { + /// A pared-down imitation of std::unique_lock from C++11. Contrary to the + /// name, it's really more of a wrapper for a lock. It may or may not have + /// an associated mutex, which is guaranteed to be locked upon creation + /// and unlocked after destruction. unique_lock can also unlock the mutex + /// and re-lock it freely during its lifetime. + /// @brief Guard a section of code with a mutex. + template<typename MutexT> + class unique_lock { + MutexT *M; + bool locked; + + unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION; + void operator=(const unique_lock &) LLVM_DELETED_FUNCTION; + public: + unique_lock() : M(nullptr), locked(false) {} + explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); } + + void operator=(unique_lock &&o) { + if (owns_lock()) + M->unlock(); + M = o.M; + locked = o.locked; + o.M = nullptr; + o.locked = false; + } + + ~unique_lock() { if (owns_lock()) M->unlock(); } + + void lock() { + assert(!locked && "mutex already locked!"); + assert(M && "no associated mutex!"); + M->lock(); + locked = true; + } + + void unlock() { + assert(locked && "unlocking a mutex that isn't locked!"); + assert(M && "no associated mutex!"); + M->unlock(); + locked = false; + } + + bool owns_lock() { return locked; } + }; +} + +#endif // LLVM_SUPPORT_UNIQUE_LOCK_H diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h index 7ca218e87a77..f6c492794875 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -40,8 +40,8 @@ enum UnwindOpcodes { /// or part thereof. union UnwindCode { struct { - support::ulittle8_t CodeOffset; - support::ulittle8_t UnwindOpAndOpInfo; + uint8_t CodeOffset; + uint8_t UnwindOpAndOpInfo; } u; support::ulittle16_t FrameOffset; @@ -74,10 +74,10 @@ struct RuntimeFunction { /// UnwindInfo - An entry in the exception table. struct UnwindInfo { - support::ulittle8_t VersionAndFlags; - support::ulittle8_t PrologSize; - support::ulittle8_t NumCodes; - support::ulittle8_t FrameRegisterAndOffset; + uint8_t VersionAndFlags; + uint8_t PrologSize; + uint8_t NumCodes; + uint8_t FrameRegisterAndOffset; UnwindCode UnwindCodes[1]; uint8_t getVersion() const { diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h index 0e909a05bf4a..63bfe5976546 100644 --- a/include/llvm/Support/WindowsError.h +++ b/include/llvm/Support/WindowsError.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_WINDOWS_ERROR_H -#define LLVM_SUPPORT_WINDOWS_ERROR_H +#ifndef LLVM_SUPPORT_WINDOWSERROR_H +#define LLVM_SUPPORT_WINDOWSERROR_H #include <system_error> diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index c39874cbd2c5..de6e6544e25b 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -41,13 +41,13 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" #include <limits> #include <map> #include <utility> namespace llvm { -class MemoryBuffer; class SourceMgr; class raw_ostream; class Twine; @@ -79,8 +79,7 @@ public: /// \brief This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &); - /// \brief This takes ownership of \p InputBuffer. - Stream(MemoryBuffer *InputBuffer, SourceMgr &); + Stream(MemoryBufferRef InputBuffer, SourceMgr &); ~Stream(); document_iterator begin(); diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index a23faf65bb59..023dcee7d54c 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -943,16 +943,17 @@ private: }; class MapHNode : public HNode { + virtual void anchor(); + public: MapHNode(Node *n) : HNode(n) { } - virtual ~MapHNode(); static inline bool classof(const HNode *n) { return MappingNode::classof(n->_node); } static inline bool classof(const MapHNode *) { return true; } - typedef llvm::StringMap<HNode*> NameToNode; + typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode; bool isValidKey(StringRef key); @@ -961,19 +962,20 @@ private: }; class SequenceHNode : public HNode { + virtual void anchor(); + public: SequenceHNode(Node *n) : HNode(n) { } - virtual ~SequenceHNode(); static inline bool classof(const HNode *n) { return SequenceNode::classof(n->_node); } static inline bool classof(const SequenceHNode *) { return true; } - std::vector<HNode*> Entries; + std::vector<std::unique_ptr<HNode>> Entries; }; - Input::HNode *createHNodes(Node *node); + std::unique_ptr<Input::HNode> createHNodes(Node *node); void setError(HNode *hnode, const Twine &message); void setError(Node *node, const Twine &message); diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 34fbe082cda8..c9ef637940db 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -17,9 +17,12 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include <system_error> namespace llvm { class format_object_base; + class FormattedString; + class FormattedNumber; template <typename T> class SmallVectorImpl; @@ -210,6 +213,12 @@ public: // Formatted output, see the format() function in Support/Format.h. raw_ostream &operator<<(const format_object_base &Fmt); + // Formatted output, see the leftJustify() function in Support/Format.h. + raw_ostream &operator<<(const FormattedString &); + + // Formatted output, see the formatHex() function in Support/Format.h. + raw_ostream &operator<<(const FormattedNumber &); + /// indent - Insert 'NumSpaces' spaces. raw_ostream &indent(unsigned NumSpaces); @@ -341,17 +350,17 @@ class raw_fd_ostream : public raw_ostream { void error_detected() { Error = true; } public: - /// raw_fd_ostream - Open the specified file for writing. If an error occurs, - /// information about the error is put into ErrorInfo, and the stream should - /// be immediately destroyed; the string will be empty if no error occurred. - /// This allows optional flags to control how the file will be opened. + /// Open the specified file for writing. If an error occurs, information + /// about the error is put into EC, and the stream should be immediately + /// destroyed; + /// \p Flags allows optional flags to control how the file will be opened. /// /// As a special case, if Filename is "-", then the stream will use /// STDOUT_FILENO instead of opening a file. Note that it will still consider /// itself to own the file descriptor. In particular, it will close the /// file descriptor when it is done (this is necessary to detect /// output errors). - raw_fd_ostream(const char *Filename, std::string &ErrorInfo, + raw_fd_ostream(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 36464d75d5ab..4abeddd6be29 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -432,8 +432,8 @@ protected: /// readability for really no benefit. enum InitKind { IK_BitInit, - IK_BitsInit, IK_FirstTypedInit, + IK_BitsInit, IK_DagInit, IK_DefInit, IK_FieldInit, @@ -651,11 +651,12 @@ public: /// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. /// It contains a vector of bits, whose size is determined by the type. /// -class BitsInit : public Init, public FoldingSetNode { +class BitsInit : public TypedInit, public FoldingSetNode { std::vector<Init*> Bits; BitsInit(ArrayRef<Init *> Range) - : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {} + : TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())), + Bits(Range.begin(), Range.end()) {} BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION; BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION; @@ -688,6 +689,14 @@ public: } std::string getAsString() const override; + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { + llvm_unreachable("Illegal element reference off bits<n>"); + } + Init *resolveReferences(Record &R, const RecordVal *RV) const override; Init *getBit(unsigned Bit) const override { @@ -928,7 +937,7 @@ public: /// class BinOpInit : public OpInit { public: - enum BinaryOp { ADD, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ }; + enum BinaryOp { ADD, AND, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ }; private: BinaryOp Opc; @@ -1392,6 +1401,18 @@ class Record { DefInit *TheInit; bool IsAnonymous; + // Class-instance values can be used by other defs. For example, Struct<i> + // is used here as a template argument to another class: + // + // multiclass MultiClass<int i> { + // def Def : Class<Struct<i>>; + // + // These need to get fully resolved before instantiating any other + // definitions that usie them (e.g. Def). However, inside a multiclass they + // can't be immediately resolved so we mark them ResolveFirst to fully + // resolve them later as soon as the multiclass is instantiated. + bool ResolveFirst; + void init(); void checkName(); @@ -1400,13 +1421,15 @@ public: explicit Record(const std::string &N, ArrayRef<SMLoc> locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous), + ResolveFirst(false) { init(); } explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(N), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous), + ResolveFirst(false) { init(); } @@ -1416,7 +1439,8 @@ public: ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), Values(O.Values), SuperClasses(O.SuperClasses), SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords), - TheInit(O.TheInit), IsAnonymous(O.IsAnonymous) { } + TheInit(O.TheInit), IsAnonymous(O.IsAnonymous), + ResolveFirst(O.ResolveFirst) { } ~Record() {} @@ -1544,6 +1568,14 @@ public: return IsAnonymous; } + bool isResolveFirst() const { + return ResolveFirst; + } + + void setResolveFirst(bool b) { + ResolveFirst = b; + } + void dump() const; //===--------------------------------------------------------------------===// @@ -1631,7 +1663,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Record &R); struct MultiClass { Record Rec; // Placeholder for template args and Name. - typedef std::vector<Record*> RecordVector; + typedef std::vector<std::unique_ptr<Record>> RecordVector; RecordVector DefPrototypes; void dump() const; @@ -1641,53 +1673,34 @@ struct MultiClass { }; class RecordKeeper { - std::map<std::string, Record*> Classes, Defs; + typedef std::map<std::string, std::unique_ptr<Record>> RecordMap; + RecordMap Classes, Defs; public: - ~RecordKeeper() { - for (std::map<std::string, Record*>::iterator I = Classes.begin(), - E = Classes.end(); I != E; ++I) - delete I->second; - for (std::map<std::string, Record*>::iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - delete I->second; - } - - const std::map<std::string, Record*> &getClasses() const { return Classes; } - const std::map<std::string, Record*> &getDefs() const { return Defs; } + const RecordMap &getClasses() const { return Classes; } + const RecordMap &getDefs() const { return Defs; } Record *getClass(const std::string &Name) const { - std::map<std::string, Record*>::const_iterator I = Classes.find(Name); - return I == Classes.end() ? nullptr : I->second; + auto I = Classes.find(Name); + return I == Classes.end() ? nullptr : I->second.get(); } Record *getDef(const std::string &Name) const { - std::map<std::string, Record*>::const_iterator I = Defs.find(Name); - return I == Defs.end() ? nullptr : I->second; + auto I = Defs.find(Name); + return I == Defs.end() ? nullptr : I->second.get(); } - void addClass(Record *R) { - bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second; + void addClass(std::unique_ptr<Record> R) { + bool Ins = Classes.insert(std::make_pair(R->getName(), + std::move(R))).second; (void)Ins; assert(Ins && "Class already exists"); } - void addDef(Record *R) { - bool Ins = Defs.insert(std::make_pair(R->getName(), R)).second; + void addDef(std::unique_ptr<Record> R) { + bool Ins = Defs.insert(std::make_pair(R->getName(), + std::move(R))).second; (void)Ins; assert(Ins && "Record already exists"); } - /// removeClass - Remove, but do not delete, the specified record. - /// - void removeClass(const std::string &Name) { - assert(Classes.count(Name) && "Class does not exist!"); - Classes.erase(Name); - } - /// removeDef - Remove, but do not delete, the specified record. - /// - void removeDef(const std::string &Name) { - assert(Defs.count(Name) && "Def does not exist!"); - Defs.erase(Name); - } - //===--------------------------------------------------------------------===// // High-level helper methods, useful for tablegen backends... diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h index 5baed79fb76a..76e56ec6443e 100644 --- a/include/llvm/TableGen/SetTheory.h +++ b/include/llvm/TableGen/SetTheory.h @@ -44,8 +44,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SETTHEORY_H -#define SETTHEORY_H +#ifndef LLVM_TABLEGEN_SETTHEORY_H +#define LLVM_TABLEGEN_SETTHEORY_H #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringMap.h" diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h index c924bd8ec57d..e3277036dc76 100644 --- a/include/llvm/TableGen/StringToOffsetTable.h +++ b/include/llvm/TableGen/StringToOffsetTable.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H -#define TBLGEN_STRING_TO_OFFSET_TABLE_H +#ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H +#define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -28,16 +28,16 @@ class StringToOffsetTable { public: unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { - StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U); - if (Entry.getValue() == -1U) { + auto IterBool = + StringOffset.insert(std::make_pair(Str, AggregateString.size())); + if (IterBool.second) { // Add the string to the aggregate if this is the first time found. - Entry.setValue(AggregateString.size()); AggregateString.append(Str.begin(), Str.end()); if (appendZero) AggregateString += '\0'; } - return Entry.getValue(); + return IterBool.first->second; } void EmitString(raw_ostream &O) { diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index f77cc7a35eb8..6c970d0c19db 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -378,20 +378,25 @@ class Instruction { bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? + bit isRegSequence = 0; // Is this instruction a kind of reg sequence? + // If so, make sure to override + // TargetInstrInfo::getRegSequenceLikeInputs. bit isPseudo = 0; // Is this instruction a pseudo-instruction? // If so, won't have encoding information for // the [MC]CodeEmitter stuff. + bit isExtractSubreg = 0; // Is this instruction a kind of extract subreg? + // If so, make sure to override + // TargetInstrInfo::getExtractSubregLikeInputs. + bit isInsertSubreg = 0; // Is this instruction a kind of insert subreg? + // If so, make sure to override + // TargetInstrInfo::getInsertSubregLikeInputs. // Side effect flags - When set, the flags have these meanings: // // hasSideEffects - The instruction has side effects that are not // captured by any operands of the instruction or other flags. // - // neverHasSideEffects (deprecated) - Set on an instruction with no pattern - // if it has no side effects. This is now equivalent to setting - // "hasSideEffects = 0". bit hasSideEffects = ?; - bit neverHasSideEffects = 0; // Is this instruction a "real" instruction (with a distinct machine // encoding), or is it a pseudo instruction used for codegen modeling @@ -583,7 +588,6 @@ class Operand<ValueType ty> : DAGOperand { string PrintMethod = "printOperand"; string EncoderMethod = ""; string DecoderMethod = ""; - string AsmOperandLowerMethod = ?; string OperandType = "OPERAND_UNKNOWN"; dag MIOperandInfo = (ops); @@ -620,6 +624,9 @@ class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> // can match a subset of some other class, in which case the AsmOperandClass // should declare the other operand as one of its super classes. AsmOperandClass ParserMatchClass; + + string OperandNamespace = "MCOI"; + string OperandType = "OPERAND_REGISTER"; } let OperandType = "OPERAND_IMMEDIATE" in { @@ -726,7 +733,7 @@ def INLINEASM : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = ""; - let neverHasSideEffects = 1; // Note side effect is encoded in an operand. + let hasSideEffects = 0; // Note side effect is encoded in an operand. } def CFI_INSTRUCTION : Instruction { let OutOperandList = (outs); @@ -753,26 +760,26 @@ def KILL : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def EXTRACT_SUBREG : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$supersrc, i32imm:$subidx); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def INSERT_SUBREG : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let Constraints = "$supersrc = $dst"; } def IMPLICIT_DEF : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isReMaterializable = 1; let isAsCheapAsAMove = 1; } @@ -780,33 +787,33 @@ def SUBREG_TO_REG : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def COPY_TO_REGCLASS : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$src, i32imm:$regclass); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isAsCheapAsAMove = 1; } def DBG_VALUE : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "DBG_VALUE"; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def REG_SEQUENCE : Instruction { let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins variable_ops); + let InOperandList = (ins unknown:$supersrc, variable_ops); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isAsCheapAsAMove = 1; } def COPY : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$src); let AsmString = ""; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isAsCheapAsAMove = 1; } def BUNDLE : Instruction { @@ -818,13 +825,13 @@ def LIFETIME_START : Instruction { let OutOperandList = (outs); let InOperandList = (ins i32imm:$id); let AsmString = "LIFETIME_START"; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def LIFETIME_END : Instruction { let OutOperandList = (outs); let InOperandList = (ins i32imm:$id); let AsmString = "LIFETIME_END"; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } def STACKMAP : Instruction { let OutOperandList = (outs); @@ -841,6 +848,32 @@ def PATCHPOINT : Instruction { let mayLoad = 1; let usesCustomInserter = 1; } +def STATEPOINT : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; + let isCall = 1; +} +def LOAD_STACK_GUARD : Instruction { + let OutOperandList = (outs ptr_rc:$dst); + let InOperandList = (ins); + let mayLoad = 1; + bit isReMaterializable = 1; + let hasSideEffects = 0; + bit isPseudo = 1; +} +def FRAME_ALLOC : Instruction { + // This instruction is really just a label. It has to be part of the chain so + // that it doesn't get dropped from the DAG, but it produces nothing and has + // no side effects. + let OutOperandList = (outs); + let InOperandList = (ins ptr_rc:$symbol, i32imm:$id); + let hasSideEffects = 0; + let hasCtrlDep = 1; +} } //===----------------------------------------------------------------------===// @@ -989,9 +1022,6 @@ class AsmWriter { // will specify which alternative to use. For example "{x|y|z}" with Variant // == 1, will expand to "y". int Variant = 0; - - // OperandSpacing - Space between operand columns. - int OperandSpacing = -1; } def DefaultAsmWriter : AsmWriter; diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index bfddd0601794..277bd98d371c 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -142,6 +142,10 @@ public: /// the assembly prologue to explicitly handle the stack. virtual void adjustForHiPEPrologue(MachineFunction &MF) const { } + /// Adjust the prologue to add an allocation at a fixed offset from the frame + /// pointer. + virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { } + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee /// saved registers and returns true if it isn't possible / profitable to do /// so by issuing a series of store instructions via @@ -199,6 +203,16 @@ public: virtual int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const; + /// Same as above, except that the 'base register' will always be RSP, not + /// RBP on x86. This is used exclusively for lowering STATEPOINT nodes. + /// TODO: This should really be a parameterizable choice. + virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { + // default to calling normal version, we override this on x86 only + llvm_unreachable("unimplemented for non-x86"); + return 0; + } + /// processFunctionBeforeCalleeSavedScan - This method is called immediately /// before PrologEpilogInserter scans the physical registers used to determine /// what callee saved registers should be spilled. This method is optional. diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 87e7c14ac1e8..e8a50fff1fe8 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -14,10 +14,12 @@ #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/CodeGen/DFAPacketizer.h" +#include "llvm/CodeGen/MachineCombinerPattern.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" namespace llvm { @@ -28,7 +30,7 @@ class MachineMemOperand; class MachineRegisterInfo; class MDNode; class MCInst; -class MCSchedModel; +struct MCSchedModel; class MCSymbolRefExpr; class SDNode; class ScheduleHazardRecognizer; @@ -38,6 +40,7 @@ class TargetRegisterClass; class TargetRegisterInfo; class BranchProbability; class TargetSubtargetInfo; +class DFAPacketizer; template<class T> class SmallVectorImpl; @@ -106,6 +109,12 @@ public: int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + /// Returns the actual stack pointer adjustment made by an instruction + /// as part of a call sequence. By default, only call frame setup/destroy + /// instructions adjust the stack, but targets may want to override this + /// to enable more fine-grained adjustment, or adjust by a different value. + virtual int getSPAdjust(const MachineInstr *MI) const; + /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" /// extension instruction. That is, it's like a copy where it's legal for the /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns @@ -200,6 +209,15 @@ public: unsigned &Size, unsigned &Offset, const TargetMachine *TM) const; + /// isAsCheapAsAMove - Return true if the instruction is as cheap as a move + /// instruction. + /// + /// Targets for different archs need to override this, and different + /// micro-architectures can also be finely tuned inside. + virtual bool isAsCheapAsAMove(const MachineInstr *MI) const { + return MI->isAsCheapAsAMove(); + } + /// reMaterialize - Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. /// The register in Orig->getOperand(0).getReg() will be substituted by @@ -252,6 +270,85 @@ public: virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const; + /// A pair composed of a register and a sub-register index. + /// Used to give some type checking when modeling Reg:SubReg. + struct RegSubRegPair { + unsigned Reg; + unsigned SubReg; + RegSubRegPair(unsigned Reg = 0, unsigned SubReg = 0) + : Reg(Reg), SubReg(SubReg) {} + }; + /// A pair composed of a pair of a register and a sub-register index, + /// and another sub-register index. + /// Used to give some type checking when modeling Reg:SubReg1, SubReg2. + struct RegSubRegPairAndIdx : RegSubRegPair { + unsigned SubIdx; + RegSubRegPairAndIdx(unsigned Reg = 0, unsigned SubReg = 0, + unsigned SubIdx = 0) + : RegSubRegPair(Reg, SubReg), SubIdx(SubIdx) {} + }; + + /// Build the equivalent inputs of a REG_SEQUENCE for the given \p MI + /// and \p DefIdx. + /// \p [out] InputRegs of the equivalent REG_SEQUENCE. Each element of + /// the list is modeled as <Reg:SubReg, SubIdx>. + /// E.g., REG_SEQUENCE vreg1:sub1, sub0, vreg2, sub1 would produce + /// two elements: + /// - vreg1:sub1, sub0 + /// - vreg2<:0>, sub1 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isRegSequence() or MI.isRegSequenceLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isRegSequenceLike(). In other words, one has to override + /// getRegSequenceLikeInputs for target specific instructions. + bool + getRegSequenceInputs(const MachineInstr &MI, unsigned DefIdx, + SmallVectorImpl<RegSubRegPairAndIdx> &InputRegs) const; + + /// Build the equivalent inputs of a EXTRACT_SUBREG for the given \p MI + /// and \p DefIdx. + /// \p [out] InputReg of the equivalent EXTRACT_SUBREG. + /// E.g., EXTRACT_SUBREG vreg1:sub1, sub0, sub1 would produce: + /// - vreg1:sub1, sub0 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isExtractSubreg() or MI.isExtractSubregLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isExtractSubregLike(). In other words, one has to override + /// getExtractSubregLikeInputs for target specific instructions. + bool + getExtractSubregInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPairAndIdx &InputReg) const; + + /// Build the equivalent inputs of a INSERT_SUBREG for the given \p MI + /// and \p DefIdx. + /// \p [out] BaseReg and \p [out] InsertedReg contain + /// the equivalent inputs of INSERT_SUBREG. + /// E.g., INSERT_SUBREG vreg0:sub0, vreg1:sub1, sub3 would produce: + /// - BaseReg: vreg0:sub0 + /// - InsertedReg: vreg1:sub1, sub3 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isInsertSubreg() or MI.isInsertSubregLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isInsertSubregLike(). In other words, one has to override + /// getInsertSubregLikeInputs for target specific instructions. + bool + getInsertSubregInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPair &BaseReg, + RegSubRegPairAndIdx &InsertedReg) const; + + /// produceSameValue - Return true if two machine instructions would produce /// identical values. By default, this is only true when the two instructions /// are deemed identical except for defs. If this function is called when the @@ -337,6 +434,26 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); } + /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold + /// either the instruction returned by getUnconditionalBranch or the + /// instruction returned by getTrap. This only makes sense because + /// getUnconditionalBranch returns a single, specific instruction. This + /// information is needed by the jumptable construction code, since it must + /// decide how many bytes to use for a jumptable entry so it can generate the + /// right mask. + /// + /// Note that if the jumptable instruction requires alignment, then that + /// alignment should be factored into this required bound so that the + /// resulting bound gives the right alignment for the instruction. + virtual unsigned getJumpInstrTableEntryBound() const { + // This method gets called by LLVMTargetMachine always, so it can't fail + // just because there happens to be no implementation for this target. + // Any code that tries to use a jumptable annotation without defining + // getUnconditionalBranch on the appropriate Target will fail anyway, and + // the value returned here won't matter in that case. + return 0; + } + /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start /// of a new basic block). @@ -486,9 +603,12 @@ public: /// a side. /// /// @param MI Optimizable select instruction. + /// @param NewMIs Set that record all MIs in the basic block up to \p + /// MI. Has to be updated with any newly created MI or deleted ones. /// @param PreferFalse Try to optimize FalseOp instead of TrueOp. /// @returns Optimized instruction or NULL. virtual MachineInstr *optimizeSelect(MachineInstr *MI, + SmallPtrSetImpl<MachineInstr *> &NewMIs, bool PreferFalse = false) const { // This function must be implemented if Optimizable is ever set. llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!"); @@ -563,6 +683,42 @@ public: const SmallVectorImpl<unsigned> &Ops, MachineInstr* LoadMI) const; + /// hasPattern - return true when there is potentially a faster code sequence + /// for an instruction chain ending in \p Root. All potential pattern are + /// returned in the \p Pattern vector. Pattern should be sorted in priority + /// order since the pattern evaluator stops checking as soon as it finds a + /// faster sequence. + /// \param Root - Instruction that could be combined with one of its operands + /// \param Pattern - Vector of possible combination pattern + + virtual bool hasPattern( + MachineInstr &Root, + SmallVectorImpl<MachineCombinerPattern::MC_PATTERN> &Pattern) const { + return false; + } + + /// genAlternativeCodeSequence - when hasPattern() finds a pattern this + /// function generates the instructions that could replace the original code + /// sequence. The client has to decide whether the actual replacementment is + /// beneficial or not. + /// \param Root - Instruction that could be combined with one of its operands + /// \param P - Combination pattern for Root + /// \param InsInstrs - Vector of new instructions that implement P + /// \param DelInstrs - Old instructions, including Root, that could be replaced + /// by InsInstr + /// \param InstrIdxForVirtReg - map of virtual register to instruction in + /// InsInstr that defines it + virtual void genAlternativeCodeSequence( + MachineInstr &Root, MachineCombinerPattern::MC_PATTERN P, + SmallVectorImpl<MachineInstr *> &InsInstrs, + SmallVectorImpl<MachineInstr *> &DelInstrs, + DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const { + return; + } + + /// useMachineCombiner - return true when a target supports MachineCombiner + virtual bool useMachineCombiner() const { return false; } + protected: /// foldMemoryOperandImpl - Target-dependent implementation for /// foldMemoryOperand. Target-independent code in foldMemoryOperand will @@ -584,6 +740,49 @@ protected: return nullptr; } + /// \brief Target-dependent implementation of getRegSequenceInputs. + /// + /// \returns true if it is possible to build the equivalent + /// REG_SEQUENCE inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isRegSequenceLike(). + /// + /// \see TargetInstrInfo::getRegSequenceInputs. + virtual bool getRegSequenceLikeInputs( + const MachineInstr &MI, unsigned DefIdx, + SmallVectorImpl<RegSubRegPairAndIdx> &InputRegs) const { + return false; + } + + /// \brief Target-dependent implementation of getExtractSubregInputs. + /// + /// \returns true if it is possible to build the equivalent + /// EXTRACT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isExtractSubregLike(). + /// + /// \see TargetInstrInfo::getExtractSubregInputs. + virtual bool getExtractSubregLikeInputs( + const MachineInstr &MI, unsigned DefIdx, + RegSubRegPairAndIdx &InputReg) const { + return false; + } + + /// \brief Target-dependent implementation of getInsertSubregInputs. + /// + /// \returns true if it is possible to build the equivalent + /// INSERT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isInsertSubregLike(). + /// + /// \see TargetInstrInfo::getInsertSubregInputs. + virtual bool + getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPair &BaseReg, + RegSubRegPairAndIdx &InsertedReg) const { + return false; + } + public: /// canFoldMemoryOperand - Returns true for the specified load / store if /// folding is possible. @@ -677,10 +876,8 @@ public: MachineBasicBlock::iterator MI) const; - /// getNoopForMachoTarget - Return the noop instruction to use for a noop. - virtual void getNoopForMachoTarget(MCInst &NopInst) const { - // Default to just using 'nop' string. - } + /// Return the noop instruction to use for a noop. + virtual void getNoopForMachoTarget(MCInst &NopInst) const; /// isPredicated - Returns true if the instruction is already predicated. @@ -784,6 +981,7 @@ public: const MachineRegisterInfo *MRI) const { return false; } + virtual bool optimizeCondBranch(MachineInstr *MI) const { return false; } /// optimizeLoadInstr - Try to remove the load by folding it to a register /// operand at the use. We fold the load instructions if and only if the @@ -862,7 +1060,7 @@ public: SDNode *Node) const; /// Return the default expected latency for a def based on it's opcode. - unsigned defaultDefLatency(const MCSchedModel *SchedModel, + unsigned defaultDefLatency(const MCSchedModel &SchedModel, const MachineInstr *DefMI) const; int computeDefOperandLatency(const InstrItineraryData *ItinData, @@ -1017,11 +1215,25 @@ public: const TargetRegisterInfo *TRI) const {} /// Create machine specific model for scheduling. - virtual DFAPacketizer* - CreateTargetScheduleState(const TargetMachine*, const ScheduleDAG*) const { + virtual DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &) const { return nullptr; } + // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target + // to tell, even without aliasing information, that two MIs access different + // memory addresses. This function returns true if two MIs access different + // memory addresses, and false otherwise. + virtual bool + areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb, + AliasAnalysis *AA = nullptr) const { + assert(MIa && (MIa->mayLoad() || MIa->mayStore()) && + "MIa must load from or modify a memory location"); + assert(MIb && (MIb->mayLoad() || MIb->mayStore()) && + "MIb must load from or modify a memory location"); + return false; + } + private: int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index 6de264e90ef7..71c0166d49b0 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -52,7 +52,7 @@ public: /// Returns true if the intrinsic can be overloaded. virtual bool isOverloaded(unsigned IID) const = 0; - + /// Create or insert an LLVM Function declaration for an intrinsic, /// and return it. The Tys and numTys are for intrinsics with overloaded /// types. See above for more information. diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h deleted file mode 100644 index f9bd0fb9f981..000000000000 --- a/include/llvm/Target/TargetJITInfo.h +++ /dev/null @@ -1,137 +0,0 @@ -//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file exposes an abstract interface used by the Just-In-Time code -// generator to perform target-specific activities, such as emitting stubs. If -// a TargetMachine supports JIT code generation, it should provide one of these -// objects through the getJITInfo() method. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETJITINFO_H -#define LLVM_TARGET_TARGETJITINFO_H - -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" -#include <cassert> - -namespace llvm { - class Function; - class GlobalValue; - class JITCodeEmitter; - class MachineRelocation; - - /// TargetJITInfo - Target specific information required by the Just-In-Time - /// code generator. - class TargetJITInfo { - virtual void anchor(); - public: - virtual ~TargetJITInfo() {} - - /// replaceMachineCodeForFunction - Make it so that calling the function - /// whose machine code is at OLD turns into a call to NEW, perhaps by - /// overwriting OLD with a branch to NEW. This is used for self-modifying - /// code. - /// - virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0; - - /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object - /// to emit an indirect symbol which contains the address of the specified - /// ptr. - virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, - JITCodeEmitter &JCE) { - llvm_unreachable("This target doesn't implement " - "emitGlobalValueIndirectSym!"); - } - - /// Records the required size and alignment for a call stub in bytes. - struct StubLayout { - size_t Size; - size_t Alignment; - }; - /// Returns the maximum size and alignment for a call stub on this target. - virtual StubLayout getStubLayout() { - llvm_unreachable("This target doesn't implement getStubLayout!"); - } - - /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a - /// small native function that simply calls the function at the specified - /// address. The JITCodeEmitter must already have storage allocated for the - /// stub. Return the address of the resultant function, which may have been - /// aligned from the address the JCE was set up to emit at. - virtual void *emitFunctionStub(const Function* F, void *Target, - JITCodeEmitter &JCE) { - llvm_unreachable("This target doesn't implement emitFunctionStub!"); - } - - /// getPICJumpTableEntry - Returns the value of the jumptable entry for the - /// specific basic block. - virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase) { - llvm_unreachable("This target doesn't implement getPICJumpTableEntry!"); - } - - /// LazyResolverFn - This typedef is used to represent the function that - /// unresolved call points should invoke. This is a target specific - /// function that knows how to walk the stack and find out which stub the - /// call is coming from. - typedef void (*LazyResolverFn)(); - - /// JITCompilerFn - This typedef is used to represent the JIT function that - /// lazily compiles the function corresponding to a stub. The JIT keeps - /// track of the mapping between stubs and LLVM Functions, the target - /// provides the ability to figure out the address of a stub that is called - /// by the LazyResolverFn. - typedef void* (*JITCompilerFn)(void *); - - /// getLazyResolverFunction - This method is used to initialize the JIT, - /// giving the target the function that should be used to compile a - /// function, and giving the JIT the target function used to do the lazy - /// resolving. - virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) { - llvm_unreachable("Not implemented for this target!"); - } - - /// relocate - Before the JIT can run a block of code that has been emitted, - /// it must rewrite the code to contain the actual addresses of any - /// referenced global symbols. - virtual void relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char* GOTBase) { - assert(NumRelocs == 0 && "This target does not have relocations!"); - } - - - /// allocateThreadLocalMemory - Each target has its own way of - /// handling thread local variables. This method returns a value only - /// meaningful to the target. - virtual char* allocateThreadLocalMemory(size_t size) { - llvm_unreachable("This target does not implement thread local storage!"); - } - - /// needsGOT - Allows a target to specify that it would like the - /// JIT to manage a GOT for it. - bool needsGOT() const { return useGOT; } - - /// hasCustomConstantPool - Allows a target to specify that constant - /// pool address resolution is handled by the target. - virtual bool hasCustomConstantPool() const { return false; } - - /// hasCustomJumpTables - Allows a target to specify that jumptables - /// are emitted by the target. - virtual bool hasCustomJumpTables() const { return false; } - - /// allocateSeparateGVMemory - If true, globals should be placed in - /// separately allocated heap memory rather than in the same - /// code memory allocated by JITCodeEmitter. - virtual bool allocateSeparateGVMemory() const { return false; } - protected: - bool useGOT; - }; -} // End llvm namespace - -#endif diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index d4f9f2330594..46f87b93b001 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -26,10 +26,18 @@ namespace llvm { ZdaPv, /// void operator delete[](void*, nothrow); ZdaPvRKSt9nothrow_t, + /// void operator delete[](void*, unsigned int); + ZdaPvj, + /// void operator delete[](void*, unsigned long); + ZdaPvm, /// void operator delete(void*); ZdlPv, /// void operator delete(void*, nothrow); ZdlPvRKSt9nothrow_t, + /// void operator delete(void*, unsigned int); + ZdlPvj, + /// void operator delete(void*, unsigned long); + ZdlPvm, /// void *new[](unsigned int); Znaj, /// void *new[](unsigned int, nothrow); @@ -54,7 +62,7 @@ namespace llvm { cxa_atexit, /// void __cxa_guard_abort(guard_t *guard); /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. - cxa_guard_abort, + cxa_guard_abort, /// int __cxa_guard_acquire(guard_t *guard); cxa_guard_acquire, /// void __cxa_guard_release(guard_t *guard); @@ -65,6 +73,11 @@ namespace llvm { dunder_isoc99_sscanf, /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); memcpy_chk, + /// void *__memmove_chk(void *s1, const void *s2, size_t n, + /// size_t s1size); + memmove_chk, + /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); + memset_chk, /// double __sincospi_stret(double x); sincospi_stret, /// float __sincospif_stret(float x); @@ -79,8 +92,18 @@ namespace llvm { sqrtf_finite, /// long double __sqrt_finite(long double x); sqrtl_finite, + /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); + stpcpy_chk, + /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + stpncpy_chk, + /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); + strcpy_chk, /// char * __strdup(const char *s); dunder_strdup, + /// char *__strncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + strncpy_chk, /// char *__strndup(const char *s, size_t n); dunder_strndup, /// char * __strtok_r(char *s, const char *delim, char **save_ptr); @@ -696,7 +719,7 @@ public: TargetLibraryInfo(); TargetLibraryInfo(const Triple &T); explicit TargetLibraryInfo(const TargetLibraryInfo &TLI); - + /// getLibFunc - Search for a particular function name. If it is one of the /// known library functions, return true and set F to the corresponding value. bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index ea9a48e2db8a..c5fed02e17b8 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -30,8 +30,9 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" -#include "llvm/IR/InlineAsm.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" @@ -50,6 +51,7 @@ namespace llvm { class MachineFunction; class MachineInstr; class MachineJumpTableInfo; + class MachineLoop; class Mangler; class MCContext; class MCExpr; @@ -136,10 +138,9 @@ public: llvm_unreachable("Invalid content kind"); } - /// NOTE: The constructor takes ownership of TLOF. - explicit TargetLoweringBase(const TargetMachine &TM, - const TargetLoweringObjectFile *TLOF); - virtual ~TargetLoweringBase(); + /// NOTE: The TargetMachine owns TLOF. + explicit TargetLoweringBase(const TargetMachine &TM); + virtual ~TargetLoweringBase() {} protected: /// \brief Initialize all of the actions to default values. @@ -148,7 +149,9 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } const DataLayout *getDataLayout() const { return DL; } - const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } + const TargetLoweringObjectFile &getObjFileLowering() const { + return *TM.getObjFileLowering(); + } bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } @@ -214,6 +217,11 @@ public: /// several shifts, adds, and multiplies for this target. bool isIntDivCheap() const { return IntDivIsCheap; } + /// Return true if sqrt(x) is as cheap or cheaper than 1 / rsqrt(x) + bool isFsqrtCheap() const { + return FsqrtIsCheap; + } + /// Returns true if target has indicated at least one type should be bypassed. bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); } @@ -223,8 +231,8 @@ public: return BypassSlowDivWidths; } - /// Return true if pow2 div is cheaper than a chain of srl/add/sra. - bool isPow2DivCheap() const { return Pow2DivIsCheap; } + /// Return true if pow2 sdiv is cheaper than a chain of sra/srl/add/sra. + bool isPow2SDivCheap() const { return Pow2SDivIsCheap; } /// Return true if Flow Control is an expensive operation that should be /// avoided. @@ -247,6 +255,16 @@ public: return true; } + /// \brief Return true if it is cheap to speculate a call to intrinsic cttz. + virtual bool isCheapToSpeculateCttz() const { + return false; + } + + /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz. + virtual bool isCheapToSpeculateCtlz() const { + return false; + } + /// \brief Return if the target supports combining a /// chain like: /// \code @@ -262,10 +280,32 @@ public: return MaskAndBranchFoldingIsLegal; } - /// Return the ValueType of the result of SETCC operations. Also used to - /// obtain the target's preferred type for the condition operand of SELECT and - /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other - /// since there are no other operands to get a type hint from. + /// \brief Return true if the target wants to use the optimization that + /// turns ext(promotableInst1(...(promotableInstN(load)))) into + /// promotedInst1(...(promotedInstN(ext(load)))). + bool enableExtLdPromotion() const { return EnableExtLdPromotion; } + + /// Return true if the target can combine store(extractelement VectorTy, + /// Idx). + /// \p Cost[out] gives the cost of that transformation when this is true. + virtual bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, + unsigned &Cost) const { + return false; + } + + /// Return true if target supports floating point exceptions. + bool hasFloatingPointExceptions() const { + return HasFloatingPointExceptions; + } + + /// Return true if target always beneficiates from combining into FMA for a + /// given value type. This must typically return false on targets where FMA + /// takes more cycles to execute than FADD. + virtual bool enableAggressiveFMAFusion(EVT VT) const { + return false; + } + + /// Return the ValueType of the result of SETCC operations. virtual EVT getSetCCResultType(LLVMContext &Context, EVT VT) const; /// Return the ValueType for comparison libcalls. Comparions libcalls include @@ -426,10 +466,15 @@ public: EVT memVT; // memory VT const Value* ptrVal; // value representing memory location int offset; // offset off of ptrVal + unsigned size; // the size of the memory location + // (taken from memVT if zero) unsigned align; // alignment bool vol; // is volatile? bool readMem; // reads memory? bool writeMem; // writes memory? + + IntrinsicInfo() : opc(0), ptrVal(nullptr), offset(0), size(0), align(1), + vol(false), readMem(false), writeMem(false) {} }; /// Given an intrinsic, checks if on the target the intrinsic will need to map @@ -517,26 +562,31 @@ public: /// Return how this load with extension should be treated: either it is legal, /// needs to be promoted to a larger size, needs to be expanded to some other /// code sequence, or the target has a custom expander for it. - LegalizeAction getLoadExtAction(unsigned ExtType, MVT VT) const { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && - "Table isn't big enough!"); - return (LegalizeAction)LoadExtActions[VT.SimpleTy][ExtType]; + LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const { + if (ValVT.isExtended() || MemVT.isExtended()) return Expand; + unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; + unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::LAST_VALUETYPE && + MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!"); + return (LegalizeAction)LoadExtActions[ValI][MemI][ExtType]; } /// Return true if the specified load with extension is legal on this target. - bool isLoadExtLegal(unsigned ExtType, EVT VT) const { - return VT.isSimple() && - getLoadExtAction(ExtType, VT.getSimpleVT()) == Legal; + bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const { + return ValVT.isSimple() && MemVT.isSimple() && + getLoadExtAction(ExtType, ValVT, MemVT) == Legal; } /// Return how this store with truncation should be treated: either it is /// legal, needs to be promoted to a larger size, needs to be expanded to some /// other code sequence, or the target has a custom expander for it. - LegalizeAction getTruncStoreAction(MVT ValVT, MVT MemVT) const { - assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && + LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { + if (ValVT.isExtended() || MemVT.isExtended()) return Expand; + unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; + unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; + assert(ValI < MVT::LAST_VALUETYPE && MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)TruncStoreActions[ValVT.SimpleTy] - [MemVT.SimpleTy]; + return (LegalizeAction)TruncStoreActions[ValI][MemI]; } /// Return true if the specified store with truncation is legal on this @@ -551,7 +601,7 @@ public: /// sequence, or the target has a custom expander for it. LegalizeAction getIndexedLoadAction(unsigned IdxMode, MVT VT) const { - assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && + assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() && "Table isn't big enough!"); unsigned Ty = (unsigned)VT.SimpleTy; return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); @@ -569,7 +619,7 @@ public: /// sequence, or the target has a custom expander for it. LegalizeAction getIndexedStoreAction(unsigned IdxMode, MVT VT) const { - assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && + assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() && "Table isn't big enough!"); unsigned Ty = (unsigned)VT.SimpleTy; return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); @@ -725,6 +775,16 @@ public: /// reduce runtime. virtual bool ShouldShrinkFPConstant(EVT) const { return true; } + // Return true if it is profitable to reduce the given load node to a smaller + // type. + // + // e.g. (i16 (trunc (i32 (load x))) -> i16 load x should be performed + virtual bool shouldReduceLoadWidth(SDNode *Load, + ISD::LoadExtType ExtTy, + EVT NewVT) const { + return true; + } + /// When splitting a value of the specified type into parts, does the Lo /// or Hi part come first? This usually follows the endianness, except /// for ppcf128, where the Hi part always comes first. @@ -773,14 +833,15 @@ public: /// /// This function returns true if the target allows unaligned memory accesses /// of the specified type in the given address space. If true, it also returns - /// whether the unaligned memory access is "fast" in the third argument by + /// whether the unaligned memory access is "fast" in the last argument by /// reference. This is used, for example, in situations where an array /// copy/move/set is converted to a sequence of store operations. Its use /// helps to ensure that such replacements don't generate code that causes an /// alignment error (trap) on the target machine. - virtual bool allowsUnalignedMemoryAccesses(EVT, - unsigned AddrSpace = 0, - bool * /*Fast*/ = nullptr) const { + virtual bool allowsMisalignedMemoryAccesses(EVT, + unsigned AddrSpace = 0, + unsigned Align = 1, + bool * /*Fast*/ = nullptr) const { return false; } @@ -823,11 +884,6 @@ public: return UseUnderscoreLongJmp; } - /// Return whether the target can generate code for jump tables. - bool supportJumpTables() const { - return SupportJumpTables; - } - /// Return integer threshold on number of blocks to use jump tables rather /// than if sequence. int getMinimumJumpTableEntries() const { @@ -880,7 +936,7 @@ public: } /// Return the preferred loop alignment. - unsigned getPrefLoopAlignment() const { + virtual unsigned getPrefLoopAlignment(MachineLoop *ML = nullptr) const { return PrefLoopAlignment; } @@ -922,9 +978,13 @@ public: /// @} //===--------------------------------------------------------------------===// - /// \name Helpers for load-linked/store-conditional atomic expansion. + /// \name Helpers for atomic expansion. /// @{ + /// True if AtomicExpandPass should use emitLoadLinked/emitStoreConditional + /// and expand AtomicCmpXchgInst. + virtual bool hasLoadLinkedStoreConditional() const { return false; } + /// Perform a load-linked operation on Addr, returning a "Value *" with the /// corresponding pointee type. This may entail some non-trivial operations to /// truncate or reconstruct types that will be illegal in the backend. See @@ -941,15 +1001,90 @@ public: llvm_unreachable("Store conditional unimplemented on this target"); } - /// Return true if the given (atomic) instruction should be expanded by the - /// IR-level AtomicExpandLoadLinked pass into a loop involving - /// load-linked/store-conditional pairs. Atomic stores will be expanded in the - /// same way as "atomic xchg" operations which ignore their output if needed. - virtual bool shouldExpandAtomicInIR(Instruction *Inst) const { + /// Inserts in the IR a target-specific intrinsic specifying a fence. + /// It is called by AtomicExpandPass before expanding an + /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad. + /// RMW and CmpXchg set both IsStore and IsLoad to true. + /// This function should either return a nullptr, or a pointer to an IR-level + /// Instruction*. Even complex fence sequences can be represented by a + /// single Instruction* through an intrinsic to be lowered later. + /// Backends with !getInsertFencesForAtomic() should keep a no-op here. + /// Backends should override this method to produce target-specific intrinsic + /// for their fences. + /// FIXME: Please note that the default implementation here in terms of + /// IR-level fences exists for historical/compatibility reasons and is + /// *unsound* ! Fences cannot, in general, be used to restore sequential + /// consistency. For example, consider the following example: + /// atomic<int> x = y = 0; + /// int r1, r2, r3, r4; + /// Thread 0: + /// x.store(1); + /// Thread 1: + /// y.store(1); + /// Thread 2: + /// r1 = x.load(); + /// r2 = y.load(); + /// Thread 3: + /// r3 = y.load(); + /// r4 = x.load(); + /// r1 = r3 = 1 and r2 = r4 = 0 is impossible as long as the accesses are all + /// seq_cst. But if they are lowered to monotonic accesses, no amount of + /// IR-level fences can prevent it. + /// @{ + virtual Instruction* emitLeadingFence(IRBuilder<> &Builder, AtomicOrdering Ord, + bool IsStore, bool IsLoad) const { + if (!getInsertFencesForAtomic()) + return nullptr; + + if (isAtLeastRelease(Ord) && IsStore) + return Builder.CreateFence(Ord); + else + return nullptr; + } + + virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord, + bool IsStore, bool IsLoad) const { + if (!getInsertFencesForAtomic()) + return nullptr; + + if (isAtLeastAcquire(Ord)) + return Builder.CreateFence(Ord); + else + return nullptr; + } + /// @} + + /// Returns true if the given (atomic) store should be expanded by the + /// IR-level AtomicExpand pass into an "atomic xchg" which ignores its input. + virtual bool shouldExpandAtomicStoreInIR(StoreInst *SI) const { return false; } + /// Returns true if the given (atomic) load should be expanded by the + /// IR-level AtomicExpand pass into a load-linked instruction + /// (through emitLoadLinked()). + virtual bool shouldExpandAtomicLoadInIR(LoadInst *LI) const { return false; } + /// Returns true if the given AtomicRMW should be expanded by the + /// IR-level AtomicExpand pass into a loop using LoadLinked/StoreConditional. + virtual bool shouldExpandAtomicRMWInIR(AtomicRMWInst *RMWI) const { + return false; + } + + /// On some platforms, an AtomicRMW that never actually modifies the value + /// (such as fetch_add of 0) can be turned into a fence followed by an + /// atomic load. This may sound useless, but it makes it possible for the + /// processor to keep the cacheline shared, dramatically improving + /// performance. And such idempotent RMWs are useful for implementing some + /// kinds of locks, see for example (justification + benchmarks): + /// http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf + /// This method tries doing that transformation, returning the atomic load if + /// it succeeds, and nullptr otherwise. + /// If shouldExpandAtomicLoadInIR returns true on that load, it will undergo + /// another round of expansion. + virtual LoadInst *lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { + return nullptr; + } //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. @@ -996,11 +1131,6 @@ protected: UseUnderscoreLongJmp = Val; } - /// Indicate whether the target can generate code for jump tables. - void setSupportJumpTables(bool Val) { - SupportJumpTables = Val; - } - /// Indicate the number of blocks to generate jump tables rather than if /// sequence. void setMinimumJumpTableEntries(int Val) { @@ -1059,14 +1189,24 @@ protected: /// containing an integer divide. void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } + /// Tells the code generator that fsqrt is cheap, and should not be replaced + /// with an alternative sequence of instructions. + void setFsqrtIsCheap(bool isCheap = true) { FsqrtIsCheap = isCheap; } + + /// Tells the code generator that this target supports floating point + /// exceptions and cares about preserving floating point exception behavior. + void setHasFloatingPointExceptions(bool FPExceptions = true) { + HasFloatingPointExceptions = FPExceptions; + } + /// Tells the code generator which bitwidths to bypass. void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; } - /// Tells the code generator that it shouldn't generate srl/add/sra for a - /// signed divide by power of two, and let the target handle it. - void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; } + /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a + /// signed divide by power of two; let the target handle it. + void setPow2SDivIsCheap(bool isCheap = true) { Pow2SDivIsCheap = isCheap; } /// Add the specified register class as an available regclass for the /// specified value type. This indicates the selector can handle values of @@ -1107,19 +1247,18 @@ protected: /// Indicate that the specified load with extension does not work with the /// specified type and indicate what to do about it. - void setLoadExtAction(unsigned ExtType, MVT VT, + void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action) { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && - "Table isn't big enough!"); - LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action; + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() && + MemVT.isValid() && "Table isn't big enough!"); + LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy][ExtType] = (uint8_t)Action; } /// Indicate that the specified truncating store does not work with the /// specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { - assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && - "Table isn't big enough!"); + assert(ValVT.isValid() && MemVT.isValid() && "Table isn't big enough!"); TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action; } @@ -1130,7 +1269,7 @@ protected: /// TargetLowering.cpp void setIndexedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE && (unsigned)Action < 0xf && "Table isn't big enough!"); // Load action are kept in the upper half. IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0; @@ -1144,7 +1283,7 @@ protected: /// TargetLowering.cpp void setIndexedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE && (unsigned)Action < 0xf && "Table isn't big enough!"); // Store action are kept in the lower half. IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f; @@ -1155,8 +1294,7 @@ protected: /// target and indicate what to do about it. void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action) { - assert(VT < MVT::LAST_VALUETYPE && - (unsigned)CC < array_lengthof(CondCodeActions) && + assert(VT.isValid() && (unsigned)CC < array_lengthof(CondCodeActions) && "Table isn't big enough!"); /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 32-bit /// value and the upper 27 bits index into the second dimension of the array @@ -1207,7 +1345,8 @@ protected: /// Set the target's preferred loop alignment. Default alignment is zero, it /// means the target does not care about loop alignment. The alignment is - /// specified in log2(bytes). + /// specified in log2(bytes). The target may also override + /// getPrefLoopAlignment to provide per-loop values. void setPrefLoopAlignment(unsigned Align) { PrefLoopAlignment = Align; } @@ -1370,6 +1509,14 @@ public: return isZExtFree(Val.getValueType(), VT2); } + /// Return true if an fpext operation is free (for instance, because + /// single-precision floating-point numbers are implicitly extended to + /// double-precision). + virtual bool isFPExtFree(EVT VT) const { + assert(VT.isFloatingPoint()); + return false; + } + /// Return true if an fneg operation is free to the point where it is never /// worthwhile to replace it with a bitwise operation. virtual bool isFNegFree(EVT VT) const { @@ -1412,6 +1559,15 @@ public: Type *Ty) const { return false; } + + /// Return true if EXTRACT_SUBVECTOR is cheap for this result type + /// with this index. This is needed because EXTRACT_SUBVECTOR usually + /// has custom lowering that depends on the index of the first element, + /// and only the target knows which lowering is cheap. + virtual bool isExtractSubvectorCheap(EVT ResVT, unsigned Index) const { + return false; + } + //===--------------------------------------------------------------------===// // Runtime Library hooks // @@ -1451,7 +1607,6 @@ public: private: const TargetMachine &TM; const DataLayout *DL; - const TargetLoweringObjectFile &TLOF; /// True if this is a little endian target. bool IsLittleEndian; @@ -1479,21 +1634,28 @@ private: /// unconditionally. bool IntDivIsCheap; + // Don't expand fsqrt with an approximation based on the inverse sqrt. + bool FsqrtIsCheap; + /// Tells the code generator to bypass slow divide or remainder /// instructions. For example, BypassSlowDivWidths[32,8] tells the code /// generator to bypass 32-bit integer div/rem with an 8-bit unsigned integer /// div/rem when the operands are positive and less than 256. DenseMap <unsigned int, unsigned int> BypassSlowDivWidths; - /// Tells the code generator that it shouldn't generate srl/add/sra for a - /// signed divide by power of two, and let the target handle it. - bool Pow2DivIsCheap; + /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a + /// signed divide by power of two; let the target handle it. + bool Pow2SDivIsCheap; /// Tells the code generator that it shouldn't generate extra flow control /// instructions and should attempt to combine flow control instructions via /// predication. bool JumpIsExpensive; + /// Whether the target supports or cares about preserving floating point + /// exception behavior. + bool HasFloatingPointExceptions; + /// This target prefers to use _setjmp to implement llvm.setjmp. /// /// Defaults to false. @@ -1504,10 +1666,6 @@ private: /// Defaults to false. bool UseUnderscoreLongJmp; - /// Whether the target can generate code for jumptables. If it's not true, - /// then each jumptable must be lowered into if-then-else's. - bool SupportJumpTables; - /// Number of blocks threshold to use jump tables. int MinimumJumpTableEntries; @@ -1600,7 +1758,8 @@ private: /// For each load extension type and each value type, keep a LegalizeAction /// that indicates how instruction selection should deal with a load of a /// specific value type and extension type. - uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE]; + uint8_t LoadExtActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE] + [ISD::LAST_LOADEXT_TYPE]; /// For each value type pair keep a LegalizeAction that indicates whether a /// truncating store of a specific value type and truncating type is legal. @@ -1841,6 +2000,9 @@ protected: /// a mask of a single bit, a compare, and a branch into a single instruction. bool MaskAndBranchFoldingIsLegal; + /// \see enableExtLdPromotion. + bool EnableExtLdPromotion; + protected: /// Return true if the value types that can be represented by the specified /// register class are all legal. @@ -1861,9 +2023,8 @@ class TargetLowering : public TargetLoweringBase { void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; public: - /// NOTE: The constructor takes ownership of TLOF. - explicit TargetLowering(const TargetMachine &TM, - const TargetLoweringObjectFile *TLOF); + /// NOTE: The TargetMachine owns TLOF. + explicit TargetLowering(const TargetMachine &TM); /// Returns true by value, base pointer and offset pointer and addressing mode /// by reference if the node's address can be legally represented as @@ -2150,6 +2311,7 @@ public: SelectionDAG &DAG; SDLoc DL; ImmutableCallSite *CS; + bool IsPatchPoint; SmallVector<ISD::OutputArg, 32> Outs; SmallVector<SDValue, 32> OutVals; SmallVector<ISD::InputArg, 32> Ins; @@ -2158,7 +2320,7 @@ public: : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - DAG(DAG), CS(nullptr) {} + DAG(DAG), CS(nullptr), IsPatchPoint(false) {} CallLoweringInfo &setDebugLoc(SDLoc dl) { DL = dl; @@ -2240,6 +2402,11 @@ public: return *this; } + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; + } + ArgListTy &getArgs() { return Args; } @@ -2324,9 +2491,9 @@ public: /// all the time, e.g. i1 on x86-64. It is also not necessary for non-C /// calling conventions. The frontend should handle this and include all of /// the necessary information. - virtual MVT getTypeForExtArgOrReturn(MVT VT, + virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, ISD::NodeType /*ExtendKind*/) const { - MVT MinVT = getRegisterType(MVT::i32); + EVT MinVT = getRegisterType(Context, MVT::i32); return VT.bitsLT(MinVT) ? MinVT : VT; } @@ -2474,11 +2641,10 @@ public: unsigned getMatchedOperand() const; /// Copy constructor for copying from a ConstraintInfo. - AsmOperandInfo(const InlineAsm::ConstraintInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintType(TargetLowering::C_Unknown), - CallOperandVal(nullptr), ConstraintVT(MVT::Other) { - } + AsmOperandInfo(InlineAsm::ConstraintInfo Info) + : InlineAsm::ConstraintInfo(std::move(Info)), + ConstraintType(TargetLowering::C_Unknown), CallOperandVal(nullptr), + ConstraintVT(MVT::Other) {} }; typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; @@ -2545,6 +2711,51 @@ public: SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, bool IsAfterLegalization, std::vector<SDNode *> *Created) const; + virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, + SelectionDAG &DAG, + std::vector<SDNode *> *Created) const { + return SDValue(); + } + + /// Indicate whether this target prefers to combine the given number of FDIVs + /// with the same divisor. + virtual bool combineRepeatedFPDivisors(unsigned NumUsers) const { + return false; + } + + /// Hooks for building estimates in place of slower divisions and square + /// roots. + + /// Return a reciprocal square root estimate value for the input operand. + /// The RefinementSteps output is the number of Newton-Raphson refinement + /// iterations required to generate a sufficient (though not necessarily + /// IEEE-754 compliant) estimate for the value type. + /// The boolean UseOneConstNR output is used to select a Newton-Raphson + /// algorithm implementation that uses one constant or two constants. + /// A target may choose to implement its own refinement within this function. + /// If that's true, then return '0' as the number of RefinementSteps to avoid + /// any further refinement of the estimate. + /// An empty SDValue return means no estimate sequence can be created. + virtual SDValue getRsqrtEstimate(SDValue Operand, + DAGCombinerInfo &DCI, + unsigned &RefinementSteps, + bool &UseOneConstNR) const { + return SDValue(); + } + + /// Return a reciprocal estimate value for the input operand. + /// The RefinementSteps output is the number of Newton-Raphson refinement + /// iterations required to generate a sufficient (though not necessarily + /// IEEE-754 compliant) estimate for the value type. + /// A target may choose to implement its own refinement within this function. + /// If that's true, then return '0' as the number of RefinementSteps to avoid + /// any further refinement of the estimate. + /// An empty SDValue return means no estimate sequence can be created. + virtual SDValue getRecipEstimate(SDValue Operand, + DAGCombinerInfo &DCI, + unsigned &RefinementSteps) const { + return SDValue(); + } //===--------------------------------------------------------------------===// // Legalization utility functions @@ -2589,6 +2800,12 @@ public: /// ARM 's' setting instructions. virtual void AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; + + /// If this function returns true, SelectionDAGBuilder emits a + /// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector. + virtual bool useLoadStackGuardNode() const { + return false; + } }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 7c32a5e3d0ca..73bf56f018e9 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -151,16 +151,10 @@ public: return nullptr; } - /// \brief True if the section is atomized using the symbols in it. - /// This is false if the section is not atomized at all (most ELF sections) or - /// if it is atomized based on its contents (MachO' __TEXT,__cstring for - /// example). - virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; - protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler &Mang, const TargetMachine &TM) const; + Mangler &Mang, const TargetMachine &TM) const = 0; }; } // end namespace llvm diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index b263c571d9e6..a4f95c061283 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -24,7 +24,6 @@ namespace llvm { class InstrItineraryData; -class JITCodeEmitter; class GlobalValue; class Mangler; class MCAsmInfo; @@ -35,9 +34,7 @@ class Target; class DataLayout; class TargetLibraryInfo; class TargetFrameLowering; -class TargetInstrInfo; class TargetIntrinsicInfo; -class TargetJITInfo; class TargetLowering; class TargetPassConfig; class TargetRegisterInfo; @@ -47,6 +44,7 @@ class ScalarTargetTransformInfo; class VectorTargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -87,47 +85,27 @@ protected: // Can only create subclasses. unsigned RequireStructuredCFG : 1; public: + mutable TargetOptions Options; + virtual ~TargetMachine(); const Target &getTarget() const { return TheTarget; } - const StringRef getTargetTriple() const { return TargetTriple; } - const StringRef getTargetCPU() const { return TargetCPU; } - const StringRef getTargetFeatureString() const { return TargetFS; } + StringRef getTargetTriple() const { return TargetTriple; } + StringRef getTargetCPU() const { return TargetCPU; } + StringRef getTargetFeatureString() const { return TargetFS; } /// getSubtargetImpl - virtual method implemented by subclasses that returns /// a reference to that target's TargetSubtargetInfo-derived member variable. virtual const TargetSubtargetInfo *getSubtargetImpl() const { return nullptr; } - - mutable TargetOptions Options; - - /// \brief Reset the target options based on the function's attributes. - void resetTargetOptions(const MachineFunction *MF) const; - - // Interfaces to the major aspects of target machine information: - // - // -- Instruction opcode and operand information - // -- Pipelines and scheduling information - // -- Stack frame information - // -- Selection DAG lowering information - // - // N.B. These objects may change during compilation. It's not safe to cache - // them between functions. - virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } - virtual const TargetFrameLowering *getFrameLowering() const { - return nullptr; + virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { + return getSubtargetImpl(); } - virtual const TargetLowering *getTargetLowering() const { return nullptr; } - virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { + virtual TargetLoweringObjectFile *getObjFileLowering() const { return nullptr; } - virtual const DataLayout *getDataLayout() const { return nullptr; } - - /// getMCAsmInfo - Return target specific asm information. - /// - const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } /// getSubtarget - This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being @@ -135,27 +113,23 @@ public: template<typename STC> const STC &getSubtarget() const { return *static_cast<const STC*>(getSubtargetImpl()); } + template <typename STC> const STC &getSubtarget(const Function *) const { + return *static_cast<const STC*>(getSubtargetImpl()); + } + + /// \brief Reset the target options based on the function's attributes. + // FIXME: Remove TargetOptions that affect per-function code generation + // from TargetMachine. + void resetTargetOptions(const Function &F) const; - /// getRegisterInfo - If register information is available, return it. If - /// not, return null. This is kept separate from RegInfo until RegInfo has - /// details of graph coloring register allocation removed from it. + /// getMCAsmInfo - Return target specific asm information. /// - virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } + const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } /// getIntrinsicInfo - If intrinsic information is available, return it. If /// not, return null. /// - virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr;} - - /// getJITInfo - If this target supports a JIT, return information for it, - /// otherwise return null. - /// - virtual TargetJITInfo *getJITInfo() { return nullptr; } - - /// getInstrItineraryData - Returns instruction itinerary data for the target - /// or specific subtarget. - /// - virtual const InstrItineraryData *getInstrItineraryData() const { + virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr; } @@ -233,18 +207,6 @@ public: return true; } - /// addPassesToEmitMachineCode - Add passes to the specified pass manager to - /// get machine code emitted. This uses a JITCodeEmitter object to handle - /// actually outputting the machine code and resolving things like the address - /// of functions. This method returns true if machine code emission is - /// not supported. - /// - virtual bool addPassesToEmitMachineCode(PassManagerBase &, - JITCodeEmitter &, - bool /*DisableVerify*/ = true) { - return true; - } - /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be @@ -291,15 +253,6 @@ public: AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) override; - /// addPassesToEmitMachineCode - Add passes to the specified pass manager to - /// get machine code emitted. This uses a JITCodeEmitter object to handle - /// actually outputting the machine code and resolving things like the address - /// of functions. This method returns true if machine code emission is - /// not supported. - /// - bool addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &MCE, - bool DisableVerify = true) override; - /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be @@ -307,14 +260,6 @@ public: /// bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, raw_ostream &OS, bool DisableVerify = true) override; - - /// addCodeEmitter - This pass should be overridden by the target to add a - /// code emitter, if supported. If this is not supported, 'true' should be - /// returned. - virtual bool addCodeEmitter(PassManagerBase &, - JITCodeEmitter &) { - return true; - } }; } // End llvm namespace diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index abb3ecacaefd..afc22365eba7 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -104,7 +104,24 @@ enum { /// support optimizations for dynamic languages (such as javascript) that /// rewrite calls to runtimes with more efficient code sequences. /// This also implies a stack map. - PATCHPOINT = 18 + PATCHPOINT = 18, + + /// This pseudo-instruction loads the stack guard value. Targets which need + /// to prevent the stack guard value or address from being spilled to the + /// stack should override TargetLowering::emitLoadStackGuardNode and + /// additionally expand this pseudo after register allocation. + LOAD_STACK_GUARD = 19, + + /// Call instruction with associated vm state for deoptimization and list + /// of live pointers for relocation by the garbage collector. It is + /// intended to support garbage collection with fully precise relocating + /// collectors and deoptimizations in either the callee or caller. + STATEPOINT = 20, + + /// Instruction that records the offset of a function's frame allocation in a + /// label. Created by the llvm.frameallocate intrinsic. It has two arguments: + /// the symbol for the label and the frame index of the stack allocation. + FRAME_ALLOC = 21, }; } // end namespace TargetOpcode } // end namespace llvm diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 922fae54bb80..9ab8242578fd 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -50,6 +50,21 @@ namespace llvm { }; } + namespace ThreadModel { + enum Model { + POSIX, // POSIX Threads + Single // Single Threaded Environment + }; + } + + enum class CFIntegrity { + Sub, // Use subtraction-based checks. + Ror, // Use rotation-based checks. + Add // Use addition-based checks. This depends on having + // sufficient alignment in the code and is usually not + // feasible. + }; + class TargetOptions { public: TargetOptions() @@ -63,9 +78,11 @@ namespace llvm { EnableFastISel(false), PositionIndependentExecutable(false), UseInitArray(false), DisableIntegratedAS(false), CompressDebugSections(false), FunctionSections(false), - DataSections(false), TrapUnreachable(false), TrapFuncName(""), + DataSections(false), TrapUnreachable(false), TrapFuncName(), FloatABIType(FloatABI::Default), - AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {} + AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), + FCFI(false), ThreadModel(ThreadModel::POSIX), + CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -220,6 +237,28 @@ namespace llvm { /// create for functions that have the jumptable attribute. JumpTable::JumpTableType JTType; + /// FCFI - This flags controls whether or not forward-edge control-flow + /// integrity is applied. + bool FCFI; + + /// ThreadModel - This flag specifies the type of threading model to assume + /// for things like atomics + ThreadModel::Model ThreadModel; + + /// CFIType - This flag specifies the type of control-flow integrity check + /// to add as a preamble to indirect calls. + CFIntegrity CFIType; + + /// CFIEnforcing - This flags controls whether or not CFI violations cause + /// the program to halt. + bool CFIEnforcing; + + /// getCFIFuncName - If this returns a non-empty string, then this is the + /// name of the function that will be called for each CFI violation in + /// non-enforcing mode. + std::string CFIFuncName; + StringRef getCFIFuncName() const; + /// Machine level options. MCTargetOptions MCOptions; }; @@ -249,6 +288,12 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(TrapFuncName) && ARE_EQUAL(FloatABIType) && ARE_EQUAL(AllowFPOpFusion) && + ARE_EQUAL(JTType) && + ARE_EQUAL(FCFI) && + ARE_EQUAL(ThreadModel) && + ARE_EQUAL(CFIType) && + ARE_EQUAL(CFIEnforcing) && + ARE_EQUAL(CFIFuncName) && ARE_EQUAL(MCOptions); #undef ARE_EQUAL } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 5dda8bd4b938..a7552565c938 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -18,7 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/IR/CallingConv.h" #include "llvm/MC/MCRegisterInfo.h" #include <cassert> @@ -45,6 +45,7 @@ public: const vt_iterator VTs; const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; + const unsigned LaneMask; const sc_iterator SuperClasses; ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&); @@ -52,10 +53,6 @@ public: /// unsigned getID() const { return MC->getID(); } - /// getName() - Return the register class name for debugging. - /// - const char *getName() const { return MC->getName(); } - /// begin/end - Return all of the registers in this class. /// iterator begin() const { return MC->begin(); } @@ -101,9 +98,9 @@ public: /// hasType - return true if this TargetRegisterClass has the ValueType vt. /// - bool hasType(EVT vt) const { + bool hasType(MVT vt) const { for(int i = 0; VTs[i] != MVT::Other; ++i) - if (EVT(VTs[i]) == vt) + if (MVT(VTs[i]) == vt) return true; return false; } @@ -194,6 +191,13 @@ public: ArrayRef<MCPhysReg> getRawAllocationOrder(const MachineFunction &MF) const { return OrderFunc ? OrderFunc(MF) : makeArrayRef(begin(), getNumRegs()); } + + /// Returns the combination of all lane masks of register in this class. + /// The lane masks of the registers are the combination of all lane masks + /// of their subregisters. + unsigned getLaneMask() const { + return LaneMask; + } }; /// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about @@ -306,7 +310,7 @@ public: /// register of the given type, picking the most sub register class of /// the right type that contains this physreg. const TargetRegisterClass * - getMinimalPhysRegClass(unsigned Reg, EVT VT = MVT::Other) const; + getMinimalPhysRegClass(unsigned Reg, MVT VT = MVT::Other) const; /// getAllocatableClass - Return the maximal subclass of the given register /// class that is alloctable, or NULL. @@ -452,6 +456,11 @@ public: /// used by register scavenger to determine what registers are free. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + /// Prior to adding the live-out mask to a stackmap or patchpoint + /// instruction, provide the target the opportunity to adjust it (mainly to + /// remove pseudo-registers that should be ignored). + virtual void adjustStackMapLiveOutMask(uint32_t *Mask) const { } + /// getMatchingSuperReg - Return a super-register of the specified register /// Reg so its sub-register of index SubIdx is Reg. unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, @@ -506,12 +515,31 @@ public: return composeSubRegIndicesImpl(a, b); } + /// Transforms a LaneMask computed for one subregister to the lanemask that + /// would have been computed when composing the subsubregisters with IdxA + /// first. @sa composeSubRegIndices() + unsigned composeSubRegIndexLaneMask(unsigned IdxA, unsigned LaneMask) const { + if (!IdxA) + return LaneMask; + return composeSubRegIndexLaneMaskImpl(IdxA, LaneMask); + } + + /// Debugging helper: dump register in human readable form to dbgs() stream. + static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0, + const TargetRegisterInfo* TRI = nullptr); + protected: /// Overridden by TableGen in targets that have sub-registers. virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const { llvm_unreachable("Target has no sub-registers"); } + /// Overridden by TableGen in targets that have sub-registers. + virtual unsigned + composeSubRegIndexLaneMaskImpl(unsigned, unsigned) const { + llvm_unreachable("Target has no sub-registers"); + } + public: /// getCommonSuperRegClass - Find a common super-register class if it exists. /// @@ -561,6 +589,11 @@ public: return RegClassBegin[i]; } + /// getRegClassName - Returns the name of the register class. + const char *getRegClassName(const TargetRegisterClass *Class) const { + return MCRegisterInfo::getRegClassName(Class->MC); + } + /// getCommonSubClass - find the largest common subclass of A and B. Return /// NULL if there is no common subclass. const TargetRegisterClass * @@ -683,12 +716,6 @@ public: /// (3) Bottom-up allocation is no longer guaranteed to optimally color. virtual bool reverseLocalAssignment() const { return false; } - /// Allow the target to override register assignment heuristics based on the - /// live range size. If this returns false, then local live ranges are always - /// assigned in order regardless of their size. This is a temporary hook for - /// debugging downstream codegen failures exposed by regalloc. - virtual bool mayOverrideLocalAssignment() const { return true; } - /// Allow the target to override the cost of using a callee-saved register for /// the first time. Default value of 0 means we will use a callee-saved /// register if it is available. diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 2d822de4ad69..907baa1b9b1f 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -162,6 +162,10 @@ def SDTBr : SDTypeProfile<0, 1, [ // br SDTCisVT<0, OtherVT> ]>; +def SDTBrCC : SDTypeProfile<0, 4, [ // brcc + SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + def SDTBrcond : SDTypeProfile<0, 2, [ // brcond SDTCisInt<0>, SDTCisVT<1, OtherVT> ]>; @@ -184,6 +188,14 @@ def SDTIStore : SDTypeProfile<1, 3, [ // indexed store SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> ]>; +def SDTMaskedStore: SDTypeProfile<0, 3, [ // masked store + SDTCisPtrTy<0>, SDTCisVec<1>, SDTCisVec<2> +]>; + +def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load + SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3> +]>; + def SDTVecShuffle : SDTypeProfile<1, 2, [ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> ]>; @@ -369,6 +381,8 @@ def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; +def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>; +def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>; def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>; def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; @@ -400,6 +414,7 @@ def select : SDNode<"ISD::SELECT" , SDTSelect>; def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; +def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; @@ -447,6 +462,11 @@ def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; + // Do not use ld, st directly. Use load, extload, sextload, zextload, store, // and truncst (see below). def ld : SDNode<"ISD::LOAD" , SDTLoad, diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index 78a2db183fb1..d1a3fcf4a50e 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -46,7 +46,7 @@ public: /// more efficient than using a library call. This function can return a null /// SDValue if the target declines to use custom code and a different /// lowering strategy should be used. - /// + /// /// If AlwaysInline is true, the size is constant and the target should not /// emit any calls and is strongly encouraged to attempt to emit inline code /// even if it is beyond the usual threshold because this intrinsic is being diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 86e303e18348..4ff88d07bf27 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -14,17 +14,24 @@ #ifndef LLVM_TARGET_TARGETSUBTARGETINFO_H #define LLVM_TARGET_TARGETSUBTARGETINFO_H +#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/CodeGen.h" namespace llvm { +class DataLayout; class MachineFunction; class MachineInstr; class SDep; class SUnit; +class TargetFrameLowering; +class TargetInstrInfo; +class TargetLowering; class TargetRegisterClass; +class TargetRegisterInfo; class TargetSchedModel; +class TargetSelectionDAGInfo; struct MachineSchedPolicy; template <typename T> class SmallVectorImpl; @@ -47,6 +54,38 @@ public: virtual ~TargetSubtargetInfo(); + // Interfaces to the major aspects of target machine information: + // + // -- Instruction opcode and operand information + // -- Pipelines and scheduling information + // -- Stack frame information + // -- Selection DAG lowering information + // + // N.B. These objects may change during compilation. It's not safe to cache + // them between functions. + virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } + virtual const TargetFrameLowering *getFrameLowering() const { + return nullptr; + } + virtual const TargetLowering *getTargetLowering() const { return nullptr; } + virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { + return nullptr; + } + virtual const DataLayout *getDataLayout() const { return nullptr; } + + /// getRegisterInfo - If register information is available, return it. If + /// not, return null. This is kept separate from RegInfo until RegInfo has + /// details of graph coloring register allocation removed from it. + /// + virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } + + /// getInstrItineraryData - Returns instruction itinerary data for the target + /// or specific subtarget. + /// + virtual const InstrItineraryData *getInstrItineraryData() const { + return nullptr; + } + /// Resolve a SchedClass at runtime, where SchedClass identifies an /// MCSchedClassDesc with the isVariant property. This may return the ID of /// another variant SchedClass, but repeated invocation must quickly terminate @@ -74,7 +113,7 @@ public: virtual bool enablePostMachineScheduler() const; /// \brief True if the subtarget should run the atomic expansion pass. - virtual bool enableAtomicExpandLoadLinked() const; + virtual bool enableAtomicExpand() const; /// \brief Override generic scheduling policy within a region. /// @@ -90,26 +129,26 @@ public: // dependency. virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } - + // For use with PostRAScheduling: get the anti-dependence breaking that should // be performed before post-RA scheduling. virtual AntiDepBreakMode getAntiDepBreakMode() const { return ANTIDEP_NONE; } - + // For use with PostRAScheduling: in CriticalPathRCs, return any register // classes that should only be considered for anti-dependence breaking if they // are on the critical path. virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { return CriticalPathRCs.clear(); } - + // For use with PostRAScheduling: get the minimum optimization level needed // to enable post-RA scheduling. virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { return CodeGenOpt::Default; } - + /// \brief True if the subtarget should run the local reassignment /// heuristic of the register allocator. /// This heuristic may be compile time intensive, \p OptLevel provides @@ -123,9 +162,17 @@ public: /// \brief Enable the use of the early if conversion pass. virtual bool enableEarlyIfConversion() const { return false; } - /// \brief Reset the features for the subtarget. - virtual void resetSubtargetFeatures(const MachineFunction *MF) { } + /// \brief Return PBQPConstraint(s) for the target. + /// + /// Override to provide custom PBQP constraints. + virtual std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const { + return nullptr; + } + /// Enable tracking of subregister liveness in register allocator. + virtual bool enableSubRegLiveness() const { + return false; + } }; } // End llvm namespace diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 50877d013702..b1426b4f45ca 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -18,16 +18,17 @@ #include <vector> namespace llvm { -class TargetLibraryInfo; class Pass; +class TargetLibraryInfo; +class TargetMachine; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { -class PassManagerBase; class FunctionPassManager; +class PassManagerBase; } -using legacy::PassManagerBase; using legacy::FunctionPassManager; +using legacy::PassManagerBase; /// PassManagerBuilder - This class is used to set up a standard optimization /// sequence for languages like C and C++, allowing some APIs to customize the @@ -118,6 +119,11 @@ public: bool LoopVectorize; bool RerollLoops; bool LoadCombine; + bool DisableGVNLoadPRE; + bool VerifyInput; + bool VerifyOutput; + bool StripDebug; + bool MergeFunctions; private: /// ExtensionList - This is list of all of the extensions that are registered. @@ -135,6 +141,7 @@ public: private: void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const; void addInitialAliasAnalysisPasses(PassManagerBase &PM) const; + void addLTOOptimizationPasses(PassManagerBase &PM); public: /// populateFunctionPassManager - This fills in the function pass manager, @@ -144,8 +151,7 @@ public: /// populateModulePassManager - This sets up the primary pass manager. void populateModulePassManager(PassManagerBase &MPM); - void populateLTOPassManager(PassManagerBase &PM, bool Internalize, - bool RunInliner, bool DisableGVNLoadPRE = false); + void populateLTOPassManager(PassManagerBase &PM, TargetMachine *TM = nullptr); }; /// Registers a function for adding a standard set of passes. This should be diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index c6a339b0fd22..24e3ef783ee6 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -63,6 +63,18 @@ struct GCOVOptions { ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()); +/// Options for the frontend instrumentation based profiling pass. +struct InstrProfOptions { + InstrProfOptions() : NoRedZone(false) {} + + // Add the 'noredzone' attribute to added runtime library calls. + bool NoRedZone; +}; + +/// Insert frontend instrumentation based profiling. +ModulePass *createInstrProfilingPass( + const InstrProfOptions &Options = InstrProfOptions()); + // Insert AddressSanitizer (address sanity checking) instrumentation FunctionPass *createAddressSanitizerFunctionPass(); ModulePass *createAddressSanitizerModulePass(); @@ -78,6 +90,9 @@ ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(), void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr); +// Insert SanitizerCoverage instrumentation. +ModulePass *createSanitizerCoverageModulePass(int CoverageLevel); + #if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID) inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile = StringRef()) { @@ -90,37 +105,6 @@ inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile = // checking on loads, stores, and other memory intrinsics. FunctionPass *createBoundsCheckingPass(); -/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB (or -/// GDB) and generate a file with the LLVM IR to be -/// displayed in the debugger. -/// -/// Existing debug metadata is preserved (but may be modified) in order to allow -/// accessing variables in the original source. The line table and file -/// information is modified to correspond to the lines in the LLVM IR. If -/// Filename and Directory are empty, a file name is generated based on existing -/// debug information. If no debug information is available, a temporary file -/// name is generated. -/// -/// @param HideDebugIntrinsics Omit debug intrinsics in emitted IR source file. -/// @param HideDebugMetadata Omit debug metadata in emitted IR source file. -/// @param Directory Embed this directory in the debug information. -/// @param Filename Embed this file name in the debug information. -ModulePass *createDebugIRPass(bool HideDebugIntrinsics, - bool HideDebugMetadata, - StringRef Directory = StringRef(), - StringRef Filename = StringRef()); - -/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB -/// (or GDB) with an existing IR file on disk. When creating -/// a DebugIR pass with this function, no source file is -/// output to disk and the existing one is unmodified. Debug -/// metadata in the Module is created/updated to point to -/// the existing textual IR file on disk. -/// NOTE: If the IR file to be debugged is not on disk, use the version of this -/// function with parameters in order to generate the file that will be -/// seen by the debugger. -ModulePass *createDebugIRPass(); - } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 413134e51c7a..5dcd89948759 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -36,6 +36,13 @@ FunctionPass *createConstantPropagationPass(); //===----------------------------------------------------------------------===// // +// AlignmentFromAssumptions - Use assume intrinsics to set load/store +// alignments. +// +FunctionPass *createAlignmentFromAssumptionsPass(); + +//===----------------------------------------------------------------------===// +// // SCCP - Sparse conditional constant propagation. // FunctionPass *createSCCPPass(); @@ -199,16 +206,17 @@ FunctionPass *createReassociatePass(); //===----------------------------------------------------------------------===// // // JumpThreading - Thread control through mult-pred/multi-succ blocks where some -// preds always go to some succ. +// preds always go to some succ. Thresholds other than minus one override the +// internal BB duplication default threshold. // -FunctionPass *createJumpThreadingPass(); +FunctionPass *createJumpThreadingPass(int Threshold = -1); //===----------------------------------------------------------------------===// // // CFGSimplification - Merge basic blocks, eliminate unreachable blocks, // simplify terminator instructions, etc... // -FunctionPass *createCFGSimplificationPass(); +FunctionPass *createCFGSimplificationPass(int Threshold = -1); //===----------------------------------------------------------------------===// // @@ -387,7 +395,9 @@ FunctionPass *createAddDiscriminatorsPass(); // // SeparateConstOffsetFromGEP - Split GEPs for better CSE // -FunctionPass *createSeparateConstOffsetFromGEPPass(); +FunctionPass * +createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr, + bool LowerGEP = false); //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index bcafda657c2b..19acf5b2db83 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -133,6 +133,11 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, } } +// SplitAllCriticalEdges - Loop over all of the edges in the CFG, +// breaking critical edges as they are found. Pass P must not be NULL. +// Returns the number of broken edges. +unsigned SplitAllCriticalEdges(Function &F, Pass *P); + /// SplitEdge - Split the edge connecting specified block. Pass P must /// not be NULL. BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 1e407fb468e1..6387c166ec71 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -115,20 +115,6 @@ namespace llvm { /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); - - /// SimplifyFortifiedLibCalls - Helper class for folding checked library - /// calls (e.g. __strcpy_chk) into their unchecked counterparts. - class SimplifyFortifiedLibCalls { - protected: - CallInst *CI; - virtual void replaceCall(Value *With) = 0; - virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp, - bool isString) const = 0; - - public: - virtual ~SimplifyFortifiedLibCalls(); - bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI); - }; } #endif diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index bdf50ddf5cc6..6584abe822d8 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -43,6 +43,8 @@ class DataLayout; class Loop; class LoopInfo; class AllocaInst; +class AliasAnalysis; +class AssumptionCacheTracker; /// CloneModule - Return an exact copy of the specified module /// @@ -157,13 +159,18 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, /// InlineFunction call, and records the auxiliary results produced by it. class InlineFunctionInfo { public: - explicit InlineFunctionInfo(CallGraph *cg = nullptr, const DataLayout *DL = nullptr) - : CG(cg), DL(DL) {} + explicit InlineFunctionInfo(CallGraph *cg = nullptr, + const DataLayout *DL = nullptr, + AliasAnalysis *AA = nullptr, + AssumptionCacheTracker *ACT = nullptr) + : CG(cg), DL(DL), AA(AA), ACT(ACT) {} /// CG - If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; const DataLayout *DL; + AliasAnalysis *AA; + AssumptionCacheTracker *ACT; /// StaticAllocas - InlineFunction fills this in with all static allocas that /// get copied into the caller. diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index 6b41e82dac73..3a96d955cac2 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H -#define LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H +#ifndef LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H +#define LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SetVector.h" diff --git a/include/llvm/Transforms/Utils/CtorUtils.h b/include/llvm/Transforms/Utils/CtorUtils.h index 81e7b951c252..63e564dcb87a 100644 --- a/include/llvm/Transforms/Utils/CtorUtils.h +++ b/include/llvm/Transforms/Utils/CtorUtils.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H -#define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H +#ifndef LLVM_TRANSFORMS_UTILS_CTORUTILS_H +#define LLVM_TRANSFORMS_UTILS_CTORUTILS_H #include "llvm/ADT/STLExtras.h" diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index c0c690664a9c..14844117f44f 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -34,12 +34,14 @@ class Value; class Pass; class PHINode; class AllocaInst; +class AssumptionCache; class ConstantExpr; class DataLayout; class TargetLibraryInfo; class TargetTransformInfo; class DIBuilder; class AliasAnalysis; +class DominatorTree; template<typename T> class SmallVectorImpl; @@ -136,7 +138,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); /// the basic block that was pointed to. /// bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, - const DataLayout *TD = nullptr); + unsigned BonusInstThreshold, const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr); /// FlatternCFG - This function is used to flatten a CFG. For /// example, it uses parallel-and and parallel-or mode to collapse @@ -148,7 +151,8 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right /// destination. -bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr); +bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr, + unsigned BonusInstThreshold = 1); /// DemoteRegToStack - This function takes a virtual register computed by an /// Instruction and replaces it with a slot in the stack frame, allocated via @@ -170,12 +174,18 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr); /// and it is more than the alignment of the ultimate object, see if we can /// increase the alignment of the ultimate object, making this check succeed. unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, - const DataLayout *TD = nullptr); + const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// getKnownAlignment - Try to infer an alignment for the specified pointer. static inline unsigned getKnownAlignment(Value *V, - const DataLayout *TD = nullptr) { - return getOrEnforceKnownAlignment(V, 0, TD); + const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr) { + return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT); } /// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the @@ -275,6 +285,11 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, /// Returns true if any basic block was removed. bool removeUnreachableBlocks(Function &F); +/// \brief Combine the metadata of two instructions so that K can replace J +/// +/// Metadata not listed as known via KnownIDs is removed +void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 7e3a74aae93c..f315adc49d15 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -16,6 +16,7 @@ namespace llvm { class AliasAnalysis; +class AssumptionCache; class BasicBlock; class DataLayout; class DominatorTree; @@ -34,7 +35,8 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); /// passed into it. bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr, - const DataLayout *DL = nullptr); + const DataLayout *DL = nullptr, + AssumptionCache *AC = nullptr); /// \brief Put loop into LCSSA form. /// @@ -47,7 +49,8 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, /// If ScalarEvolution is passed in, it will be preserved. /// /// Returns true if any modifications are made to the loop. -bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr); +bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, + ScalarEvolution *SE = nullptr); /// \brief Put a loop nest into LCSSA form. /// @@ -58,7 +61,7 @@ bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr); /// If ScalarEvolution is passed in, it will be preserved. /// /// Returns true if any modifications are made to the loop. -bool formLCSSARecursively(Loop &L, DominatorTree &DT, +bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE = nullptr); } diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 98a19ed426ac..16904f16e369 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -20,7 +20,7 @@ class Module; class Function; class GlobalValue; class GlobalVariable; -template <class PtrType, unsigned SmallSize> class SmallPtrSet; +template <class PtrType> class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. /// This wraps the function in the appropriate structure and stores it along @@ -34,7 +34,7 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority); /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect /// the initializer elements of that global in Set and return the global itself. GlobalVariable *collectUsedGlobalVariables(Module &M, - SmallPtrSet<GlobalValue *, 8> &Set, + SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index c83fedb0e2ca..d0602bf47c92 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -22,6 +22,7 @@ namespace llvm { class AllocaInst; class DominatorTree; class AliasSetTracker; +class AssumptionCache; /// \brief Return true if this alloca is legal for promotion. /// @@ -41,7 +42,8 @@ bool isAllocaPromotable(const AllocaInst *AI); /// If AST is specified, the specified tracker is updated to reflect changes /// made to the IR. void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT, - AliasSetTracker *AST = nullptr); + AliasSetTracker *AST = nullptr, + AssumptionCache *AC = nullptr); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index a2a5f9a45601..d2f096fd1efd 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -15,40 +15,149 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/IRBuilder.h" + namespace llvm { - class Value; - class CallInst; - class DataLayout; - class Instruction; - class TargetLibraryInfo; - class LibCallSimplifierImpl; - - /// LibCallSimplifier - This class implements a collection of optimizations - /// that replace well formed calls to library functions with a more optimal - /// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'. - class LibCallSimplifier { - /// Impl - A pointer to the actual implementation of the library call - /// simplifier. - LibCallSimplifierImpl *Impl; - - public: - LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI, - bool UnsafeFPShrink); - virtual ~LibCallSimplifier(); - - /// optimizeCall - Take the given call instruction and return a more - /// optimal value to replace the instruction with or 0 if a more - /// optimal form can't be found. Note that the returned value may - /// be equal to the instruction being optimized. In this case all - /// other instructions that use the given instruction were modified - /// and the given instruction is dead. - Value *optimizeCall(CallInst *CI); - - /// replaceAllUsesWith - This method is used when the library call - /// simplifier needs to replace instructions other than the library - /// call being modified. - virtual void replaceAllUsesWith(Instruction *I, Value *With) const; - }; +class Value; +class CallInst; +class DataLayout; +class Instruction; +class TargetLibraryInfo; +class BasicBlock; +class Function; + +/// \brief This class implements simplifications for calls to fortified library +/// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to, +/// when possible, replace them with their non-checking counterparts. +/// Other optimizations can also be done, but it's possible to disable them and +/// only simplify needless use of the checking versions (when the object size +/// is unknown) by passing true for OnlyLowerUnknownSize. +class FortifiedLibCallSimplifier { +private: + const DataLayout *DL; + const TargetLibraryInfo *TLI; + bool OnlyLowerUnknownSize; + +public: + FortifiedLibCallSimplifier(const DataLayout *DL, const TargetLibraryInfo *TLI, + bool OnlyLowerUnknownSize = false); + + /// \brief Take the given call instruction and return a more + /// optimal value to replace the instruction with or 0 if a more + /// optimal form can't be found. + /// The call must not be an indirect call. + Value *optimizeCall(CallInst *CI); + +private: + Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCpyChk(CallInst *CI, IRBuilder<> &B); + + /// \brief Checks whether the call \p CI to a fortified libcall is foldable + /// to the non-fortified version. + bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp, + unsigned SizeOp, bool isString); +}; + +/// LibCallSimplifier - This class implements a collection of optimizations +/// that replace well formed calls to library functions with a more optimal +/// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'. +class LibCallSimplifier { +private: + FortifiedLibCallSimplifier FortifiedSimplifier; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + bool UnsafeFPShrink; + +protected: + ~LibCallSimplifier() {} + +public: + LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI); + + /// optimizeCall - Take the given call instruction and return a more + /// optimal value to replace the instruction with or 0 if a more + /// optimal form can't be found. Note that the returned value may + /// be equal to the instruction being optimized. In this case all + /// other instructions that use the given instruction were modified + /// and the given instruction is dead. + /// The call must not be an indirect call. + Value *optimizeCall(CallInst *CI); + + /// replaceAllUsesWith - This method is used when the library call + /// simplifier needs to replace instructions other than the library + /// call being modified. + virtual void replaceAllUsesWith(Instruction *I, Value *With) const; + +private: + // String and Memory Library Call Optimizations + Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrChr(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrRChr(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStpCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrLen(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrPBrk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrTo(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + // Wrapper for all String/Memory Library Call Optimizations + Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B); + + // Math Library Optimizations + Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool CheckRetType); + Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B); + Value *optimizeCos(CallInst *CI, IRBuilder<> &B); + Value *optimizePow(CallInst *CI, IRBuilder<> &B); + Value *optimizeExp2(CallInst *CI, IRBuilder<> &B); + Value *optimizeFabs(CallInst *CI, IRBuilder<> &B); + Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B); + Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B); + + // Integer Library Call Optimizations + Value *optimizeFFS(CallInst *CI, IRBuilder<> &B); + Value *optimizeAbs(CallInst *CI, IRBuilder<> &B); + Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B); + Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B); + Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B); + + // Formatting and IO Library Call Optimizations + Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B, + int StreamArg = -1); + Value *optimizePrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B); + Value *optimizePuts(CallInst *CI, IRBuilder<> &B); + + // Helper methods + Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B); + void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat, + SmallVectorImpl<CallInst *> &SinCalls, + SmallVectorImpl<CallInst *> &CosCalls, + SmallVectorImpl<CallInst *> &SinCosCalls); + void replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls, Value *Res); + Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B); + Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B); + + /// hasFloatVersion - Checks if there is a float version of the specified + /// function by checking for an existing function with name FuncName + f + bool hasFloatVersion(StringRef FuncName); +}; } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h new file mode 100644 index 000000000000..af7937265795 --- /dev/null +++ b/include/llvm/Transforms/Utils/SymbolRewriter.h @@ -0,0 +1,155 @@ +//===-- SymbolRewriter.h - Symbol Rewriting Pass ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the prototypes and definitions related to the Symbol +// Rewriter pass. +// +// The Symbol Rewriter pass takes a set of rewrite descriptors which define +// transformations for symbol names. These can be either single name to name +// trnsformation or more broad regular expression based transformations. +// +// All the functions are re-written at the IR level. The Symbol Rewriter itself +// is exposed as a module level pass. All symbols at the module level are +// iterated. For any matching symbol, the requested transformation is applied, +// updating references to it as well (a la RAUW). The resulting binary will +// only contain the rewritten symbols. +// +// By performing this operation in the compiler, we are able to catch symbols +// that would otherwise not be possible to catch (e.g. inlined symbols). +// +// This makes it possible to cleanly transform symbols without resorting to +// overly-complex macro tricks and the pre-processor. An example of where this +// is useful is the sanitizers where we would like to intercept a well-defined +// set of functions across the module. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H +#define LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Module.h" + +namespace llvm { +class MemoryBuffer; + +namespace yaml { +class KeyValueNode; +class MappingNode; +class ScalarNode; +class Stream; +} + +namespace SymbolRewriter { +/// The basic entity representing a rewrite operation. It serves as the base +/// class for any rewrite descriptor. It has a certain set of specializations +/// which describe a particular rewrite. +/// +/// The RewriteMapParser can be used to parse a mapping file that provides the +/// mapping for rewriting the symbols. The descriptors individually describe +/// whether to rewrite a function, global variable, or global alias. Each of +/// these can be selected either by explicitly providing a name for the ones to +/// be rewritten or providing a (posix compatible) regular expression that will +/// select the symbols to rewrite. This descriptor list is passed to the +/// SymbolRewriter pass. +class RewriteDescriptor : public ilist_node<RewriteDescriptor> { + RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + + const RewriteDescriptor & + operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + +public: + enum class Type { + Invalid, /// invalid + Function, /// function - descriptor rewrites a function + GlobalVariable, /// global variable - descriptor rewrites a global variable + NamedAlias, /// named alias - descriptor rewrites a global alias + }; + + virtual ~RewriteDescriptor() {} + + Type getType() const { return Kind; } + + virtual bool performOnModule(Module &M) = 0; + +protected: + explicit RewriteDescriptor(Type T) : Kind(T) {} + +private: + const Type Kind; +}; + +typedef iplist<RewriteDescriptor> RewriteDescriptorList; + +class RewriteMapParser { +public: + RewriteMapParser() {} + ~RewriteMapParser() {} + + bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors); + +private: + bool parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL); + bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry, + RewriteDescriptorList *DL); + bool parseRewriteFunctionDescriptor(yaml::Stream &Stream, + yaml::ScalarNode *Key, + yaml::MappingNode *Value, + RewriteDescriptorList *DL); + bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream, + yaml::ScalarNode *Key, + yaml::MappingNode *Value, + RewriteDescriptorList *DL); + bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, + yaml::MappingNode *V, + RewriteDescriptorList *DL); +}; +} + +template <> +struct ilist_traits<SymbolRewriter::RewriteDescriptor> + : public ilist_default_traits<SymbolRewriter::RewriteDescriptor> { + mutable ilist_half_node<SymbolRewriter::RewriteDescriptor> Sentinel; + +public: + // createSentinel is used to get a reference to a node marking the end of + // the list. Because the sentinel is relative to this instance, use a + // non-static method. + SymbolRewriter::RewriteDescriptor *createSentinel() const { + // since i[p] lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment the + // i[p]list. Since the NodeTy is expected to publicly derive from + // ilist_node<NodeTy>, there is a legal viable downcast from it to + // NodeTy. We use this trick to superpose i[p]list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node<NodeTy>) so no one will ever notice + // the superposition. + return static_cast<SymbolRewriter::RewriteDescriptor *>(&Sentinel); + } + void destroySentinel(SymbolRewriter::RewriteDescriptor *) {} + + SymbolRewriter::RewriteDescriptor *provideInitialHead() const { + return createSentinel(); + } + + SymbolRewriter::RewriteDescriptor * + ensureHead(SymbolRewriter::RewriteDescriptor *&) const { + return createSentinel(); + } + + static void noteHead(SymbolRewriter::RewriteDescriptor *, + SymbolRewriter::RewriteDescriptor *) {} +}; + +ModulePass *createRewriteSymbolsPass(); +ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &); +} + +#endif diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 7ac2572f9af3..550292f6b7a3 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H -#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H +#ifndef LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H +#define LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H #include "llvm/Pass.h" diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index aaadd7d48bdc..807367cd4b12 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -18,6 +18,7 @@ namespace llvm { +class AssumptionCache; class Loop; class LoopInfo; class LPPassManager; @@ -25,7 +26,7 @@ class Pass; bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime, unsigned TripMultiple, LoopInfo *LI, Pass *PP, - LPPassManager *LPM); + LPPassManager *LPM, AssumptionCache *AC); bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, LPPassManager* LPM); diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index 5774763575d3..047ab818711b 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -71,20 +71,23 @@ namespace llvm { ValueMapTypeRemapper *TypeMapper = nullptr, ValueMaterializer *Materializer = nullptr); + Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); + + /// MapMetadata - provide versions that preserve type safety for MDNodes. + MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); + void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = nullptr, ValueMaterializer *Materializer = nullptr); - /// MapValue - provide versions that preserve type safety for MDNode and - /// Constants. - inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM, - RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = nullptr, - ValueMaterializer *Materializer = nullptr) { - return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper, - Materializer)); - } + /// MapValue - provide versions that preserve type safety for Constants. inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = nullptr, diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h index 44a7149eee98..b47acf517b37 100644 --- a/include/llvm/Transforms/Utils/VectorUtils.h +++ b/include/llvm/Transforms/Utils/VectorUtils.h @@ -14,8 +14,8 @@ #ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H #define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H -#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Target/TargetLibraryInfo.h" namespace llvm { @@ -36,6 +36,8 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) { case Intrinsic::log10: case Intrinsic::log2: case Intrinsic::fabs: + case Intrinsic::minnum: + case Intrinsic::maxnum: case Intrinsic::copysign: case Intrinsic::floor: case Intrinsic::ceil: @@ -99,7 +101,7 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) { if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) { Intrinsic::ID ID = II->getIntrinsicID(); if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start || - ID == Intrinsic::lifetime_end) + ID == Intrinsic::lifetime_end || ID == Intrinsic::assume) return ID; else return Intrinsic::not_intrinsic; @@ -153,6 +155,14 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) { case LibFunc::fabsf: case LibFunc::fabsl: return checkUnaryFloatSignature(*CI, Intrinsic::fabs); + case LibFunc::fmin: + case LibFunc::fminf: + case LibFunc::fminl: + return checkBinaryFloatSignature(*CI, Intrinsic::minnum); + case LibFunc::fmax: + case LibFunc::fmaxf: + case LibFunc::fmaxl: + return checkBinaryFloatSignature(*CI, Intrinsic::maxnum); case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap index 1790a7242e5b..61f65510c4ea 100644 --- a/include/llvm/module.modulemap +++ b/include/llvm/module.modulemap @@ -75,8 +75,9 @@ module LLVM_IR { exclude header "IR/PassManager.h" exclude header "IR/LegacyPassManager.h" - // Exclude this; it's intended for (repeated) textual inclusion. - exclude header "IR/Instruction.def" + // These are intended for (repeated) textual inclusion. + textual header "IR/Instruction.def" + textual header "IR/Metadata.def" } module LLVM_LegacyPassManager { @@ -112,7 +113,12 @@ module LLVM_MC { exclude header "MC/MCTargetOptionsCommandFlags.h" } -module LLVM_Object { requires cplusplus umbrella "Object" module * { export * } } +module LLVM_Object { + requires cplusplus + umbrella "Object" + module * { export * } +} + module LLVM_Option { requires cplusplus umbrella "Option" module * { export * } } module LLVM_TableGen { requires cplusplus umbrella "TableGen" module * { export * } } @@ -148,9 +154,6 @@ module LLVM_Utils { exclude header "Support/AIXDataTypesFix.h" // Exclude this; it's fundamentally non-modular. - exclude header "Support/Debug.h" - - // Exclude this; it's fundamentally non-modular. exclude header "Support/PluginLoader.h" // Exclude this; it's a weirdly-factored part of llvm-gcov and conflicts @@ -159,6 +162,18 @@ module LLVM_Utils { // FIXME: Mislayered? exclude header "Support/TargetRegistry.h" + + // These are intended for textual inclusion. + textual header "Support/ELFRelocs/AArch64.def" + textual header "Support/ELFRelocs/ARM.def" + textual header "Support/ELFRelocs/Hexagon.def" + textual header "Support/ELFRelocs/i386.def" + textual header "Support/ELFRelocs/Mips.def" + textual header "Support/ELFRelocs/PowerPC64.def" + textual header "Support/ELFRelocs/PowerPC.def" + textual header "Support/ELFRelocs/Sparc.def" + textual header "Support/ELFRelocs/SystemZ.def" + textual header "Support/ELFRelocs/x86_64.def" } } |