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:
Dimitry Andric 2015-01-25 23:36:55 +00:00
commit 39d628a0c7
2609 changed files with 202653 additions and 110829 deletions

View file

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

View file

@ -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);
/**
* @}
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
}
/// @}
};

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
}

View file

@ -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);
}

View file

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

View file

@ -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);
}

View file

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

View file

@ -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);
}

View file

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

View file

@ -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) {}

View file

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

View file

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

View file

@ -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);
}

View file

@ -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'));
}
};
}

View file

@ -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*>();

View file

@ -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.
/// @{

View file

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

View file

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

View file

@ -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); }
};

View file

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

View file

@ -10,8 +10,8 @@
#ifndef LLVM_ADT_ITERATOR_H
#define LLVM_ADT_ITERATOR_H
#include <iterator>
#include <cstddef>
#include <iterator>
namespace llvm {

View file

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

View file

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

View file

@ -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);
};

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
};
}

View file

@ -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!";

View file

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

View file

@ -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
};
//===-------------------------------------

View file

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

View file

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

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

@ -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"; }
};

View file

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

View file

@ -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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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());
}

View file

@ -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"; }
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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();

View file

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

View file

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

View 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

View file

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

View file

@ -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);
};

View file

@ -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();
};

View file

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

View file

@ -36,6 +36,8 @@ namespace llvm {
/// Creates a shadow stack garbage collector. This collector requires no code
/// generator support.
void linkShadowStackGC();
void linkStatepointExampleGC();
}
#endif

View file

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

View file

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