mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Merge llvm 3.6.0rc1 from ^/vendor/llvm/dist, merge clang 3.6.0rc1 from
^/vendor/clang/dist, resolve conflicts, and cleanup patches.
This commit is contained in:
commit
39d628a0c7
2609 changed files with 202653 additions and 110829 deletions
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
@ -1377,6 +1382,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.
|
||||
*
|
||||
|
|
@ -1537,6 +1549,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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
@ -1569,6 +1589,20 @@ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str,
|
|||
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.
|
||||
*
|
||||
|
|
@ -1606,6 +1640,13 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
|
|||
LLVMValueRef *ConstantVals,
|
||||
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.
|
||||
*
|
||||
|
|
@ -2376,6 +2417,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
|
||||
*
|
||||
|
|
@ -2436,6 +2497,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.
|
||||
*
|
||||
|
|
@ -2445,6 +2563,10 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
|
|||
*/
|
||||
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCCoreValueInstructionPHINode PHI Nodes
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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,13 +186,27 @@ 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,
|
||||
LLVMOpInfoCallback GetOpInfo,
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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)(
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -177,6 +177,35 @@ extern lto_module_t
|
|||
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,11 +353,26 @@ 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -175,6 +203,47 @@ namespace llvm {
|
|||
return std::vector<T>(Data, Data+Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @{
|
||||
/// @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;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
size_type size() const { return Vector.size(); }
|
||||
|
||||
iterator begin() {
|
||||
return Vector.begin();
|
||||
}
|
||||
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 begin() const {
|
||||
return Vector.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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*>();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#ifndef LLVM_ADT_ITERATOR_H
|
||||
#define LLVM_ADT_ITERATOR_H
|
||||
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
142
contrib/llvm/include/llvm/Analysis/AssumptionCache.h
Normal file
142
contrib/llvm/include/llvm/Analysis/AssumptionCache.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
/// \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;
|
||||
|
||||
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 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
//===-------------------------------------
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,13 @@ namespace llvm {
|
|||
//
|
||||
ImmutablePass *createBasicAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createCFLAliasAnalysisPass - This pass implements a set-based approach to
|
||||
// alias analysis.
|
||||
//
|
||||
ImmutablePass *createCFLAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
/// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows
|
||||
|
|
@ -86,6 +93,13 @@ namespace llvm {
|
|||
//
|
||||
ImmutablePass *createTypeBasedAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createScopedNoAliasAAPass - This pass implements metadata-based
|
||||
// scoped noalias analysis.
|
||||
//
|
||||
ImmutablePass *createScopedNoAliasAAPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based
|
||||
|
|
@ -93,6 +107,8 @@ namespace llvm {
|
|||
//
|
||||
ImmutablePass *createObjCARCAliasAnalysisPass();
|
||||
|
||||
FunctionPass *createPAEvalPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
/// createLazyValueInfoPass - This creates an instance of the LazyValueInfo
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
// Only RefCountedBase is allowed to delete.
|
||||
friend class RefCountedBase<BitCodeAbbrev>;
|
||||
|
||||
public:
|
||||
BitCodeAbbrev() : RefCount(1) {}
|
||||
|
||||
void addRef() { ++RefCount; }
|
||||
void dropRef() { if (--RefCount == 0) delete this; }
|
||||
|
||||
unsigned getNumOperandInfos() const {
|
||||
return static_cast<unsigned>(OperandList.size());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
|
||||
|
||||
void init(BitstreamReader *R) {
|
||||
freeState();
|
||||
|
||||
BitStream = R;
|
||||
NextChar = 0;
|
||||
CurWord = 0;
|
||||
Size = 0;
|
||||
BitsInCurWord = 0;
|
||||
CurCodeSize = 2;
|
||||
}
|
||||
|
||||
void init(BitstreamReader &R) {
|
||||
freeState();
|
||||
|
||||
BitStream = &R;
|
||||
NextChar = 0;
|
||||
CurWord = 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,75 +308,72 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
uint32_t Read(unsigned NumBits) {
|
||||
assert(NumBits && NumBits <= 32 &&
|
||||
"Cannot return zero or more than 32 bits!");
|
||||
|
||||
// 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;
|
||||
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);
|
||||
void fillCurWord() {
|
||||
assert(Size == 0 || NextChar < (unsigned)Size);
|
||||
|
||||
// Read the next word from the stream.
|
||||
uint8_t Array[sizeof(word_t)] = {0};
|
||||
|
||||
BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array);
|
||||
uint64_t BytesRead =
|
||||
BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
|
||||
|
||||
// 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 (BytesRead == 0) {
|
||||
Size = NextChar;
|
||||
return;
|
||||
}
|
||||
|
||||
CurWord = EndianValue;
|
||||
|
||||
NextChar += sizeof(word_t);
|
||||
|
||||
// Extract NumBits-BitsInCurWord from what we just read.
|
||||
unsigned BitsLeft = NumBits-BitsInCurWord;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
CurWord =
|
||||
support::endian::read<word_t, support::little, support::unaligned>(
|
||||
Array);
|
||||
NextChar += BytesRead;
|
||||
BitsInCurWord = BytesRead * 8;
|
||||
}
|
||||
|
||||
uint64_t Read64(unsigned NumBits) {
|
||||
if (NumBits <= 32) return Read(NumBits);
|
||||
word_t Read(unsigned NumBits) {
|
||||
static const unsigned BitsInWord = sizeof(word_t) * 8;
|
||||
|
||||
uint64_t V = Read(32);
|
||||
return V | (uint64_t)Read(NumBits-32) << 32;
|
||||
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) {
|
||||
word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));
|
||||
|
||||
// Use a mask to avoid undefined behavior.
|
||||
CurWord >>= (NumBits & Mask);
|
||||
|
||||
BitsInCurWord -= NumBits;
|
||||
return R;
|
||||
}
|
||||
|
||||
word_t R = BitsInCurWord ? CurWord : 0;
|
||||
unsigned BitsLeft = NumBits - BitsInCurWord;
|
||||
|
||||
fillCurWord();
|
||||
|
||||
// If we run out of data, stop at the end of the stream.
|
||||
if (BitsLeft > BitsInCurWord)
|
||||
return 0;
|
||||
|
||||
word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
|
||||
|
||||
// Use a mask to avoid undefined behavior.
|
||||
CurWord >>= (BitsLeft & Mask);
|
||||
|
||||
BitsInCurWord -= BitsLeft;
|
||||
|
||||
R |= R2 << (NumBits - BitsLeft);
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
uint32_t ReadVBR(unsigned NumBits) {
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
/// 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);
|
||||
|
||||
/// 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);
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
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
|
||||
// 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.
|
||||
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
|
||||
// extended with undefined upper bits when retrieved.
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
@ -82,11 +92,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
|
|||
"Emit nothing, for performance testing"),
|
||||
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"),
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CODEGEN_ASMPRINTER_DIE_H__
|
||||
#define CODEGEN_ASMPRINTER_DIE_H__
|
||||
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
|
||||
#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
|
@ -381,10 +381,10 @@ public:
|
|||
///
|
||||
class DIEString : public DIEValue {
|
||||
const DIEValue *Access;
|
||||
const StringRef Str;
|
||||
StringRef Str;
|
||||
|
||||
public:
|
||||
DIEString(const DIEValue *Acc, const StringRef S)
|
||||
DIEString(const DIEValue *Acc, StringRef S)
|
||||
: DIEValue(isString), Access(Acc), Str(S) {}
|
||||
|
||||
/// getString - Grab the string out of the object.
|
||||
|
|
@ -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;
|
||||
NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
|
||||
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);
|
||||
explicit FastISel(FunctionLoweringInfo &FuncInfo,
|
||||
const TargetLibraryInfo *LibInfo,
|
||||
bool SkipTargetIndependentISel = false);
|
||||
|
||||
/// 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 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
|
||||
/// \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);
|
||||
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.
|
||||
///
|
||||
/// \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);
|
||||
/// \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);
|
||||
|
||||
/// 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 two 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);
|
||||
unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
|
||||
const TargetRegisterClass *RC, unsigned Op0,
|
||||
bool Op0IsKill, unsigned Op1, bool Op1IsKill);
|
||||
|
||||
/// 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
|
||||
/// \brief Emit a MachineInstr with three 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_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_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);
|
||||
/// \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);
|
||||
|
||||
/// 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 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 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);
|
||||
CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const;
|
||||
|
||||
bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs);
|
||||
bool lowerCallTo(CallLoweringInfo &CLI);
|
||||
|
||||
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 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:
|
||||
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 LowerCall(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);
|
||||
|
||||
/// \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);
|
||||
|
||||
/// 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 materializeRegForValue to materialize a constant in a
|
||||
/// target-independent way.
|
||||
unsigned materializeConstant(const Value *V, MVT VT);
|
||||
|
||||
/// \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
|
||||
|
|
|
|||
122
contrib/llvm/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
Normal file
122
contrib/llvm/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
/// needsSafePoitns - True if safe points of any kind are required. By
|
||||
// default, none are recorded.
|
||||
/// Returns true if this strategy is expecting the use of gc.statepoints,
|
||||
/// and false otherwise.
|
||||
bool useStatepoints() const { return UseStatepoints; }
|
||||
|
||||
/** @name Statepoint Specific Properties */
|
||||
///@{
|
||||
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ namespace llvm {
|
|||
/// Creates a shadow stack garbage collector. This collector requires no code
|
||||
/// generator support.
|
||||
void linkShadowStackGC();
|
||||
|
||||
void linkStatepointExampleGC();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue